From ffdecf1795cb5435b6bac157d6d93119eb826d56 Mon Sep 17 00:00:00 2001 From: Machac Date: Wed, 6 Dec 2023 12:14:58 +0100 Subject: [PATCH 01/10] Change Gradle to Maven change groovy test to Java change anf fix Checkin rename package --- .gitignore | 44 +++- .travis.yml | 18 -- CONTRIBUTING.md | 29 --- build.gradle | 178 --------------- gradle.properties | 3 - gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 6 - gradlew | 185 --------------- gradlew.bat | 104 --------- pom.xml | 173 +++++++++++++++ .../quartz/mongodb/Constants.java | 2 +- .../mongodb/DynamicMongoDBJobStore.java | 4 +- .../quartz/mongodb/JobCompleteHandler.java | 8 +- .../quartz/mongodb/JobConverter.java | 6 +- .../quartz/mongodb/JobDataConverter.java | 4 +- .../quartz/mongodb/LockManager.java | 6 +- .../quartz/mongodb/MongoDBJobStore.java | 50 ++--- .../quartz/mongodb/MongoStoreAssembler.java | 22 +- .../mongodb/TriggerAndJobPersister.java | 10 +- .../quartz/mongodb/TriggerRunner.java | 16 +- .../quartz/mongodb/TriggerStateManager.java | 18 +- .../clojure/DynamicClassLoadHelper.java | 2 +- .../mongodb/cluster/CheckinExecutor.java | 2 +- .../quartz/mongodb/cluster/CheckinTask.java | 58 +++++ .../mongodb/cluster/KamikazeErrorHandler.java | 2 +- .../mongodb/cluster/NoOpErrorHandler.java | 2 +- .../cluster/RecoveryTriggerFactory.java | 5 +- .../quartz/mongodb/cluster/Scheduler.java | 2 +- .../mongodb/cluster/TriggerRecoverer.java | 14 +- .../quartz/mongodb/dao/CalendarDao.java | 13 +- .../quartz/mongodb/dao/JobDao.java | 14 +- .../quartz/mongodb/dao/LocksDao.java | 9 +- .../mongodb/dao/PausedJobGroupsDao.java | 4 +- .../mongodb/dao/PausedTriggerGroupsDao.java | 4 +- .../quartz/mongodb/dao/SchedulerDao.java | 13 +- .../quartz/mongodb/dao/TriggerDao.java | 21 +- .../mongodb/db/ExternalMongoConnector.java | 11 +- .../mongodb/db/InternalMongoConnector.java | 2 +- .../quartz/mongodb/db/MongoConnector.java | 2 +- .../mongodb/db/MongoConnectorBuilder.java | 9 +- .../quartz/mongodb/db/SSLContextFactory.java | 15 +- .../mongodb/trigger/MisfireHandler.java | 4 +- .../mongodb/trigger/TriggerConverter.java | 13 +- .../trigger/TriggerPropertiesConverter.java | 10 +- ...darIntervalTriggerPropertiesConverter.java | 4 +- .../CronTriggerPropertiesConverter.java | 4 +- ...imeIntervalTriggerPropertiesConverter.java | 7 +- .../SimpleTriggerPropertiesConverter.java | 4 +- .../quartz/mongodb/util/Clock.java | 2 +- .../quartz/mongodb/util/ExpiryCalculator.java | 10 +- .../quartz/mongodb/util/GroupHelper.java | 9 +- .../quartz/mongodb/util/Keys.java | 4 +- .../quartz/mongodb/util/QueryHelper.java | 14 +- .../quartz/mongodb/util/SerialUtils.java | 2 +- .../mongodb/util/TriggerGroupHelper.java | 4 +- .../quartz/mongodb/cluster/CheckinTask.java | 38 ---- .../quartz/mongodb/Clocks.groovy | 4 +- .../quartz/mongodb/FailoverTest.groovy | 4 +- .../mongodb/JobDataConverterTest.groovy | 2 +- .../quartz/mongodb/LoadBalancingTest.groovy | 2 +- .../quartz/mongodb/LockManagerTest.groovy | 6 +- .../quartz/mongodb/MongoHelper.groovy | 2 +- .../quartz/mongodb/QuartzHelper.groovy | 2 +- .../mongodb/TriggerStateManagerTest.groovy | 12 +- .../mongodb/cluster/CheckinTaskTest.groovy | 4 +- .../mongodb/cluster/SchedulerTest.groovy | 2 +- .../quartz/mongodb/dao/CalendarDaoTest.groovy | 8 +- .../quartz/mongodb/dao/LocksDaoTest.groovy | 10 +- .../mongodb/dao/SchedulerDaoTest.groovy | 8 +- .../quartz/mongodb/dao/TriggerDaoTest.groovy | 16 +- .../trigger/TriggerConverterTest.groovy | 13 +- .../mongodb/util/ExpiryCalculatorTest.groovy | 10 +- src/test/groovy/it/MongoDBJobStoreTest.groovy | 9 +- .../it/QuartzWithMongoDbStoreTest.groovy | 6 +- .../com/netgrif/mongo/quartz/DeadJob.java | 61 +++++ .../netgrif/mongo/quartz/FailoverTest.java | 209 +++++++++++++++++ .../mongo/quartz/JobDataConverterTest.java | 210 ++++++++++++++++++ .../mongo/quartz/LoadBalancingTest.java | 66 ++++++ .../netgrif/mongo/quartz/LockManagerTest.java | 92 ++++++++ .../com/netgrif/mongo/quartz/MongoHelper.java | 107 +++++++++ .../netgrif/mongo/quartz/QuartzHelper.java | 95 ++++++++ .../mongo/quartz/TriggerStateManagerTest.java | 87 ++++++++ .../mongo/quartz/cluster/CheckinTaskTest.java | 4 + .../mongo/quartz/cluster/SchedulerTest.java | 4 + 84 files changed, 1443 insertions(+), 831 deletions(-) mode change 100755 => 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 CONTRIBUTING.md delete mode 100644 build.gradle delete mode 100644 gradle.properties delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100755 gradlew delete mode 100644 gradlew.bat create mode 100644 pom.xml rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/Constants.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/DynamicMongoDBJobStore.java (83%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/JobCompleteHandler.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/JobConverter.java (96%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/JobDataConverter.java (97%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/LockManager.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/MongoDBJobStore.java (93%) rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/MongoStoreAssembler.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/TriggerAndJobPersister.java (96%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/TriggerRunner.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/TriggerStateManager.java (92%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/clojure/DynamicClassLoadHelper.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/cluster/CheckinExecutor.java (96%) mode change 100644 => 100755 create mode 100755 src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/cluster/KamikazeErrorHandler.java (90%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/cluster/NoOpErrorHandler.java (68%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/cluster/RecoveryTriggerFactory.java (97%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/cluster/Scheduler.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/cluster/TriggerRecoverer.java (91%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/CalendarDao.java (96%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/JobDao.java (91%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/LocksDao.java (96%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/PausedJobGroupsDao.java (91%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/PausedTriggerGroupsDao.java (91%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/SchedulerDao.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/dao/TriggerDao.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/db/ExternalMongoConnector.java (85%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/db/InternalMongoConnector.java (99%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/db/MongoConnector.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/db/MongoConnectorBuilder.java (99%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/db/SSLContextFactory.java (98%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/MisfireHandler.java (96%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/TriggerConverter.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/TriggerPropertiesConverter.java (75%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java (92%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java (95%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/Clock.java (93%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/ExpiryCalculator.java (88%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/GroupHelper.java (79%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/Keys.java (97%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/QueryHelper.java (58%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/SerialUtils.java (98%) mode change 100644 => 100755 rename src/main/java/com/{novemberain => netgrif}/quartz/mongodb/util/TriggerGroupHelper.java (88%) mode change 100644 => 100755 delete mode 100644 src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinTask.java rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/Clocks.groovy (85%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/FailoverTest.groovy (99%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/JobDataConverterTest.groovy (99%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/LoadBalancingTest.groovy (97%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/LockManagerTest.groovy (93%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/MongoHelper.groovy (98%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/QuartzHelper.groovy (98%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/TriggerStateManagerTest.groovy (83%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/cluster/CheckinTaskTest.groovy (88%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/cluster/SchedulerTest.groovy (95%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/dao/CalendarDaoTest.groovy (87%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/dao/LocksDaoTest.groovy (94%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/dao/SchedulerDaoTest.groovy (96%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/dao/TriggerDaoTest.groovy (83%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/trigger/TriggerConverterTest.groovy (90%) rename src/test/groovy/com/{novemberain => netgrif}/quartz/mongodb/util/ExpiryCalculatorTest.groovy (92%) create mode 100644 src/test/java/com/netgrif/mongo/quartz/DeadJob.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/FailoverTest.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/JobDataConverterTest.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/LoadBalancingTest.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/LockManagerTest.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/MongoHelper.java create mode 100755 src/test/java/com/netgrif/mongo/quartz/QuartzHelper.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/TriggerStateManagerTest.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java create mode 100644 src/test/java/com/netgrif/mongo/quartz/cluster/SchedulerTest.java diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 index d8dab78e..3761db16 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,17 @@ -/build -/.gradle -/.settings -/.classpath -/.project -/.idea +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/ +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws *.iml +*.ipr /out lib/* *# @@ -13,3 +20,28 @@ lib/* src/legacytest/* checkouts/* bin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 62f70d8c..00000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -dist: bionic -sudo: false - -language: java -jdk: - - oraclejdk13 - - openjdk13 - -services: - - mongodb - -install: ./gradlew assemble - -cache: - directories: - - $HOME/.gradle - -script: ./gradlew check --info --stacktrace diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 623c6c87..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,29 +0,0 @@ -# Contributing - -This project uses a very minimalistic approach to contributions: - - * Fork it - * Create a branch - * Make your changes - * Commit it with an explanation of [*why* this change is necessary](https://chris.beams.io/posts/git-commit/#why-not-how) - * Make sure all tests pass - * Submit a pull request - * Be patient - -## Prerequisites - -This project uses Gradle 6.x. A [compatible JDK version](https://docs.gradle.org/current/userguide/compatibility.html#java) is therefore required. - -## Running Tests - -To start a local MongoDB node before running tests, use - -``` shell -./gradlew startMongoDb -``` - -Then run the tests: - -``` shell -./gradlew check -``` diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 0f8b763b..00000000 --- a/build.gradle +++ /dev/null @@ -1,178 +0,0 @@ -buildscript { - repositories { - mavenCentral() - jcenter() - } -} - -plugins { - id 'net.researchgate.release' version '2.8.1' - id "com.jfrog.bintray" version "1.8.5" - id 'com.sourcemuse.mongo' version '1.0.7' -} - -allprojects { - repositories { - jcenter() - } - apply plugin: 'maven-publish' - apply plugin: 'java' -} - -apply plugin: 'eclipse' -apply plugin: 'groovy' -apply plugin: 'idea' -apply plugin: 'com.sourcemuse.mongo' - -archivesBaseName = 'quartz-mongodb' - -jar { - archiveVersion = projectVersion -} - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -configurations { - provided - implementation.extendsFrom provided -} -sourceSets { - main { compileClasspath += configurations.provided } -} - -idea { - module { - scopes.PROVIDED.plus += [configurations.provided] - downloadJavadoc = true - downloadSources = true - } -} - -eclipse { - classpath { - downloadSources true - downloadJavadoc true - } - jdt { - sourceCompatibility java.sourceCompatibility - targetCompatibility java.targetCompatibility - } -} - -dependencies { - implementation("org.quartz-scheduler:quartz:2.3.2") - implementation("org.mongodb:mongodb-driver-sync:4.7.1") - implementation("commons-codec:commons-codec:1.10") - implementation("org.apache.commons:commons-lang3:3.8") - implementation("org.apache.httpcomponents:httpcore:4.4.10") - implementation("org.slf4j:slf4j-api:1.7.21") - - compileOnly("org.clojure:clojure:1.10.0") - - testImplementation("org.clojure:clojure:1.10.0") - testImplementation("joda-time:joda-time:2.8.2") - testImplementation("org.slf4j:slf4j-simple:1.7.10") - testImplementation("org.codehaus.groovy:groovy-all:2.5.12") - testImplementation("org.spockframework:spock-core:1.3-groovy-2.5") - testRuntimeOnly("cglib:cglib-nodep:3.1") - testRuntimeOnly("org.objenesis:objenesis:2.1") -} - -release { - scmAdapters = [net.researchgate.release.GitAdapter] - git { - pushToRemote = 'origin' - } - - versionPropertyFile = 'gradle.properties' -} - -task sourceJar(type: Jar) { - dependsOn classes - classifier "sources" - from sourceSets.main.allSource -} - -task javadocJar(type: Jar) { - classifier 'javadoc' - from javadoc -} - -tasks.withType(Javadoc) { - options.addStringOption('Xdoclint:none', '-quiet') -} - -artifacts { - archives sourceJar - archives javadocJar -} - -publishing { - publications { - quartzMongoDB(MavenPublication) { - groupId = 'com.novemberain' - artifactId = archivesBaseName - version = projectVersion - - artifact sourceJar { - classifier "sources" - } - - from components.java - } - } -} - -mongo { - port 27017 - logging 'console' - journalingEnabled true -} - -test { - beforeTest { descriptor -> - logger.lifecycle("Running test \"${descriptor}\"") - } -} - -// force test runs even when there are no test changes, -// such test loops are very useful for testing race conditions -// and other concurrency hazards -test.outputs.upToDateWhen { false } - -tasks.withType(Test){ - runWithMongoDb = true - mongo { - journalingEnabled true - port 27017 - logging 'console' - mongoVersion 'PRODUCTION' - } -} - -bintray { - user = System.getenv("BINTRAY_USERNAME") - key = System.getenv("BINTRAY_API_KEY") - publications = ['quartzMongoDB'] - pkg { - repo = 'maven' - name = 'quartz-mongodb' - labels = ['quartz', 'mongodb'] - userOrg = 'michaelklishin' - licenses = ['Apache-2.0'] - vcsUrl = 'https://github.com/michaelklishin/quartz-mongodb.git' - - version { - name = projectVersion - desc = 'MongoDB-backed job store for the Quartz scheduler' - vcsTag = projectVersion - } - } -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 465b4750..00000000 --- a/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -projectVersion=2.2.0-SNAPSHOT -org.gradle.caching = true -org.gradle.vfs.watch = true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 62d4c053550b91381bbd28b1afc82d634bf73a8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58910 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 766af62f..00000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Jul 14 22:34:43 MSK 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStorePath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew deleted file mode 100755 index fbd7c515..00000000 --- a/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 5093609d..00000000 --- a/gradlew.bat +++ /dev/null @@ -1,104 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..29332136 --- /dev/null +++ b/pom.xml @@ -0,0 +1,173 @@ + + + 4.0.0 + + com.netgrif.quartz + quartz-mongodb-connector + 1.0.0-SNAPSHOT + + + 11 + 11 + UTF-8 + + + + + org.quartz-scheduler + quartz + 2.3.2 + + + + org.mongodb + mongodb-driver-sync + 4.7.1 + + + + commons-codec + commons-codec + 1.10 + + + + org.apache.commons + commons-lang3 + 3.8 + + + + org.apache.httpcomponents + httpcore + 4.4.10 + + + + org.slf4j + slf4j-api + 1.7.21 + + + + org.clojure + clojure + 1.10.0 + + + + + joda-time + joda-time + 2.8.2 + test + + + + org.slf4j + slf4j-simple + 1.7.10 + test + + + + org.codehaus.groovy + groovy-all + 2.5.11 + test + pom + + + + org.spockframework + spock-core + 1.3-groovy-2.5 + test + + + + cglib + cglib-nodep + 3.1 + test + + + + org.objenesis + objenesis + 2.1 + test + + + + + org.junit.jupiter + junit-jupiter-api + 5.9.2 + test + + + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + test + + + + + org.junit.jupiter + junit-jupiter-params + 5.9.2 + test + + + + joda-time + joda-time + 2.12.5 + test + + + + + org.mockito + mockito-core + 4.1.0 + test + + + + + org.mockito + mockito-junit-jupiter + 4.1.0 + test + + + + org.projectlombok + lombok + 1.18.28 + test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + false + + + + + + diff --git a/src/main/java/com/novemberain/quartz/mongodb/Constants.java b/src/main/java/com/netgrif/quartz/mongodb/Constants.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/Constants.java rename to src/main/java/com/netgrif/quartz/mongodb/Constants.java index 55b32645..13d87d8f --- a/src/main/java/com/novemberain/quartz/mongodb/Constants.java +++ b/src/main/java/com/netgrif/quartz/mongodb/Constants.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; public interface Constants { diff --git a/src/main/java/com/novemberain/quartz/mongodb/DynamicMongoDBJobStore.java b/src/main/java/com/netgrif/quartz/mongodb/DynamicMongoDBJobStore.java old mode 100644 new mode 100755 similarity index 83% rename from src/main/java/com/novemberain/quartz/mongodb/DynamicMongoDBJobStore.java rename to src/main/java/com/netgrif/quartz/mongodb/DynamicMongoDBJobStore.java index 411470e6..3e392089 --- a/src/main/java/com/novemberain/quartz/mongodb/DynamicMongoDBJobStore.java +++ b/src/main/java/com/netgrif/quartz/mongodb/DynamicMongoDBJobStore.java @@ -1,7 +1,7 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; import com.mongodb.client.MongoClient; -import com.novemberain.quartz.mongodb.clojure.DynamicClassLoadHelper; +import com.netgrif.quartz.mongodb.clojure.DynamicClassLoadHelper; import org.quartz.spi.ClassLoadHelper; public class DynamicMongoDBJobStore extends MongoDBJobStore { diff --git a/src/main/java/com/novemberain/quartz/mongodb/JobCompleteHandler.java b/src/main/java/com/netgrif/quartz/mongodb/JobCompleteHandler.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/JobCompleteHandler.java rename to src/main/java/com/netgrif/quartz/mongodb/JobCompleteHandler.java index 9593578f..01bddefb --- a/src/main/java/com/novemberain/quartz/mongodb/JobCompleteHandler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/JobCompleteHandler.java @@ -1,8 +1,8 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; -import com.novemberain.quartz.mongodb.dao.JobDao; -import com.novemberain.quartz.mongodb.dao.LocksDao; -import com.novemberain.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.dao.JobDao; +import com.netgrif.quartz.mongodb.dao.LocksDao; +import com.netgrif.quartz.mongodb.dao.TriggerDao; import org.quartz.JobDetail; import org.quartz.JobPersistenceException; import org.quartz.Trigger.CompletedExecutionInstruction; diff --git a/src/main/java/com/novemberain/quartz/mongodb/JobConverter.java b/src/main/java/com/netgrif/quartz/mongodb/JobConverter.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/com/novemberain/quartz/mongodb/JobConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/JobConverter.java index b27fa776..99924999 --- a/src/main/java/com/novemberain/quartz/mongodb/JobConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/JobConverter.java @@ -1,11 +1,11 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; import org.bson.Document; import org.quartz.*; import org.quartz.spi.ClassLoadHelper; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_NAME; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_NAME; public class JobConverter { diff --git a/src/main/java/com/novemberain/quartz/mongodb/JobDataConverter.java b/src/main/java/com/netgrif/quartz/mongodb/JobDataConverter.java old mode 100644 new mode 100755 similarity index 97% rename from src/main/java/com/novemberain/quartz/mongodb/JobDataConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/JobDataConverter.java index 1c56fb65..6437a57e --- a/src/main/java/com/novemberain/quartz/mongodb/JobDataConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/JobDataConverter.java @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; -import com.novemberain.quartz.mongodb.util.SerialUtils; +import com.netgrif.quartz.mongodb.util.SerialUtils; import org.bson.Document; import org.quartz.JobDataMap; import org.quartz.JobPersistenceException; diff --git a/src/main/java/com/novemberain/quartz/mongodb/LockManager.java b/src/main/java/com/netgrif/quartz/mongodb/LockManager.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/LockManager.java rename to src/main/java/com/netgrif/quartz/mongodb/LockManager.java index 548aa492..f7855060 --- a/src/main/java/com/novemberain/quartz/mongodb/LockManager.java +++ b/src/main/java/com/netgrif/quartz/mongodb/LockManager.java @@ -1,8 +1,8 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; import com.mongodb.MongoWriteException; -import com.novemberain.quartz.mongodb.dao.LocksDao; -import com.novemberain.quartz.mongodb.util.ExpiryCalculator; +import com.netgrif.quartz.mongodb.dao.LocksDao; +import com.netgrif.quartz.mongodb.util.ExpiryCalculator; import org.bson.Document; import org.quartz.JobDetail; import org.quartz.TriggerKey; diff --git a/src/main/java/com/novemberain/quartz/mongodb/MongoDBJobStore.java b/src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/MongoDBJobStore.java rename to src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java index 1c353a3d..16e16e78 100755 --- a/src/main/java/com/novemberain/quartz/mongodb/MongoDBJobStore.java +++ b/src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java @@ -1,40 +1,32 @@ -/* - * $Id: MongoDBJobStore.java 253170 2014-01-06 02:28:03Z waded $ - * -------------------------------------------------------------------------------------- - * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com - * - * The software in this package is published under the terms of the CPAL v1.0 - * license, a copy of which has been included with this distribution in the - * LICENSE.txt file. - */ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; import com.mongodb.MongoCommandException; import com.mongodb.MongoException; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; -import com.novemberain.quartz.mongodb.db.MongoConnector; -import com.novemberain.quartz.mongodb.util.Keys; +import com.netgrif.quartz.mongodb.db.MongoConnector; +import com.netgrif.quartz.mongodb.util.Keys; import org.bson.Document; import org.quartz.*; -import org.quartz.Calendar; import org.quartz.Trigger.CompletedExecutionInstruction; import org.quartz.Trigger.TriggerState; import org.quartz.impl.matchers.GroupMatcher; import org.quartz.spi.*; +import org.quartz.Calendar; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; public class MongoDBJobStore implements JobStore, Constants { + private static final Logger log = LoggerFactory.getLogger(MongoDBJobStore.class); + + private MongoStoreAssembler assembler = new MongoStoreAssembler(); MongoConnector mongoConnector; @@ -110,6 +102,7 @@ protected ClassLoadHelper getClassLoaderHelper(ClassLoadHelper original) { public void initialize(ClassLoadHelper loadHelper, SchedulerSignaler signaler) throws SchedulerConfigException { Properties props = loadProperties(loadHelper); + log.info("Init MongoQuartz connector"); try { assembler.build(this, loadHelper, signaler, props); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { @@ -212,23 +205,7 @@ public boolean isJobDataAsBase64() { return jobDataAsBase64; } - /** - * Configures the way job data is stored. {@link JobDetail}'s - * or {@link Trigger}'s {@link JobDataMap} can be represented - * as a {@code Map}. - *
    - *
  • {@code true} (default) - Serialize map with - * {@link java.io.ObjectOutputStream ObjectOutputStream} - * and store as {@code base64} encoded string in field - * '{@value Constants#JOB_DATA}'. Map may contain any - * {@link java.io.Serializable Serializable} object - * internally, but will have some performance impact.
  • - *
  • {@code false} - Store map directly in - * '{@value Constants#JOB_DATA_PLAIN}' field. Use this - * option is you only store simple types in job data - * map for better performance.
  • - *
- */ + public void setJobDataAsBase64(boolean jobDataAsBase64) { this.jobDataAsBase64 = jobDataAsBase64; @@ -335,9 +312,10 @@ public void clearAllSchedulingData() throws JobPersistenceException { assembler.pausedTriggerGroupsDao.remove(); } + @Override public void storeCalendar(String name, Calendar calendar, boolean replaceExisting, boolean updateTriggers) - throws JobPersistenceException { + throws ObjectAlreadyExistsException, JobPersistenceException { // TODO implement updating triggers if (updateTriggers) { throw new UnsupportedOperationException("Updating triggers is not supported."); diff --git a/src/main/java/com/novemberain/quartz/mongodb/MongoStoreAssembler.java b/src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/MongoStoreAssembler.java rename to src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java index 0704c695..99b4db49 --- a/src/main/java/com/novemberain/quartz/mongodb/MongoStoreAssembler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java @@ -1,15 +1,15 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; import com.mongodb.client.MongoCollection; -import com.novemberain.quartz.mongodb.cluster.*; -import com.novemberain.quartz.mongodb.dao.*; -import com.novemberain.quartz.mongodb.db.MongoConnector; -import com.novemberain.quartz.mongodb.db.MongoConnectorBuilder; -import com.novemberain.quartz.mongodb.trigger.MisfireHandler; -import com.novemberain.quartz.mongodb.trigger.TriggerConverter; -import com.novemberain.quartz.mongodb.util.Clock; -import com.novemberain.quartz.mongodb.util.ExpiryCalculator; -import com.novemberain.quartz.mongodb.util.QueryHelper; +import com.netgrif.quartz.mongodb.cluster.*; +import com.netgrif.quartz.mongodb.db.MongoConnector; +import com.netgrif.quartz.mongodb.db.MongoConnectorBuilder; +import com.netgrif.quartz.mongodb.trigger.MisfireHandler; +import com.netgrif.quartz.mongodb.trigger.TriggerConverter; +import com.netgrif.quartz.mongodb.util.Clock; +import com.netgrif.quartz.mongodb.util.ExpiryCalculator; +import com.netgrif.quartz.mongodb.util.QueryHelper; +import com.netgrif.quartz.mongodb.dao.*; import org.bson.Document; import org.quartz.SchedulerConfigException; import org.quartz.spi.ClassLoadHelper; @@ -93,7 +93,7 @@ private Runnable createCheckinTask(MongoDBJobStore jobStore, ClassLoadHelper loa Runnable errorHandler; Class aClass; if (jobStore.getCheckInErrorHandler() == null) { - // current default, see + // TOTO je blbe :/ aClass = KamikazeErrorHandler.class; } else { aClass = loadHelper.loadClass(jobStore.getCheckInErrorHandler()); diff --git a/src/main/java/com/novemberain/quartz/mongodb/TriggerAndJobPersister.java b/src/main/java/com/netgrif/quartz/mongodb/TriggerAndJobPersister.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/com/novemberain/quartz/mongodb/TriggerAndJobPersister.java rename to src/main/java/com/netgrif/quartz/mongodb/TriggerAndJobPersister.java index cf0e674b..8145a7a4 --- a/src/main/java/com/novemberain/quartz/mongodb/TriggerAndJobPersister.java +++ b/src/main/java/com/netgrif/quartz/mongodb/TriggerAndJobPersister.java @@ -1,9 +1,9 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; -import com.novemberain.quartz.mongodb.dao.JobDao; -import com.novemberain.quartz.mongodb.dao.TriggerDao; -import com.novemberain.quartz.mongodb.trigger.TriggerConverter; -import com.novemberain.quartz.mongodb.util.Keys; +import com.netgrif.quartz.mongodb.dao.JobDao; +import com.netgrif.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.trigger.TriggerConverter; +import com.netgrif.quartz.mongodb.util.Keys; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; diff --git a/src/main/java/com/novemberain/quartz/mongodb/TriggerRunner.java b/src/main/java/com/netgrif/quartz/mongodb/TriggerRunner.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/TriggerRunner.java rename to src/main/java/com/netgrif/quartz/mongodb/TriggerRunner.java index b3411115..a63b0201 --- a/src/main/java/com/novemberain/quartz/mongodb/TriggerRunner.java +++ b/src/main/java/com/netgrif/quartz/mongodb/TriggerRunner.java @@ -1,14 +1,14 @@ -package com.novemberain.quartz.mongodb; +package com.netgrif.quartz.mongodb; import com.mongodb.MongoException; import com.mongodb.MongoWriteException; -import com.novemberain.quartz.mongodb.cluster.TriggerRecoverer; -import com.novemberain.quartz.mongodb.dao.CalendarDao; -import com.novemberain.quartz.mongodb.dao.JobDao; -import com.novemberain.quartz.mongodb.dao.LocksDao; -import com.novemberain.quartz.mongodb.dao.TriggerDao; -import com.novemberain.quartz.mongodb.trigger.MisfireHandler; -import com.novemberain.quartz.mongodb.trigger.TriggerConverter; +import com.netgrif.quartz.mongodb.cluster.TriggerRecoverer; +import com.netgrif.quartz.mongodb.dao.CalendarDao; +import com.netgrif.quartz.mongodb.dao.JobDao; +import com.netgrif.quartz.mongodb.dao.LocksDao; +import com.netgrif.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.trigger.MisfireHandler; +import com.netgrif.quartz.mongodb.trigger.TriggerConverter; import org.bson.Document; import org.quartz.*; import org.quartz.Calendar; diff --git a/src/main/java/com/novemberain/quartz/mongodb/TriggerStateManager.java b/src/main/java/com/netgrif/quartz/mongodb/TriggerStateManager.java old mode 100644 new mode 100755 similarity index 92% rename from src/main/java/com/novemberain/quartz/mongodb/TriggerStateManager.java rename to src/main/java/com/netgrif/quartz/mongodb/TriggerStateManager.java index b26a811c..2bb66a9d --- a/src/main/java/com/novemberain/quartz/mongodb/TriggerStateManager.java +++ b/src/main/java/com/netgrif/quartz/mongodb/TriggerStateManager.java @@ -1,12 +1,12 @@ -package com.novemberain.quartz.mongodb; - -import com.novemberain.quartz.mongodb.dao.JobDao; -import com.novemberain.quartz.mongodb.dao.PausedJobGroupsDao; -import com.novemberain.quartz.mongodb.dao.PausedTriggerGroupsDao; -import com.novemberain.quartz.mongodb.dao.TriggerDao; -import com.novemberain.quartz.mongodb.util.GroupHelper; -import com.novemberain.quartz.mongodb.util.QueryHelper; -import com.novemberain.quartz.mongodb.util.TriggerGroupHelper; +package com.netgrif.quartz.mongodb; + +import com.netgrif.quartz.mongodb.dao.JobDao; +import com.netgrif.quartz.mongodb.dao.PausedJobGroupsDao; +import com.netgrif.quartz.mongodb.dao.PausedTriggerGroupsDao; +import com.netgrif.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.util.GroupHelper; +import com.netgrif.quartz.mongodb.util.QueryHelper; +import com.netgrif.quartz.mongodb.util.TriggerGroupHelper; import org.bson.types.ObjectId; import org.quartz.JobKey; import org.quartz.Trigger.TriggerState; diff --git a/src/main/java/com/novemberain/quartz/mongodb/clojure/DynamicClassLoadHelper.java b/src/main/java/com/netgrif/quartz/mongodb/clojure/DynamicClassLoadHelper.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/clojure/DynamicClassLoadHelper.java rename to src/main/java/com/netgrif/quartz/mongodb/clojure/DynamicClassLoadHelper.java index 21bc0a4b..a620700a --- a/src/main/java/com/novemberain/quartz/mongodb/clojure/DynamicClassLoadHelper.java +++ b/src/main/java/com/netgrif/quartz/mongodb/clojure/DynamicClassLoadHelper.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.clojure; +package com.netgrif.quartz.mongodb.clojure; import clojure.lang.DynamicClassLoader; import org.quartz.spi.ClassLoadHelper; diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinExecutor.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinExecutor.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinExecutor.java rename to src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinExecutor.java index df8e240d..cf72979c --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinExecutor.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinExecutor.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java new file mode 100755 index 00000000..a40626c0 --- /dev/null +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java @@ -0,0 +1,58 @@ + package com.netgrif.quartz.mongodb.cluster; + +import com.mongodb.MongoWriteConcernException; +import com.netgrif.quartz.mongodb.dao.SchedulerDao; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckinTask implements Runnable { + + private static final Logger log = LoggerFactory.getLogger(CheckinTask.class); + + private SchedulerDao schedulerDao; + private Runnable errorHandler; + private int retryCount = 0; + private static final int MAX_RETRIES = 10; + private static final long RETRY_DELAY_MS = 1000; + + public CheckinTask(SchedulerDao schedulerDao, Runnable errorHandler) { + this.schedulerDao = schedulerDao; + this.errorHandler = errorHandler; + } + + public void setErrorHandler(Runnable errorHandler) { + this.errorHandler = errorHandler; + } + + @Override + public void run() { + try { + schedulerDao.checkIn(); + retryCount = 0; + } catch (MongoWriteConcernException e) { + handleWriteConcernException(e); + } catch (Exception e) { + log.error("TOTOK: Neočakávaná chyba počas check-in: " + e.getMessage(), e); + //errorHandler.run(); //TODO: ups.. + } + } + + private void handleWriteConcernException(MongoWriteConcernException e) { + if (retryCount < MAX_RETRIES) { + log.warn("WriteConcernException occurred, retrying check-in... Attempt: " + (retryCount + 1)); + try { + Thread.sleep(RETRY_DELAY_MS * retryCount); + retryCount++; + run(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + log.error("TOTOK: Thread interrupted during retry delay", ie); + } catch (Exception ee) { + log.error("TOTOK: shit.." +ee.getMessage() , ee); + } + } else { + log.error("TOTOK: Maximum number of attempts reached. Unable to complete check-in.", e); + errorHandler.run(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/KamikazeErrorHandler.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/KamikazeErrorHandler.java old mode 100644 new mode 100755 similarity index 90% rename from src/main/java/com/novemberain/quartz/mongodb/cluster/KamikazeErrorHandler.java rename to src/main/java/com/netgrif/quartz/mongodb/cluster/KamikazeErrorHandler.java index be33d727..ddfaac71 --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/KamikazeErrorHandler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/KamikazeErrorHandler.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; /** * This implementation pauses Quartz to not allow to execute the same JOB by two schedulers. diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/NoOpErrorHandler.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/NoOpErrorHandler.java old mode 100644 new mode 100755 similarity index 68% rename from src/main/java/com/novemberain/quartz/mongodb/cluster/NoOpErrorHandler.java rename to src/main/java/com/netgrif/quartz/mongodb/cluster/NoOpErrorHandler.java index 9b4481d2..eb8128ed --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/NoOpErrorHandler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/NoOpErrorHandler.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; public class NoOpErrorHandler implements Runnable { @Override diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/RecoveryTriggerFactory.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/RecoveryTriggerFactory.java old mode 100644 new mode 100755 similarity index 97% rename from src/main/java/com/novemberain/quartz/mongodb/cluster/RecoveryTriggerFactory.java rename to src/main/java/com/netgrif/quartz/mongodb/cluster/RecoveryTriggerFactory.java index 681f7135..25354f92 --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/RecoveryTriggerFactory.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/RecoveryTriggerFactory.java @@ -1,13 +1,12 @@ -package com.novemberain.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; import org.quartz.JobDataMap; import org.quartz.JobKey; -import org.quartz.Scheduler; import org.quartz.SimpleTrigger; import org.quartz.TriggerKey; import org.quartz.impl.triggers.SimpleTriggerImpl; import org.quartz.spi.OperableTrigger; - +import org.quartz.Scheduler; import java.util.Date; public class RecoveryTriggerFactory { diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/Scheduler.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/Scheduler.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/cluster/Scheduler.java rename to src/main/java/com/netgrif/quartz/mongodb/cluster/Scheduler.java index 2f007a8a..072ce715 --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/Scheduler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/Scheduler.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; public class Scheduler { diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/TriggerRecoverer.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/TriggerRecoverer.java old mode 100644 new mode 100755 similarity index 91% rename from src/main/java/com/novemberain/quartz/mongodb/cluster/TriggerRecoverer.java rename to src/main/java/com/netgrif/quartz/mongodb/cluster/TriggerRecoverer.java index d73685a4..5ff9fa7b --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/TriggerRecoverer.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/TriggerRecoverer.java @@ -1,11 +1,11 @@ -package com.novemberain.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; -import com.novemberain.quartz.mongodb.LockManager; -import com.novemberain.quartz.mongodb.TriggerAndJobPersister; -import com.novemberain.quartz.mongodb.dao.JobDao; -import com.novemberain.quartz.mongodb.dao.LocksDao; -import com.novemberain.quartz.mongodb.dao.TriggerDao; -import com.novemberain.quartz.mongodb.trigger.MisfireHandler; +import com.netgrif.quartz.mongodb.LockManager; +import com.netgrif.quartz.mongodb.TriggerAndJobPersister; +import com.netgrif.quartz.mongodb.dao.JobDao; +import com.netgrif.quartz.mongodb.dao.LocksDao; +import com.netgrif.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.trigger.MisfireHandler; import org.quartz.JobPersistenceException; import org.quartz.TriggerKey; import org.quartz.spi.OperableTrigger; diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/CalendarDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/CalendarDao.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/com/novemberain/quartz/mongodb/dao/CalendarDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/CalendarDao.java index 42043c40..e5e1bcf0 --- a/src/main/java/com/novemberain/quartz/mongodb/dao/CalendarDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/CalendarDao.java @@ -1,17 +1,16 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.Projections; +import com.netgrif.quartz.mongodb.util.SerialUtils; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.Binary; import org.quartz.Calendar; import org.quartz.JobPersistenceException; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.Filters; -import com.mongodb.client.model.IndexOptions; -import com.mongodb.client.model.Projections; -import com.novemberain.quartz.mongodb.util.SerialUtils; - import java.util.LinkedList; import java.util.List; diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/JobDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/JobDao.java old mode 100644 new mode 100755 similarity index 91% rename from src/main/java/com/novemberain/quartz/mongodb/dao/JobDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/JobDao.java index 9771cadb..9ab6b7df --- a/src/main/java/com/novemberain/quartz/mongodb/dao/JobDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/JobDao.java @@ -1,14 +1,14 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; import com.mongodb.MongoWriteException; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.Filters; import com.mongodb.client.model.IndexOptions; import com.mongodb.client.result.DeleteResult; -import com.novemberain.quartz.mongodb.JobConverter; -import com.novemberain.quartz.mongodb.util.GroupHelper; -import com.novemberain.quartz.mongodb.util.Keys; -import com.novemberain.quartz.mongodb.util.QueryHelper; +import com.netgrif.quartz.mongodb.JobConverter; +import com.netgrif.quartz.mongodb.util.GroupHelper; +import com.netgrif.quartz.mongodb.util.Keys; +import com.netgrif.quartz.mongodb.util.QueryHelper; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; @@ -19,8 +19,8 @@ import java.util.*; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; -import static com.novemberain.quartz.mongodb.util.Keys.toFilter; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.toFilter; public class JobDao { diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/LocksDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/LocksDao.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/com/novemberain/quartz/mongodb/dao/LocksDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/LocksDao.java index 6e2caab0..8ba80188 --- a/src/main/java/com/novemberain/quartz/mongodb/dao/LocksDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/LocksDao.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; @@ -6,7 +6,7 @@ import com.mongodb.client.model.IndexOptions; import com.mongodb.client.model.Projections; import com.mongodb.client.result.UpdateResult; -import com.novemberain.quartz.mongodb.util.Clock; +import com.netgrif.quartz.mongodb.util.Clock; import org.bson.Document; import org.bson.conversions.Bson; import org.quartz.JobDetail; @@ -21,8 +21,8 @@ import java.util.LinkedList; import java.util.List; -import static com.novemberain.quartz.mongodb.Constants.LOCK_INSTANCE_ID; -import static com.novemberain.quartz.mongodb.util.Keys.*; +import static com.netgrif.quartz.mongodb.Constants.LOCK_INSTANCE_ID; +import static com.netgrif.quartz.mongodb.util.Keys.*; public class LocksDao { @@ -104,6 +104,7 @@ public void lockTrigger(TriggerKey key) { * @return false when not found or caught an exception */ public boolean relock(TriggerKey key, Date lockTime) { + key = key; UpdateResult updateResult; try { updateResult = locksCollection.updateOne( diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/PausedJobGroupsDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/PausedJobGroupsDao.java old mode 100644 new mode 100755 similarity index 91% rename from src/main/java/com/novemberain/quartz/mongodb/dao/PausedJobGroupsDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/PausedJobGroupsDao.java index a873bd4a..0da76b68 --- a/src/main/java/com/novemberain/quartz/mongodb/dao/PausedJobGroupsDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/PausedJobGroupsDao.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.Filters; @@ -9,7 +9,7 @@ import java.util.HashSet; import java.util.List; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; public class PausedJobGroupsDao { diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/PausedTriggerGroupsDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/PausedTriggerGroupsDao.java old mode 100644 new mode 100755 similarity index 91% rename from src/main/java/com/novemberain/quartz/mongodb/dao/PausedTriggerGroupsDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/PausedTriggerGroupsDao.java index 1dde3935..0d29e762 --- a/src/main/java/com/novemberain/quartz/mongodb/dao/PausedTriggerGroupsDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/PausedTriggerGroupsDao.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.Filters; @@ -9,7 +9,7 @@ import java.util.HashSet; import java.util.List; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; public class PausedTriggerGroupsDao { diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/SchedulerDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/SchedulerDao.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/dao/SchedulerDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/SchedulerDao.java index 2ab3b299..421dff47 --- a/src/main/java/com/novemberain/quartz/mongodb/dao/SchedulerDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/SchedulerDao.java @@ -1,11 +1,14 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.*; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.Projections; +import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; -import com.novemberain.quartz.mongodb.cluster.Scheduler; -import com.novemberain.quartz.mongodb.util.Clock; +import com.netgrif.quartz.mongodb.cluster.Scheduler; +import com.netgrif.quartz.mongodb.util.Clock; import org.bson.Document; import org.bson.conversions.Bson; import org.slf4j.Logger; @@ -61,7 +64,7 @@ public void createIndex() { public void checkIn() { long lastCheckinTime = clock.millis(); - log.debug("Saving node data: name='{}', id='{}', checkin time={}, interval={}", + log.debug("Saving node data: name='{}', id='{}', checkin time={}, interval={}", schedulerName, instanceId, lastCheckinTime, clusterCheckinIntervalMillis); // If not found Mongo will create a new entry with content from filter and update. diff --git a/src/main/java/com/novemberain/quartz/mongodb/dao/TriggerDao.java b/src/main/java/com/netgrif/quartz/mongodb/dao/TriggerDao.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/dao/TriggerDao.java rename to src/main/java/com/netgrif/quartz/mongodb/dao/TriggerDao.java index e20067e9..de5b4dc0 --- a/src/main/java/com/novemberain/quartz/mongodb/dao/TriggerDao.java +++ b/src/main/java/com/netgrif/quartz/mongodb/dao/TriggerDao.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.dao; +package com.netgrif.quartz.mongodb.dao; import com.mongodb.MongoWriteException; import com.mongodb.client.FindIterable; @@ -7,10 +7,10 @@ import com.mongodb.client.model.IndexOptions; import com.mongodb.client.model.ReplaceOptions; import com.mongodb.client.model.UpdateOptions; -import com.novemberain.quartz.mongodb.Constants; -import com.novemberain.quartz.mongodb.trigger.TriggerConverter; -import com.novemberain.quartz.mongodb.util.Keys; -import com.novemberain.quartz.mongodb.util.QueryHelper; +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.trigger.TriggerConverter; +import com.netgrif.quartz.mongodb.util.Keys; +import com.netgrif.quartz.mongodb.util.QueryHelper; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; @@ -23,16 +23,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; import static com.mongodb.client.model.Sorts.ascending; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; -import static com.novemberain.quartz.mongodb.util.Keys.toFilter; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.toFilter; public class TriggerDao { diff --git a/src/main/java/com/novemberain/quartz/mongodb/db/ExternalMongoConnector.java b/src/main/java/com/netgrif/quartz/mongodb/db/ExternalMongoConnector.java old mode 100644 new mode 100755 similarity index 85% rename from src/main/java/com/novemberain/quartz/mongodb/db/ExternalMongoConnector.java rename to src/main/java/com/netgrif/quartz/mongodb/db/ExternalMongoConnector.java index f37a187d..94c81a3f --- a/src/main/java/com/novemberain/quartz/mongodb/db/ExternalMongoConnector.java +++ b/src/main/java/com/netgrif/quartz/mongodb/db/ExternalMongoConnector.java @@ -1,16 +1,21 @@ -package com.novemberain.quartz.mongodb.db; +package com.netgrif.quartz.mongodb.db; import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The implementation of {@link MongoConnector} that doesn't own the lifecycle of {@link MongoClient}. */ public class ExternalMongoConnector implements MongoConnector { + + private static final Logger log = LoggerFactory.getLogger(ExternalMongoConnector.class); + private final WriteConcern writeConcern; private final MongoDatabase database; @@ -26,6 +31,10 @@ public ExternalMongoConnector(final WriteConcern writeConcern, final MongoDataba this.writeConcern = writeConcern; } + public ExternalMongoConnector(MongoClient mongoClient, String dbName) { + this(WriteConcern.W1, mongoClient.getDatabase(dbName)); + } + /** * Constructs an instance of {@link ExternalMongoConnector}. * diff --git a/src/main/java/com/novemberain/quartz/mongodb/db/InternalMongoConnector.java b/src/main/java/com/netgrif/quartz/mongodb/db/InternalMongoConnector.java old mode 100644 new mode 100755 similarity index 99% rename from src/main/java/com/novemberain/quartz/mongodb/db/InternalMongoConnector.java rename to src/main/java/com/netgrif/quartz/mongodb/db/InternalMongoConnector.java index 7c5a9f41..05d121f1 --- a/src/main/java/com/novemberain/quartz/mongodb/db/InternalMongoConnector.java +++ b/src/main/java/com/netgrif/quartz/mongodb/db/InternalMongoConnector.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.db; +package com.netgrif.quartz.mongodb.db; import com.mongodb.*; import com.mongodb.client.MongoClient; diff --git a/src/main/java/com/novemberain/quartz/mongodb/db/MongoConnector.java b/src/main/java/com/netgrif/quartz/mongodb/db/MongoConnector.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/db/MongoConnector.java rename to src/main/java/com/netgrif/quartz/mongodb/db/MongoConnector.java index a3273f81..4c444ed6 --- a/src/main/java/com/novemberain/quartz/mongodb/db/MongoConnector.java +++ b/src/main/java/com/netgrif/quartz/mongodb/db/MongoConnector.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.db; +package com.netgrif.quartz.mongodb.db; import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; diff --git a/src/main/java/com/novemberain/quartz/mongodb/db/MongoConnectorBuilder.java b/src/main/java/com/netgrif/quartz/mongodb/db/MongoConnectorBuilder.java old mode 100644 new mode 100755 similarity index 99% rename from src/main/java/com/novemberain/quartz/mongodb/db/MongoConnectorBuilder.java rename to src/main/java/com/netgrif/quartz/mongodb/db/MongoConnectorBuilder.java index a8550453..6dffd541 --- a/src/main/java/com/novemberain/quartz/mongodb/db/MongoConnectorBuilder.java +++ b/src/main/java/com/netgrif/quartz/mongodb/db/MongoConnectorBuilder.java @@ -1,19 +1,18 @@ -package com.novemberain.quartz.mongodb.db; +package com.netgrif.quartz.mongodb.db; import com.mongodb.*; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; import org.quartz.SchedulerConfigException; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLException; - /** * Builder for {@link MongoConnector}. */ @@ -79,7 +78,7 @@ public MongoConnector build() throws SchedulerConfigException { if (database != null) { // User passed MongoDatabase instance. validateForDatabase(); - return new ExternalMongoConnector(writeConcern, database); + return new ExternalMongoConnector(writeConcern, database); //TODO: init edit } // Options below require database name diff --git a/src/main/java/com/novemberain/quartz/mongodb/db/SSLContextFactory.java b/src/main/java/com/netgrif/quartz/mongodb/db/SSLContextFactory.java old mode 100644 new mode 100755 similarity index 98% rename from src/main/java/com/novemberain/quartz/mongodb/db/SSLContextFactory.java rename to src/main/java/com/netgrif/quartz/mongodb/db/SSLContextFactory.java index 4702f70e..5b94a054 --- a/src/main/java/com/novemberain/quartz/mongodb/db/SSLContextFactory.java +++ b/src/main/java/com/netgrif/quartz/mongodb/db/SSLContextFactory.java @@ -1,5 +1,11 @@ -package com.novemberain.quartz.mongodb.db; +package com.netgrif.quartz.mongodb.db; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.SSLContexts; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; @@ -7,13 +13,6 @@ import java.security.GeneralSecurityException; import java.security.KeyStore; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLException; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.ssl.SSLContexts; - /** * Allows to get an {@link SSLContext} from a Java truststore and keystore. */ diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/MisfireHandler.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/MisfireHandler.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/MisfireHandler.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/MisfireHandler.java index 02480e04..54d516b0 --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/MisfireHandler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/MisfireHandler.java @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb.trigger; +package com.netgrif.quartz.mongodb.trigger; -import com.novemberain.quartz.mongodb.dao.CalendarDao; +import com.netgrif.quartz.mongodb.dao.CalendarDao; import org.quartz.Calendar; import org.quartz.JobPersistenceException; import org.quartz.Trigger; diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/TriggerConverter.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/TriggerConverter.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/TriggerConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/TriggerConverter.java index f60e0254..f6b99cac --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/TriggerConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/TriggerConverter.java @@ -1,9 +1,8 @@ -package com.novemberain.quartz.mongodb.trigger; +package com.netgrif.quartz.mongodb.trigger; -import com.novemberain.quartz.mongodb.Constants; -import com.novemberain.quartz.mongodb.JobDataConverter; -import com.novemberain.quartz.mongodb.dao.JobDao; -import com.novemberain.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.JobDataConverter; +import com.netgrif.quartz.mongodb.dao.JobDao; import org.bson.Document; import org.bson.types.ObjectId; import org.quartz.Job; @@ -14,8 +13,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_NAME; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_NAME; public class TriggerConverter { diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/TriggerPropertiesConverter.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/TriggerPropertiesConverter.java old mode 100644 new mode 100755 similarity index 75% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/TriggerPropertiesConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/TriggerPropertiesConverter.java index 219f6d10..bec1adab --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/TriggerPropertiesConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/TriggerPropertiesConverter.java @@ -1,9 +1,9 @@ -package com.novemberain.quartz.mongodb.trigger; +package com.netgrif.quartz.mongodb.trigger; -import com.novemberain.quartz.mongodb.trigger.properties.CalendarIntervalTriggerPropertiesConverter; -import com.novemberain.quartz.mongodb.trigger.properties.CronTriggerPropertiesConverter; -import com.novemberain.quartz.mongodb.trigger.properties.DailyTimeIntervalTriggerPropertiesConverter; -import com.novemberain.quartz.mongodb.trigger.properties.SimpleTriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.properties.CalendarIntervalTriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.properties.CronTriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.properties.DailyTimeIntervalTriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.properties.SimpleTriggerPropertiesConverter; import org.bson.Document; import org.quartz.spi.OperableTrigger; diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java index 6895deb0..7143b6eb --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/CalendarIntervalTriggerPropertiesConverter.java @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb.trigger.properties; +package com.netgrif.quartz.mongodb.trigger.properties; -import com.novemberain.quartz.mongodb.trigger.TriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.TriggerPropertiesConverter; import org.bson.Document; import org.quartz.DateBuilder.IntervalUnit; import org.quartz.impl.triggers.CalendarIntervalTriggerImpl; diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java old mode 100644 new mode 100755 similarity index 92% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java index e751499d..c7e846f0 --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/CronTriggerPropertiesConverter.java @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb.trigger.properties; +package com.netgrif.quartz.mongodb.trigger.properties; -import com.novemberain.quartz.mongodb.trigger.TriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.TriggerPropertiesConverter; import org.bson.Document; import org.quartz.CronExpression; import org.quartz.CronTrigger; diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java index 965dad08..2014c7be --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/DailyTimeIntervalTriggerPropertiesConverter.java @@ -1,17 +1,16 @@ -package com.novemberain.quartz.mongodb.trigger.properties; +package com.netgrif.quartz.mongodb.trigger.properties; -import com.novemberain.quartz.mongodb.trigger.TriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.TriggerPropertiesConverter; import org.bson.Document; import org.quartz.DailyTimeIntervalTrigger; +import org.quartz.DateBuilder; import org.quartz.TimeOfDay; import org.quartz.impl.triggers.DailyTimeIntervalTriggerImpl; import org.quartz.spi.OperableTrigger; -import org.quartz.DateBuilder; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Set; public class DailyTimeIntervalTriggerPropertiesConverter extends TriggerPropertiesConverter { diff --git a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java rename to src/main/java/com/netgrif/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java index d973dc29..3fce5e79 --- a/src/main/java/com/novemberain/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java +++ b/src/main/java/com/netgrif/quartz/mongodb/trigger/properties/SimpleTriggerPropertiesConverter.java @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb.trigger.properties; +package com.netgrif.quartz.mongodb.trigger.properties; -import com.novemberain.quartz.mongodb.trigger.TriggerPropertiesConverter; +import com.netgrif.quartz.mongodb.trigger.TriggerPropertiesConverter; import org.bson.Document; import org.quartz.SimpleTrigger; import org.quartz.impl.triggers.SimpleTriggerImpl; diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/Clock.java b/src/main/java/com/netgrif/quartz/mongodb/util/Clock.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/com/novemberain/quartz/mongodb/util/Clock.java rename to src/main/java/com/netgrif/quartz/mongodb/util/Clock.java index 990c2de2..e3f7d032 --- a/src/main/java/com/novemberain/quartz/mongodb/util/Clock.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/Clock.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; import java.util.Date; diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/ExpiryCalculator.java b/src/main/java/com/netgrif/quartz/mongodb/util/ExpiryCalculator.java old mode 100644 new mode 100755 similarity index 88% rename from src/main/java/com/novemberain/quartz/mongodb/util/ExpiryCalculator.java rename to src/main/java/com/netgrif/quartz/mongodb/util/ExpiryCalculator.java index 9774ddac..4d4a650e --- a/src/main/java/com/novemberain/quartz/mongodb/util/ExpiryCalculator.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/ExpiryCalculator.java @@ -1,8 +1,8 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; -import com.novemberain.quartz.mongodb.Constants; -import com.novemberain.quartz.mongodb.cluster.Scheduler; -import com.novemberain.quartz.mongodb.dao.SchedulerDao; +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.cluster.Scheduler; +import com.netgrif.quartz.mongodb.dao.SchedulerDao; import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +25,7 @@ public ExpiryCalculator(SchedulerDao schedulerDao, Clock clock, this.clock = clock; this.jobTimeoutMillis = jobTimeoutMillis; this.triggerTimeoutMillis = triggerTimeoutMillis; - this.isClustered = isClustered; + this.isClustered = isClustered; //TODO: tak to je na hovienko... } public boolean isJobLockExpired(Document lock) { diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/GroupHelper.java b/src/main/java/com/netgrif/quartz/mongodb/util/GroupHelper.java old mode 100644 new mode 100755 similarity index 79% rename from src/main/java/com/novemberain/quartz/mongodb/util/GroupHelper.java rename to src/main/java/com/netgrif/quartz/mongodb/util/GroupHelper.java index f1d69f29..82dfeeeb --- a/src/main/java/com/novemberain/quartz/mongodb/util/GroupHelper.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/GroupHelper.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.Filters; @@ -11,7 +11,6 @@ import java.util.List; import java.util.Set; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; public class GroupHelper { protected MongoCollection collection; @@ -25,20 +24,20 @@ public GroupHelper(MongoCollection collection, QueryHelper queryHelper public Set groupsThatMatch(GroupMatcher matcher) { Bson filter = queryHelper.matchingKeysConditionFor(matcher); return collection - .distinct(KEY_GROUP, String.class) + .distinct(Keys.KEY_GROUP, String.class) .filter(filter) .into(new HashSet()); } public List inGroupsThatMatch(GroupMatcher matcher) { return collection - .find(Filters.in(KEY_GROUP, groupsThatMatch(matcher))) + .find(Filters.in(Keys.KEY_GROUP, groupsThatMatch(matcher))) .into(new LinkedList()); } public Set allGroups() { return collection - .distinct(KEY_GROUP, String.class) + .distinct(Keys.KEY_GROUP, String.class) .into(new HashSet()); } } diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/Keys.java b/src/main/java/com/netgrif/quartz/mongodb/util/Keys.java old mode 100644 new mode 100755 similarity index 97% rename from src/main/java/com/novemberain/quartz/mongodb/util/Keys.java rename to src/main/java/com/netgrif/quartz/mongodb/util/Keys.java index d79c3d48..18a5c091 --- a/src/main/java/com/novemberain/quartz/mongodb/util/Keys.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/Keys.java @@ -1,8 +1,8 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; -import com.novemberain.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.Constants; import org.bson.Document; import org.bson.conversions.Bson; import org.quartz.JobKey; diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/QueryHelper.java b/src/main/java/com/netgrif/quartz/mongodb/util/QueryHelper.java old mode 100644 new mode 100755 similarity index 58% rename from src/main/java/com/novemberain/quartz/mongodb/util/QueryHelper.java rename to src/main/java/com/netgrif/quartz/mongodb/util/QueryHelper.java index 149a9153..ffbff63b --- a/src/main/java/com/novemberain/quartz/mongodb/util/QueryHelper.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/QueryHelper.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; import com.mongodb.client.model.Filters; import org.bson.BsonDocument; @@ -7,8 +7,6 @@ import java.util.Collection; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; - public class QueryHelper { public Bson matchingKeysConditionFor(GroupMatcher matcher) { @@ -16,19 +14,19 @@ public Bson matchingKeysConditionFor(GroupMatcher matcher) { switch (matcher.getCompareWithOperator()) { case EQUALS: - return Filters.eq(KEY_GROUP, compareToValue); + return Filters.eq(Keys.KEY_GROUP, compareToValue); case STARTS_WITH: - return Filters.regex(KEY_GROUP, "^" + compareToValue + ".*"); + return Filters.regex(Keys.KEY_GROUP, "^" + compareToValue + ".*"); case ENDS_WITH: - return Filters.regex(KEY_GROUP, ".*" + compareToValue + "$"); + return Filters.regex(Keys.KEY_GROUP, ".*" + compareToValue + "$"); case CONTAINS: - return Filters.regex(KEY_GROUP, compareToValue); + return Filters.regex(Keys.KEY_GROUP, compareToValue); } return new BsonDocument(); } public Bson inGroups(Collection groups) { - return Filters.in(KEY_GROUP, groups); + return Filters.in(Keys.KEY_GROUP, groups); } } diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/SerialUtils.java b/src/main/java/com/netgrif/quartz/mongodb/util/SerialUtils.java old mode 100644 new mode 100755 similarity index 98% rename from src/main/java/com/novemberain/quartz/mongodb/util/SerialUtils.java rename to src/main/java/com/netgrif/quartz/mongodb/util/SerialUtils.java index 5cfca439..fef0c2d6 --- a/src/main/java/com/novemberain/quartz/mongodb/util/SerialUtils.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/SerialUtils.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; import org.apache.commons.codec.binary.Base64; import org.bson.types.Binary; diff --git a/src/main/java/com/novemberain/quartz/mongodb/util/TriggerGroupHelper.java b/src/main/java/com/netgrif/quartz/mongodb/util/TriggerGroupHelper.java old mode 100644 new mode 100755 similarity index 88% rename from src/main/java/com/novemberain/quartz/mongodb/util/TriggerGroupHelper.java rename to src/main/java/com/netgrif/quartz/mongodb/util/TriggerGroupHelper.java index 170e0663..97821cab --- a/src/main/java/com/novemberain/quartz/mongodb/util/TriggerGroupHelper.java +++ b/src/main/java/com/netgrif/quartz/mongodb/util/TriggerGroupHelper.java @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.util; +package com.netgrif.quartz.mongodb.util; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.Filters; @@ -9,7 +9,7 @@ import java.util.LinkedList; import java.util.List; -import static com.novemberain.quartz.mongodb.util.Keys.KEY_GROUP; +import static com.netgrif.quartz.mongodb.util.Keys.KEY_GROUP; public class TriggerGroupHelper extends GroupHelper { public static final String JOB_ID = "jobId"; diff --git a/src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinTask.java b/src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinTask.java deleted file mode 100644 index 65b98050..00000000 --- a/src/main/java/com/novemberain/quartz/mongodb/cluster/CheckinTask.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.novemberain.quartz.mongodb.cluster; - -import com.mongodb.MongoException; -import com.novemberain.quartz.mongodb.dao.SchedulerDao; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The responsibility of this class is to check-in inside Scheduler Cluster. - */ -public class CheckinTask implements Runnable { - - private static final Logger log = LoggerFactory.getLogger(CheckinTask.class); - - private SchedulerDao schedulerDao; - private Runnable errorhandler; - - public CheckinTask(SchedulerDao schedulerDao, Runnable errorHandler) { - this.schedulerDao = schedulerDao; - this.errorhandler = errorHandler; - } - - // for tests only - public void setErrorHandler(Runnable errorHandler) { - this.errorhandler = errorHandler; - } - - @Override - public void run() { - log.debug("Node {}:{} checks-in.", schedulerDao.schedulerName, schedulerDao.instanceId); - try { - schedulerDao.checkIn(); - } catch (MongoException e) { - log.error("Node " + schedulerDao.instanceId + " could not check-in: " + e.getMessage(), e); - errorhandler.run(); - } - } -} diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/Clocks.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/Clocks.groovy similarity index 85% rename from src/test/groovy/com/novemberain/quartz/mongodb/Clocks.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/Clocks.groovy index 2a1ae6ed..bc96ee3d 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/Clocks.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/Clocks.groovy @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb -import com.novemberain.quartz.mongodb.util.Clock +import com.netgrif.quartz.mongodb.util.Clock import java.util.concurrent.atomic.AtomicInteger diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/FailoverTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/FailoverTest.groovy similarity index 99% rename from src/test/groovy/com/novemberain/quartz/mongodb/FailoverTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/FailoverTest.groovy index 56ba52bc..9860717c 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/FailoverTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/FailoverTest.groovy @@ -1,6 +1,6 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb -import com.novemberain.quartz.mongodb.util.Keys +import com.netgrif.quartz.mongodb.util.Keys import org.bson.types.ObjectId import org.quartz.Job import org.quartz.JobExecutionContext diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/JobDataConverterTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/JobDataConverterTest.groovy similarity index 99% rename from src/test/groovy/com/novemberain/quartz/mongodb/JobDataConverterTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/JobDataConverterTest.groovy index ccdb3d40..ed3b0ae6 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/JobDataConverterTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/JobDataConverterTest.groovy @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb import groovy.transform.EqualsAndHashCode import groovy.transform.ToString diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/LoadBalancingTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/LoadBalancingTest.groovy similarity index 97% rename from src/test/groovy/com/novemberain/quartz/mongodb/LoadBalancingTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/LoadBalancingTest.groovy index 8eb07346..27df965f 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/LoadBalancingTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/LoadBalancingTest.groovy @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb import org.quartz.Job import org.quartz.JobBuilder diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/LockManagerTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/LockManagerTest.groovy similarity index 93% rename from src/test/groovy/com/novemberain/quartz/mongodb/LockManagerTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/LockManagerTest.groovy index cdc5a3e8..2d010e8d 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/LockManagerTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/LockManagerTest.groovy @@ -1,10 +1,10 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb import com.mongodb.MongoWriteException import com.mongodb.ServerAddress import com.mongodb.WriteError -import com.novemberain.quartz.mongodb.dao.LocksDao -import com.novemberain.quartz.mongodb.util.ExpiryCalculator +import com.netgrif.quartz.mongodb.dao.LocksDao +import com.netgrif.quartz.mongodb.util.ExpiryCalculator import org.bson.BsonDocument import org.bson.Document import org.quartz.TriggerKey diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/MongoHelper.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/MongoHelper.groovy similarity index 98% rename from src/test/groovy/com/novemberain/quartz/mongodb/MongoHelper.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/MongoHelper.groovy index 61f80a63..aee1cb30 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/MongoHelper.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/MongoHelper.groovy @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb import com.mongodb.MongoClientSettings import com.mongodb.ServerAddress diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/QuartzHelper.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/QuartzHelper.groovy similarity index 98% rename from src/test/groovy/com/novemberain/quartz/mongodb/QuartzHelper.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/QuartzHelper.groovy index 3b523948..5256300d 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/QuartzHelper.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/QuartzHelper.groovy @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb import org.joda.time.DateTime import org.quartz.Scheduler diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/TriggerStateManagerTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/TriggerStateManagerTest.groovy similarity index 83% rename from src/test/groovy/com/novemberain/quartz/mongodb/TriggerStateManagerTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/TriggerStateManagerTest.groovy index 3255f9d0..17117f78 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/TriggerStateManagerTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/TriggerStateManagerTest.groovy @@ -1,10 +1,10 @@ -package com.novemberain.quartz.mongodb +package com.netgrif.quartz.mongodb -import com.novemberain.quartz.mongodb.dao.JobDao -import com.novemberain.quartz.mongodb.dao.PausedJobGroupsDao -import com.novemberain.quartz.mongodb.dao.PausedTriggerGroupsDao -import com.novemberain.quartz.mongodb.dao.TriggerDao -import com.novemberain.quartz.mongodb.util.QueryHelper +import com.netgrif.quartz.mongodb.dao.JobDao +import com.netgrif.quartz.mongodb.dao.PausedJobGroupsDao +import com.netgrif.quartz.mongodb.dao.PausedTriggerGroupsDao +import com.netgrif.quartz.mongodb.dao.TriggerDao +import com.netgrif.quartz.mongodb.util.QueryHelper import org.quartz.TriggerKey import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/cluster/CheckinTaskTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/cluster/CheckinTaskTest.groovy similarity index 88% rename from src/test/groovy/com/novemberain/quartz/mongodb/cluster/CheckinTaskTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/cluster/CheckinTaskTest.groovy index 9671cfce..cc6306d6 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/cluster/CheckinTaskTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/cluster/CheckinTaskTest.groovy @@ -1,7 +1,7 @@ -package com.novemberain.quartz.mongodb.cluster +package com.netgrif.quartz.mongodb.cluster import com.mongodb.MongoException -import com.novemberain.quartz.mongodb.dao.SchedulerDao +import com.netgrif.quartz.mongodb.dao.SchedulerDao import spock.lang.Specification class CheckinTaskTest extends Specification { diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/cluster/SchedulerTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/cluster/SchedulerTest.groovy similarity index 95% rename from src/test/groovy/com/novemberain/quartz/mongodb/cluster/SchedulerTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/cluster/SchedulerTest.groovy index b0057118..3d65e849 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/cluster/SchedulerTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/cluster/SchedulerTest.groovy @@ -1,4 +1,4 @@ -package com.novemberain.quartz.mongodb.cluster +package com.netgrif.quartz.mongodb.cluster import spock.lang.Specification diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/dao/CalendarDaoTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/dao/CalendarDaoTest.groovy similarity index 87% rename from src/test/groovy/com/novemberain/quartz/mongodb/dao/CalendarDaoTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/dao/CalendarDaoTest.groovy index 730df1c3..592c9e2c 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/dao/CalendarDaoTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/dao/CalendarDaoTest.groovy @@ -1,11 +1,11 @@ -package com.novemberain.quartz.mongodb.dao +package com.netgrif.quartz.mongodb.dao -import com.novemberain.quartz.mongodb.MongoHelper +import com.netgrif.quartz.mongodb.MongoHelper import org.quartz.impl.calendar.DailyCalendar import spock.lang.Specification -import static com.novemberain.quartz.mongodb.dao.CalendarDao.CALENDAR_NAME -import static com.novemberain.quartz.mongodb.dao.CalendarDao.CALENDAR_SERIALIZED_OBJECT +import static com.netgrif.quartz.mongodb.dao.CalendarDao.CALENDAR_NAME +import static com.netgrif.quartz.mongodb.dao.CalendarDao.CALENDAR_SERIALIZED_OBJECT class CalendarDaoTest extends Specification { diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/dao/LocksDaoTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/dao/LocksDaoTest.groovy similarity index 94% rename from src/test/groovy/com/novemberain/quartz/mongodb/dao/LocksDaoTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/dao/LocksDaoTest.groovy index d6651ea7..41e61be5 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/dao/LocksDaoTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/dao/LocksDaoTest.groovy @@ -1,10 +1,10 @@ -package com.novemberain.quartz.mongodb.dao +package com.netgrif.quartz.mongodb.dao import com.mongodb.MongoWriteException -import com.novemberain.quartz.mongodb.Clocks -import com.novemberain.quartz.mongodb.MongoHelper -import com.novemberain.quartz.mongodb.util.Clock -import com.novemberain.quartz.mongodb.util.Keys +import com.netgrif.quartz.mongodb.Clocks +import com.netgrif.quartz.mongodb.MongoHelper +import com.netgrif.quartz.mongodb.util.Clock +import com.netgrif.quartz.mongodb.util.Keys import org.quartz.TriggerKey import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/dao/SchedulerDaoTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/dao/SchedulerDaoTest.groovy similarity index 96% rename from src/test/groovy/com/novemberain/quartz/mongodb/dao/SchedulerDaoTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/dao/SchedulerDaoTest.groovy index af462170..1f6cd00a 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/dao/SchedulerDaoTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/dao/SchedulerDaoTest.groovy @@ -1,8 +1,8 @@ -package com.novemberain.quartz.mongodb.dao +package com.netgrif.quartz.mongodb.dao -import com.novemberain.quartz.mongodb.Clocks -import com.novemberain.quartz.mongodb.MongoHelper -import com.novemberain.quartz.mongodb.util.Clock +import com.netgrif.quartz.mongodb.Clocks +import com.netgrif.quartz.mongodb.MongoHelper +import com.netgrif.quartz.mongodb.util.Clock import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/dao/TriggerDaoTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/dao/TriggerDaoTest.groovy similarity index 83% rename from src/test/groovy/com/novemberain/quartz/mongodb/dao/TriggerDaoTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/dao/TriggerDaoTest.groovy index 188896ee..1386ace5 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/dao/TriggerDaoTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/dao/TriggerDaoTest.groovy @@ -1,18 +1,18 @@ -package com.novemberain.quartz.mongodb.dao +package com.netgrif.quartz.mongodb.dao -import com.novemberain.quartz.mongodb.MongoHelper -import com.novemberain.quartz.mongodb.trigger.TriggerConverter -import com.novemberain.quartz.mongodb.util.Keys -import com.novemberain.quartz.mongodb.util.QueryHelper +import com.netgrif.quartz.mongodb.MongoHelper +import com.netgrif.quartz.mongodb.trigger.TriggerConverter +import com.netgrif.quartz.mongodb.util.Keys +import com.netgrif.quartz.mongodb.util.QueryHelper import org.bson.Document import org.quartz.TriggerKey import org.quartz.impl.triggers.SimpleTriggerImpl import spock.lang.Shared import spock.lang.Specification -import static com.novemberain.quartz.mongodb.Constants.STATE_ERROR -import static com.novemberain.quartz.mongodb.Constants.STATE_PAUSED -import static com.novemberain.quartz.mongodb.Constants.STATE_WAITING +import static com.netgrif.quartz.mongodb.Constants.STATE_ERROR +import static com.netgrif.quartz.mongodb.Constants.STATE_PAUSED +import static com.netgrif.quartz.mongodb.Constants.STATE_WAITING class TriggerDaoTest extends Specification { diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/trigger/TriggerConverterTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/trigger/TriggerConverterTest.groovy similarity index 90% rename from src/test/groovy/com/novemberain/quartz/mongodb/trigger/TriggerConverterTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/trigger/TriggerConverterTest.groovy index be607862..dc02a155 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/trigger/TriggerConverterTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/trigger/TriggerConverterTest.groovy @@ -1,12 +1,11 @@ -package com.novemberain.quartz.mongodb.trigger +package com.netgrif.quartz.mongodb.trigger -import com.novemberain.quartz.mongodb.Constants -import com.novemberain.quartz.mongodb.JobDataConverter -import com.novemberain.quartz.mongodb.dao.JobDao -import com.novemberain.quartz.mongodb.dao.TriggerDao -import com.novemberain.quartz.mongodb.util.Keys + +import com.netgrif.quartz.mongodb.JobDataConverter +import com.netgrif.quartz.mongodb.dao.JobDao +import com.netgrif.quartz.mongodb.dao.TriggerDao +import com.netgrif.quartz.mongodb.util.Keys import org.bson.Document -import org.quartz.TriggerKey import org.quartz.impl.triggers.SimpleTriggerImpl import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/com/novemberain/quartz/mongodb/util/ExpiryCalculatorTest.groovy b/src/test/groovy/com/netgrif/quartz/mongodb/util/ExpiryCalculatorTest.groovy similarity index 92% rename from src/test/groovy/com/novemberain/quartz/mongodb/util/ExpiryCalculatorTest.groovy rename to src/test/groovy/com/netgrif/quartz/mongodb/util/ExpiryCalculatorTest.groovy index 5d6b1c96..26287ab8 100644 --- a/src/test/groovy/com/novemberain/quartz/mongodb/util/ExpiryCalculatorTest.groovy +++ b/src/test/groovy/com/netgrif/quartz/mongodb/util/ExpiryCalculatorTest.groovy @@ -1,9 +1,9 @@ -package com.novemberain.quartz.mongodb.util +package com.netgrif.quartz.mongodb.util -import com.novemberain.quartz.mongodb.Clocks -import com.novemberain.quartz.mongodb.Constants -import com.novemberain.quartz.mongodb.cluster.Scheduler -import com.novemberain.quartz.mongodb.dao.SchedulerDao +import com.netgrif.quartz.mongodb.Clocks +import com.netgrif.quartz.mongodb.Constants +import com.netgrif.quartz.mongodb.cluster.Scheduler +import com.netgrif.quartz.mongodb.dao.SchedulerDao import org.bson.Document import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/it/MongoDBJobStoreTest.groovy b/src/test/groovy/it/MongoDBJobStoreTest.groovy index 04131b17..788fbc75 100644 --- a/src/test/groovy/it/MongoDBJobStoreTest.groovy +++ b/src/test/groovy/it/MongoDBJobStoreTest.groovy @@ -1,8 +1,8 @@ package it import com.mongodb.client.model.Updates -import com.novemberain.quartz.mongodb.MongoDBJobStore -import com.novemberain.quartz.mongodb.MongoHelper +import com.netgrif.quartz.mongodb.MongoDBJobStore +import com.netgrif.quartz.mongodb.MongoHelper import org.bson.Document import org.bson.types.ObjectId import org.quartz.CalendarIntervalScheduleBuilder @@ -24,11 +24,10 @@ import org.quartz.spi.OperableTrigger import spock.lang.Specification import spock.lang.Subject -import static com.novemberain.quartz.mongodb.QuartzHelper.in2Months -import static com.novemberain.quartz.mongodb.QuartzHelper.inSeconds +import static com.netgrif.quartz.mongodb.QuartzHelper.in2Months +import static com.netgrif.quartz.mongodb.QuartzHelper.inSeconds import static org.quartz.DateBuilder.IntervalUnit.* import static org.quartz.Trigger.TriggerState.* -import static org.quartz.Trigger.TriggerState.PAUSED class MongoDBJobStoreTest extends Specification { diff --git a/src/test/groovy/it/QuartzWithMongoDbStoreTest.groovy b/src/test/groovy/it/QuartzWithMongoDbStoreTest.groovy index 7d191fae..acb45e79 100644 --- a/src/test/groovy/it/QuartzWithMongoDbStoreTest.groovy +++ b/src/test/groovy/it/QuartzWithMongoDbStoreTest.groovy @@ -1,7 +1,7 @@ package it -import com.novemberain.quartz.mongodb.MongoHelper -import com.novemberain.quartz.mongodb.QuartzHelper +import com.netgrif.quartz.mongodb.MongoHelper +import com.netgrif.quartz.mongodb.QuartzHelper import org.quartz.CalendarIntervalScheduleBuilder import org.quartz.Job import org.quartz.JobBuilder @@ -22,7 +22,7 @@ import spock.lang.Specification import java.util.concurrent.CountDownLatch import java.util.concurrent.atomic.AtomicInteger -import static com.novemberain.quartz.mongodb.QuartzHelper.inSeconds +import static com.netgrif.quartz.mongodb.QuartzHelper.inSeconds import static org.quartz.impl.matchers.GroupMatcher.groupEquals /** diff --git a/src/test/java/com/netgrif/mongo/quartz/DeadJob.java b/src/test/java/com/netgrif/mongo/quartz/DeadJob.java new file mode 100644 index 00000000..08a9d21e --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/DeadJob.java @@ -0,0 +1,61 @@ +package com.netgrif.mongo.quartz; + +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import java.util.concurrent.CountDownLatch; + + +public class DeadJob { + + public static final CountDownLatch job2RunSignaler = new CountDownLatch(1); + public static final CountDownLatch job3RunSignaler = new CountDownLatch(1); + public static final CountDownLatch job4RunSignaler = new CountDownLatch(3); + + + public static class DeadJob1 implements Job { + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + System.out.println("Executing DeadJob1"); + throw new IllegalStateException("Should not be executed!"); + } + } + + + public static class DeadJob2 implements Job { + @Override + public void execute(JobExecutionContext ctx) throws JobExecutionException { + System.out.println("Executing DeadJob2"); + if (ctx.isRecovering()) { + throw new IllegalStateException("Should not be in recovering state!"); + } + job2RunSignaler.countDown(); + } + } + + + public static class DeadJob3 implements Job { + @Override + public void execute(JobExecutionContext ctx) throws JobExecutionException { + System.out.println("Executing DeadJob3"); + if (!ctx.isRecovering()) { + throw new IllegalStateException("Should not be in recovering state!"); + } + job3RunSignaler.countDown(); + } + } + + + public static class DeadJob4 implements Job { + @Override + public void execute(JobExecutionContext ctx) throws JobExecutionException { + System.out.println("Executing DeadJob4"); + if (!ctx.isRecovering()) { + throw new IllegalStateException("Should not be in recovering state!"); + } + job4RunSignaler.countDown(); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java b/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java new file mode 100644 index 00000000..e2109a6c --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java @@ -0,0 +1,209 @@ +package com.netgrif.mongo.quartz; + +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.util.Keys; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.impl.triggers.SimpleTriggerImpl; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FailoverTest { + + private static final long quartzFinishWaittimeSecs = 2L; + + + @BeforeEach + public void setup() throws SchedulerException { + MongoHelper.purgeCollections(); + } + + + public void insertSimpleTrigger(Date fireTime, long repeatInterval, int repeatCount) { + insertSimpleTrigger(fireTime, null, repeatInterval, repeatCount); + } + + public void insertSimpleTriggerLong(Date fireTime, long finalFireTime, long repeatInterval, int repeatCount) { + Map data = new HashMap<>(); + data.putAll(commonTriggerData()); + data.put("class", SimpleTriggerImpl.class.getName()); + data.put("startTime", fireTime); + data.put("previousFireTime", fireTime); + data.put("nextFireTime", null); + data.put("finalFireTime", finalFireTime); + data.put("repeatCount", repeatCount); + data.put("repeatInterval", repeatInterval); + + MongoHelper.addTrigger(data); + + } + + public void insertSimpleTrigger(Date fireTime, Date finalFireTime, long repeatInterval, int repeatCount) { + Map data = new HashMap<>(); + data.putAll(commonTriggerData()); + data.put("class", SimpleTriggerImpl.class.getName()); + data.put("startTime", fireTime); + data.put("previousFireTime", fireTime); + data.put("nextFireTime", null); + data.put("finalFireTime", finalFireTime); + data.put("repeatCount", repeatCount); + data.put("repeatInterval", repeatInterval); + + MongoHelper.addTrigger(data); + } + + public void insertOneshotTrigger(Date fireTime) { + insertSimpleTrigger(fireTime, 0, 0); + } + + public void insertTriggerLock(String instanceId) { + Map lockData = new HashMap<>(); + lockData.put(Keys.LOCK_TYPE, Keys.LockType.t.name()); + lockData.put(Keys.KEY_GROUP, "g1"); + lockData.put(Keys.KEY_NAME, "t1"); + lockData.put(Constants.LOCK_INSTANCE_ID, instanceId); + lockData.put(Constants.LOCK_TIME, new Date(1462820481910L)); + + MongoHelper.addLock(lockData); + } + + + @Test + public void shouldExecuteOneShotTriggerOnlyOnce() throws InterruptedException, SchedulerException { + // Set up + insertScheduler("single-node"); + insertJob("DeadJob1", false); + insertOneshotTrigger(new Date(1462820481910L)); + insertTriggerLock("single-node"); + + List cluster = QuartzHelper.createCluster("single-node"); + + TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + + assertEquals(0, MongoHelper.getCount("triggers")); + assertEquals(0, MongoHelper.getCount("locks")); + + QuartzHelper.shutdown(cluster); + } + + @Test + public void shouldReexecuteOtherTriggerFromFailedExecution() throws Exception { + insertScheduler("dead-node"); + insertJob("DeadJob2", false); + insertTrigger(); + insertTriggerLock("dead-node"); + + List cluster = QuartzHelper.createCluster("single-node"); + DeadJob.job2RunSignaler.await(2, TimeUnit.SECONDS); + + assertEquals(0, DeadJob.job2RunSignaler.getCount()); + TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + QuartzHelper.shutdown(cluster); + } + + @Test + public void shouldRecoverOwnOneShotTrigger() throws Exception { + insertScheduler("single-node"); + insertJob("DeadJob3", true); + insertOneshotTrigger(new Date(1462820481910L)); + insertTriggerLock("single-node"); + + List cluster = QuartzHelper.createCluster("single-node"); + DeadJob.job3RunSignaler.await(2, TimeUnit.SECONDS); + + assertEquals(0, DeadJob.job3RunSignaler.getCount()); + TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + assertEquals(0, MongoHelper.getCount("triggers")); + assertEquals(0, MongoHelper.getCount("jobs")); + assertEquals(0, MongoHelper.getCount("locks")); + QuartzHelper.shutdown(cluster); + } + + @Test + @Disabled("TODO") + public void shouldRecoverOwnRepeatingTrigger() throws Exception { + insertScheduler("single-node"); + insertJob("DeadJob4", true); + insertTriggerLock("single-node"); + long repeatInterval = 1000L; + int repeatCount = 2; + Date fireTime = new Date(); + long finalFireTime = fireTime.getTime() + (repeatInterval * (repeatCount + 1)); + insertSimpleTriggerLong(fireTime, finalFireTime, repeatInterval, repeatCount); + + List cluster = QuartzHelper.createCluster("single-node"); + DeadJob.job4RunSignaler.await(5, TimeUnit.SECONDS); + + assertEquals(0, DeadJob.job4RunSignaler.getCount()); + TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + assertEquals(0, MongoHelper.getCount("triggers")); + assertEquals(0, MongoHelper.getCount("jobs")); + assertEquals(0, MongoHelper.getCount("locks")); + QuartzHelper.shutdown(cluster); + } + + + + private void insertScheduler(String id) { + MongoHelper.addScheduler(new HashMap<>() {{ + put("instanceId", id); + put("schedulerName", "test cluster"); + put("lastCheckinTime", 1462806352702L); + put("checkinInterval", 7500L); + }}); + } + + private void insertJob(String jobName, boolean recover) { + MongoHelper.addJob(new HashMap<>() {{ + put("_id", new ObjectId("00000000ee78252adaba4534")); + put("keyName", "job"); + put("keyGroup", "g1"); + put("jobDescription", null); + put("jobClass", "com.netgrif.mongo.quartz.DeadJob$" + jobName); + put("durability", false); + put("requestsRecovery", recover); + }}); + } + + private Map commonTriggerData() { + return new HashMap<>() {{ + put("state", "waiting"); + put("calendarName", null); + put("description", null); + put("endTime", null); + put("fireInstanceId", null); + put("jobId", new ObjectId("00000000ee78252adaba4534")); + put("keyName", "t1"); + put("keyGroup", "g1"); + put("misfireInstruction", 0); + put("nextFireTime", null); + put("priority", 5); + put("timesTriggered", 1); + }}; + } + + private void insertTrigger() { + Map data = commonTriggerData(); + data.putAll(new HashMap<>() {{ + put("class", "org.quartz.impl.triggers.CalendarIntervalTriggerImpl"); + put("startTime", new Date(1462820481910L)); + put("previousFireTime", new Date(1462820481910L)); + put("nextFireTime", new Date(1462820483910L)); + put("finalFireTime", null); + put("repeatIntervalUnit", "SECOND"); + put("repeatInterval", 2); + }}); + MongoHelper.addTrigger(data); + } + +} diff --git a/src/test/java/com/netgrif/mongo/quartz/JobDataConverterTest.java b/src/test/java/com/netgrif/mongo/quartz/JobDataConverterTest.java new file mode 100644 index 00000000..de736e4b --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/JobDataConverterTest.java @@ -0,0 +1,210 @@ +package com.netgrif.mongo.quartz; + + +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.JobDataConverter; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.quartz.JobDataMap; +import org.quartz.JobPersistenceException; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +public class JobDataConverterTest { + + private JobDataConverter converterBase64; + private JobDataConverter converterPlain; + private String base64 = "rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAACdAADc3RydAADMTIzdAADZm9vc3IAMWNvbS5uZXRncmlmLm1vbmdvLnF1YXJ0ei5Kb2JEYXRhQ29udmVydGVyVGVzdCRGb29jnxlZgcJi3AIAAkwAA2JhcnQAM0xjb20vbmV0Z3JpZi9tb25nby9xdWFydHovSm9iRGF0YUNvbnZlcnRlclRlc3QkQmFyO0wAA3N0cnQAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IAMWNvbS5uZXRncmlmLm1vbmdvLnF1YXJ0ei5Kb2JEYXRhQ29udmVydGVyVGVzdCRCYXIeonWPEVlgfwIAAUwAA3N0cnEAfgAHeHB0AANhYmN0AANkZWZ4"; + + @BeforeEach + public void setUp() { + converterBase64 = new JobDataConverter(true); + converterPlain = new JobDataConverter(false); + } + + @Test + public void emptyJobDataDoesNotModifyTheDocument() throws JobPersistenceException { + JobDataMap emptyJobDataMap = new JobDataMap(); + Document doc = new Document(); + + converterBase64.toDocument(emptyJobDataMap, doc); + assertEquals(0, doc.size()); + + converterPlain.toDocument(emptyJobDataMap, doc); + assertEquals(0, doc.size()); + } + + @Test + public void documentWithoutJobDataDoesNotModifyJobDataMap() throws JobPersistenceException { + Document doc = new Document(); + doc.put("foo", "bar"); + doc.put("num", 123); + JobDataMap jobDataMap = new JobDataMap(); + + assertFalse(converterBase64.toJobData(doc, jobDataMap)); + assertEquals(0, jobDataMap.size()); + + assertFalse(converterPlain.toJobData(doc, jobDataMap)); + assertEquals(0, jobDataMap.size()); + } + + @Test + public void testBase64EncodeWorks() throws JobPersistenceException { + JobDataMap jobDataMap = createJobDataWithSerializableContent(); + Document doc = new Document(); + + converterBase64.toDocument(jobDataMap, doc); + assertEquals(1, doc.size()); + assertEquals(base64, doc.get(Constants.JOB_DATA)); + } + + @Test + public void testBase64DecodeWorks() throws JobPersistenceException { + Document doc = new Document(); + doc.put(Constants.JOB_DATA, base64); + JobDataMap jobDataMap = new JobDataMap(); + + assertTrue(converterBase64.toJobData(doc, jobDataMap)); + assertEquals(2, jobDataMap.getWrappedMap().size()); + assertMapEquals(createJobDataWithSerializableContent().getWrappedMap(), jobDataMap.getWrappedMap()); + } + + @Test + public void testBase64DecodeFails() { + Document doc = new Document(); + doc.put(Constants.JOB_DATA, 'a' + base64); + JobDataMap jobDataMap = new JobDataMap(); + + assertThrows(JobPersistenceException.class, () -> { + converterBase64.toJobData(doc, jobDataMap); + }); + } + + @Test + public void testPlainEncodeWorks() throws JobPersistenceException { + JobDataMap jobDataMap = createJobDataWithSimpleContent(); + Document doc = new Document(); + + converterPlain.toDocument(jobDataMap, doc); + assertEquals(1, doc.size()); + assertMapEquals(createJobDataWithSimpleContent().getWrappedMap(), (Map)doc.get(Constants.JOB_DATA_PLAIN)); + } + + @Test + public void testPlainDecodeWorks() throws JobPersistenceException { + Document doc = new Document(); + doc.put(Constants.JOB_DATA_PLAIN, createJobDataWithSimpleContent().getWrappedMap()); + JobDataMap jobDataMap = new JobDataMap(); + + assertTrue(converterPlain.toJobData(doc, jobDataMap)); + assertEquals(2, jobDataMap.getWrappedMap().size()); + + Map expectedMap = createJobDataWithSimpleContent().getWrappedMap(); + Map actualMap = jobDataMap.getWrappedMap(); + + for (String key : expectedMap.keySet()) { + Object expectedValue = expectedMap.get(key); + Object actualValue = actualMap.get(key); + + if (expectedValue instanceof Map) { + assertMapEquals((Map) expectedValue, (Map) actualValue); + } else if (expectedValue instanceof List) { + assertListsEqual((List) expectedValue, (List) actualValue); + } else { + assertEquals(expectedValue, actualValue); + } + } + } + + + + @Test + public void testPlainDecodeFallsBackToBase64() throws JobPersistenceException { + Document doc = new Document(); + doc.put(Constants.JOB_DATA, base64); + JobDataMap jobDataMap = new JobDataMap(); + + assertTrue(converterPlain.toJobData(doc, jobDataMap)); + assertEquals(2, jobDataMap.getWrappedMap().size()); + assertMapEquals(createJobDataWithSerializableContent().getWrappedMap(), jobDataMap.getWrappedMap()); + } + + private JobDataMap createJobDataWithSerializableContent() { + Foo foo = new Foo(new Bar("abc"), "def"); + Map map = new HashMap<>(); + map.put("foo", foo); + map.put("str", "123"); + return new JobDataMap(map); + } + + private JobDataMap createJobDataWithSimpleContent() { + Map map = new HashMap<>(); + map.put("foo", "foo"); + Map barMap = new HashMap<>(); + barMap.put("one", 1); + barMap.put("two", 2.0); + barMap.put("list", new String[]{"a", "b", "c"}); + map.put("bar", barMap); + return new JobDataMap(map); + } + + @ToString + @EqualsAndHashCode + static class Foo implements Serializable { + Bar bar; + String str; + + public Foo(Bar bar, String str) { + this.bar = bar; + this.str = str; + } + } + + @ToString + @EqualsAndHashCode + static class Bar implements Serializable { + String str; + + public Bar(String str) { + this.str = str; + } + } + + private void assertMapEquals(Map expectedMap, Map actualMap) { + assertEquals(expectedMap.size(), actualMap.size()); + for (Object key : expectedMap.keySet()) { + assertTrue(actualMap.containsKey(key)); + Object expectedValue = expectedMap.get(key); + Object actualValue = actualMap.get(key); + + if (expectedValue instanceof Object[] && actualValue instanceof Object[]) { + assertArrayEquals((Object[]) expectedValue, (Object[]) actualValue); + } else { + areEqualKeyValues(expectedMap, actualMap); + } + } + } + + private Map areEqualKeyValues(Map first, Map second) { + return first.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey(), + e -> e.getValue().equals(second.get(e.getKey())))); + } + + + private void assertListsEqual(List expectedList, List actualList) { + assertEquals(expectedList.size(), actualList.size()); + for (int i = 0; i < expectedList.size(); i++) { + assertEquals(expectedList.get(i), actualList.get(i)); + } + } +} diff --git a/src/test/java/com/netgrif/mongo/quartz/LoadBalancingTest.java b/src/test/java/com/netgrif/mongo/quartz/LoadBalancingTest.java new file mode 100644 index 00000000..26ec8462 --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/LoadBalancingTest.java @@ -0,0 +1,66 @@ +package com.netgrif.mongo.quartz; + +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.quartz.*; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@Slf4j +public class LoadBalancingTest { + + private static List counter = new CopyOnWriteArrayList<>(); + private List cluster; + + @BeforeEach + public void setup() throws SchedulerException { + MongoHelper.purgeCollections(); + this.cluster = QuartzHelper.createCluster("BaWiX", "Test"); + } + + + @AfterEach + public void cleanup() throws SchedulerException { + QuartzHelper.shutdown(this.cluster); + } + + @Test + public void shouldExecuteTheJobOnlyOnce() throws InterruptedException, SchedulerException { + counter.clear(); + JobDetail job = JobBuilder.newJob(SharedJob.class) + .withIdentity("job1", "g1") + .build(); + Trigger trigger = TriggerBuilder.newTrigger() + .startAt(new Date(System.currentTimeMillis() + 1000L)) + .withIdentity("t1", "g1") + .build(); + + this.cluster.get(0).scheduleJob(job, trigger); + Thread.sleep(7000); + + assertEquals(1, counter.size()); + } + + public static class SharedJob implements Job { + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + try { + String id = context.getScheduler().getSchedulerInstanceId(); + System.out.println("Shared Job executed by: " + id); + counter.add(id); + Thread.sleep(2000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new JobExecutionException(e); + } catch (SchedulerException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/src/test/java/com/netgrif/mongo/quartz/LockManagerTest.java b/src/test/java/com/netgrif/mongo/quartz/LockManagerTest.java new file mode 100644 index 00000000..852bc484 --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/LockManagerTest.java @@ -0,0 +1,92 @@ +package com.netgrif.mongo.quartz; + +import com.mongodb.MongoWriteException; +import com.mongodb.ServerAddress; +import com.mongodb.WriteError; +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.LockManager; +import com.netgrif.quartz.mongodb.dao.LocksDao; +import com.netgrif.quartz.mongodb.util.ExpiryCalculator; +import org.bson.BsonDocument; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.quartz.TriggerKey; + +import java.util.Date; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class LockManagerTest { + + @Mock + private LocksDao locksDao; + + @Mock + private ExpiryCalculator expiryCalc; + + @InjectMocks + private LockManager manager; + + private TriggerKey tkey; + + @BeforeEach + public void setup() { + tkey = new TriggerKey("n1", "g1"); + } + + private MongoWriteException newWriteException() { + return new MongoWriteException( + new WriteError(1, "Rly!", BsonDocument.parse("{}")), + new ServerAddress()); + } + + @Test + public void tryLockShouldLockTriggerWhenHaveNoLocks() { + manager.tryLock(tkey); + verify(locksDao).lockTrigger(tkey); + } + + @Test + public void tryLockCannotGetExistingLockForExpirationCheck() { + doThrow(newWriteException()).when(locksDao).lockTrigger(tkey); + + assertFalse(manager.tryLock(tkey)); + } + + @Test + public void shouldNotRelockWhenLockIsNotFound() { + when(locksDao.findTriggerLock(tkey)).thenReturn(null); + + assertFalse(manager.relockExpired(tkey)); + } + + @Test + public void shouldNotRelockValidLock() { + Document existingLock = new Document(); + when(locksDao.findTriggerLock(tkey)).thenReturn(existingLock); + when(expiryCalc.isTriggerLockExpired(existingLock)).thenReturn(false); + + assertFalse(manager.relockExpired(tkey)); + } + + @Test + @Disabled("Dorobit...") + public void shouldRelockExpiredLock() { + Date lockTime = new Date(123); + Document existingLock = new Document(Constants.LOCK_TIME, lockTime); + boolean relocked = manager.relockExpired(tkey); + + assert manager.relockExpired(tkey); + } + + +} diff --git a/src/test/java/com/netgrif/mongo/quartz/MongoHelper.java b/src/test/java/com/netgrif/mongo/quartz/MongoHelper.java new file mode 100644 index 00000000..10888575 --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/MongoHelper.java @@ -0,0 +1,107 @@ +package com.netgrif.mongo.quartz; + +import com.mongodb.MongoClientSettings; +import com.mongodb.ServerAddress; +import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; + +import java.util.*; + +public class MongoHelper { + + public static final String testDatabaseName = "quartz_mongodb_test"; + + public static final int DEFAULT_MONGO_PORT = 27017; + + private static final MongoClient client = MongoClients.create( + MongoClientSettings.builder() + .writeConcern(WriteConcern.JOURNALED) + .applyToClusterSettings(builder -> + builder.hosts(Collections.singletonList(new ServerAddress("localhost", DEFAULT_MONGO_PORT))) + ) + .build()); + + private static final MongoDatabase testDatabase = client.getDatabase(testDatabaseName); + + private static final Map> collections = new HashMap<>(); + + static { + collections.put("calendars", testDatabase.getCollection("quartz_calendars")); + collections.put("locks", testDatabase.getCollection("quartz_locks")); + collections.put("jobs", testDatabase.getCollection("quartz_jobs")); + collections.put("jobGroups", testDatabase.getCollection("quartz_paused_job_groups")); + collections.put("schedulers", testDatabase.getCollection("quartz_schedulers")); + collections.put("triggers", testDatabase.getCollection("quartz_triggers")); + collections.put("triggerGroups", testDatabase.getCollection("quartz_paused_trigger_groups")); + } + + public static void dropTestDB() { + testDatabase.drop(); + } + + public static void clearColl(String colKey) { + collections.get(colKey).deleteMany(new Document()); + } + + public static void purgeCollections() { + clearColl("triggers"); + clearColl("jobs"); + clearColl("locks"); + clearColl("calendars"); + clearColl("schedulers"); + clearColl("triggerGroups"); + clearColl("jobGroups"); + } + + public static void addScheduler(Map dataMap) { + collections.get("schedulers").insertOne(new Document(dataMap)); + } + + public static void addJob(Map dataMap) { + collections.get("jobs").insertOne(new Document(dataMap)); + } + + public static void addLock(Map dataMap) { + collections.get("locks").insertOne(new Document(dataMap)); + } + + public static void addTrigger(Map dataMap) { + collections.get("triggers").insertOne(new Document(dataMap)); + } + + public static long getCount(String col) { + return collections.get(col).countDocuments(); + } + + public static MongoCollection getCalendarsColl() { + return collections.get("calendars"); + } + + public static MongoCollection getLocksColl() { + return collections.get("locks"); + } + + public static MongoCollection getSchedulersColl() { + return collections.get("schedulers"); + } + + public static MongoCollection getTriggersColl() { + return collections.get("triggers"); + } + + public static Document getFirst(String col) { + return getFirst(col, new HashMap<>()); + } + + public static Document getFirst(String col, Map amap) { + return collections.get(col).find(new Document(amap)).first(); + } + + public static Collection findAll(String col) { + return collections.get(col).find().into(new ArrayList<>()); + } +} diff --git a/src/test/java/com/netgrif/mongo/quartz/QuartzHelper.java b/src/test/java/com/netgrif/mongo/quartz/QuartzHelper.java new file mode 100755 index 00000000..c88fc79c --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/QuartzHelper.java @@ -0,0 +1,95 @@ +package com.netgrif.mongo.quartz; + +import org.joda.time.DateTime; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.impl.StdSchedulerFactory; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Properties; + +public class QuartzHelper { + + /** + * Creates standard properties with MongoDBJobStore. + */ + public static Properties createProps() { + Properties props = new Properties(); + props.setProperty("org.quartz.jobStore.class", "com.netgrif.quartz.mongodb.DynamicMongoDBJobStore"); + props.setProperty("org.quartz.jobStore.mongoUri", "mongodb://localhost:" + MongoHelper.DEFAULT_MONGO_PORT); + props.setProperty("org.quartz.scheduler.idleWaitTime", "1000"); + props.setProperty("org.quartz.jobStore.dbName", "quartz_mongodb_test"); + props.setProperty("org.quartz.threadPool.threadCount", "1"); + props.setProperty("org.quartz.scheduler.skipUpdateCheck", "true"); + props.setProperty("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingTriggerHistoryPlugin"); + props.setProperty("org.quartz.plugin.jobHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin"); + return props; + } + + /** + * Creates properties for clustered scheduler. + */ + public static Properties createClusteredProps(String instanceName) { + Properties props = createProps(); + props.setProperty("org.quartz.jobStore.isClustered", "true"); + props.setProperty("org.quartz.scheduler.instanceId", instanceName); + props.setProperty("org.quartz.scheduler.instanceName", "test cluster"); + return props; + } + + /** + * Create a new Scheduler with the following properties. + */ + public static Scheduler createScheduler(Properties properties) throws SchedulerException { + StdSchedulerFactory factory = new StdSchedulerFactory(); + factory.initialize(properties); + Scheduler scheduler = factory.getScheduler(); + scheduler.start(); + return scheduler; + } + + /** + * Create and start the default scheduler. + */ + public static Scheduler startDefaultScheduler() throws SchedulerException { + return createScheduler(createProps()); + } + + public static Scheduler createClusteredScheduler(String instanceName) throws SchedulerException { + return createScheduler(createClusteredProps(instanceName)); + } + + /** + * Creates a cluster of schedulers with given names. + */ + public static List createCluster(String... names) throws SchedulerException { + List schedulers = new ArrayList<>(); + for (String name : names) { + schedulers.add(createClusteredScheduler(name)); + } + return schedulers; + } + + /** + * Shutdown all schedulers in given cluster. + */ + public static void shutdown(List cluster) { + for (Scheduler scheduler : cluster) { + try { + scheduler.shutdown(); + } catch (SchedulerException e) { + e.printStackTrace(); + } + } + } + + public static Date inSeconds(int n) { + return DateTime.now().plusSeconds(n).toDate(); + } + + public static Date in2Months() { + return DateTime.now().plusMonths(2).toDate(); + } +} diff --git a/src/test/java/com/netgrif/mongo/quartz/TriggerStateManagerTest.java b/src/test/java/com/netgrif/mongo/quartz/TriggerStateManagerTest.java new file mode 100644 index 00000000..124e5825 --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/TriggerStateManagerTest.java @@ -0,0 +1,87 @@ +package com.netgrif.mongo.quartz; + + +import com.netgrif.quartz.mongodb.Constants; +import com.netgrif.quartz.mongodb.TriggerStateManager; +import com.netgrif.quartz.mongodb.dao.JobDao; +import com.netgrif.quartz.mongodb.dao.PausedJobGroupsDao; +import com.netgrif.quartz.mongodb.dao.PausedTriggerGroupsDao; +import com.netgrif.quartz.mongodb.dao.TriggerDao; +import com.netgrif.quartz.mongodb.util.QueryHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.quartz.TriggerKey; + +import java.util.*; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TriggerStateManagerTest { + + @Mock + private TriggerDao triggerDao; + + @Mock + private JobDao jobDao; + + @Mock + private PausedJobGroupsDao pausedJobGroupsDao; + + @Mock + private PausedTriggerGroupsDao pausedTriggerGroupsDao; + + @Mock + private QueryHelper queryHelper; + + @InjectMocks + private TriggerStateManager stateManager; + + private static final TriggerKey triggerKey = new TriggerKey("t-name", "t-group"); + + @BeforeEach + void setUp() { + stateManager = new TriggerStateManager(triggerDao, jobDao, pausedJobGroupsDao, pausedTriggerGroupsDao, queryHelper); + } + + @Test + void resetTriggerFromErrorStateShouldDoNothingWhenTriggerIsNotInErrorState() { + when(triggerDao.getState(triggerKey)).thenReturn(Constants.STATE_WAITING); + + stateManager.resetTriggerFromErrorState(triggerKey); + + verifyNoInteractions(pausedTriggerGroupsDao); + verifyNoMoreInteractions(triggerDao); + } + + @Test + void resetTriggerFromErrorStateShouldSetWaitingStateWhenTriggerIsInErrorState() { + when(triggerDao.getState(triggerKey)).thenReturn(Constants.STATE_ERROR); + HashSet pausedGroups = new HashSet<>(); + pausedGroups.add("g1"); + doReturn(pausedGroups).when(pausedTriggerGroupsDao).getPausedGroups(); + + stateManager.resetTriggerFromErrorState(triggerKey); + + verify(pausedTriggerGroupsDao).getPausedGroups(); + verify(triggerDao).transferState(triggerKey, Constants.STATE_ERROR, Constants.STATE_WAITING); + } + + @Test + void resetTriggerFromErrorStateShouldSetPausedStateWhenTriggerIsInPausedGroup() { + when(triggerDao.getState(triggerKey)).thenReturn(Constants.STATE_ERROR); + HashSet pausedGroups = new HashSet<>(); + pausedGroups.add("g1"); + pausedGroups.add(triggerKey.getGroup()); + doReturn(pausedGroups).when(pausedTriggerGroupsDao).getPausedGroups(); + + stateManager.resetTriggerFromErrorState(triggerKey); + + verify(pausedTriggerGroupsDao).getPausedGroups(); + verify(triggerDao).transferState(triggerKey, Constants.STATE_ERROR, Constants.STATE_PAUSED); + } +} diff --git a/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java b/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java new file mode 100644 index 00000000..9871fcc2 --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java @@ -0,0 +1,4 @@ +package com.netgrif.mongo.quartz.cluster; + +public class CheckinTaskTest { +} diff --git a/src/test/java/com/netgrif/mongo/quartz/cluster/SchedulerTest.java b/src/test/java/com/netgrif/mongo/quartz/cluster/SchedulerTest.java new file mode 100644 index 00000000..a258e5e4 --- /dev/null +++ b/src/test/java/com/netgrif/mongo/quartz/cluster/SchedulerTest.java @@ -0,0 +1,4 @@ +package com.netgrif.mongo.quartz.cluster; + +public class SchedulerTest { +} From e448d6866ab9c8ad92a14fce6659c4b478749ecb Mon Sep 17 00:00:00 2001 From: Machac Date: Thu, 7 Dec 2023 11:42:32 +0100 Subject: [PATCH 02/10] Change message --- .../com/netgrif/quartz/mongodb/cluster/CheckinTask.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java index a40626c0..9802ad08 100755 --- a/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java @@ -32,7 +32,7 @@ public void run() { } catch (MongoWriteConcernException e) { handleWriteConcernException(e); } catch (Exception e) { - log.error("TOTOK: Neočakávaná chyba počas check-in: " + e.getMessage(), e); + log.error("Unexpected error during check-in: " + e.getMessage(), e); //errorHandler.run(); //TODO: ups.. } } @@ -46,12 +46,12 @@ private void handleWriteConcernException(MongoWriteConcernException e) { run(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); - log.error("TOTOK: Thread interrupted during retry delay", ie); + log.error("Thread interrupted during retry delay", ie); } catch (Exception ee) { - log.error("TOTOK: shit.." +ee.getMessage() , ee); + log.error("Hups..." +ee.getMessage() , ee); } } else { - log.error("TOTOK: Maximum number of attempts reached. Unable to complete check-in.", e); + log.error("Maximum number of attempts reached. Unable to complete check-in.", e); errorHandler.run(); } } From b7233394be2f708cc7eb50106d19d0f15d589f3a Mon Sep 17 00:00:00 2001 From: Machac Date: Mon, 18 Dec 2023 11:47:23 +0100 Subject: [PATCH 03/10] Change message --- .../java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java index 9802ad08..69421750 100755 --- a/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java +++ b/src/main/java/com/netgrif/quartz/mongodb/cluster/CheckinTask.java @@ -1,4 +1,4 @@ - package com.netgrif.quartz.mongodb.cluster; +package com.netgrif.quartz.mongodb.cluster; import com.mongodb.MongoWriteConcernException; import com.netgrif.quartz.mongodb.dao.SchedulerDao; From 452e8d1dd0476a92c87bc76a64d2f6ba97af1662 Mon Sep 17 00:00:00 2001 From: Machac Date: Wed, 17 Jan 2024 15:38:47 +0100 Subject: [PATCH 04/10] Fix group id --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 29332136..382030a3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.netgrif.quartz + com.netgrif quartz-mongodb-connector 1.0.0-SNAPSHOT From 01e1560f4c4577d453974a9d765bfafb93703185 Mon Sep 17 00:00:00 2001 From: Machac Date: Wed, 17 Jan 2024 16:08:17 +0100 Subject: [PATCH 05/10] Github --- .github/workflows/pr-build.yml | 64 +++++++++++++++++++ .github/workflows/publish.yml | 21 ------ .github/workflows/release-build.yml | 99 +++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/pr-build.yml delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release-build.yml diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml new file mode 100644 index 00000000..f8d6ec77 --- /dev/null +++ b/.github/workflows/pr-build.yml @@ -0,0 +1,64 @@ +name: Pull Request +on: + pull_request: + types: [ opened, synchronize, reopened ] + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: 'adopt' + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build + run: mvn clean verify -DskipTests=true + + test: + name: Test + needs: build + runs-on: ubuntu-latest + timeout-minutes: 200 + + steps: + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: 'adopt' + + - name: Cache SonarCloud packages + uses: actions/cache@v3 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build + run: mvn clean package install -DskipTests=true + + - name: Build, test + timeout-minutes: 180 + run: mvn -B test \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 3db59ba1..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Publish Bintray -on: - release: - types: [published] - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Grant Permission to Execute - run: chmod +x gradlew - - name: Publish Library - env: - BINTRAY_USERNAME: ${{ secrets.BINTRAY_USERNAME }} - BINTRAY_API_KEY: ${{ secrets.BINTRAY_API_KEY }} - run: ./gradlew bintrayUpload \ No newline at end of file diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml new file mode 100644 index 00000000..26a4a2b7 --- /dev/null +++ b/.github/workflows/release-build.yml @@ -0,0 +1,99 @@ +name: Publish package to GitHub Packages +on: + release: + types: [ published ] + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: 'adopt' + - uses: cardinalby/git-get-release-action@v1 + id: getEnvRelease + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Project Version from pom.xml + uses: entimaniac/read-pom-version-action@1.0.0 + id: getVersion + + # - name: Check Enviroment release + # if: ${{ !((steps.getEnvRelease.outputs.prerelease && contains(steps.getVersion.outputs.version, '-SNAPSHOT')) || (!steps.getEnvRelease.outputs.prerelease && !contains(steps.getVersion.outputs.version, '-SNAPSHOT'))) }} + # run: exit 1 + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build + run: mvn clean verify + + publish-OSSRH: + runs-on: ubuntu-latest + name: Publish to Maven Central + needs: test + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v3 + + - id: install-secret-key + name: Install gpg secret key + run: | + cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import + gpg --list-secret-keys --keyid-format LONG + + - name: Set up Maven Central Repository + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: 'adopt' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + - name: Publish package + run: mvn -DskipTests=true --batch-mode -P ossrh-publish -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} deploy + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} + + publish-artifact: + name: GitHub Artifacts + needs: test + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Publish artifact on GitHub Packages + run: mvn -B -P github-publish clean deploy -DskipTests + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 269df4479b51cf8e2a12ec2c941e042a667348ff Mon Sep 17 00:00:00 2001 From: Machac Date: Thu, 18 Jan 2024 10:20:02 +0100 Subject: [PATCH 06/10] Github --- .github/workflows/pr-build.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index f8d6ec77..0ae923c0 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -8,6 +8,9 @@ jobs: name: Build runs-on: ubuntu-latest steps: + - name: List directory structure + run: ls -alh + - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -42,13 +45,6 @@ jobs: java-version: 11 distribution: 'adopt' - - name: Cache SonarCloud packages - uses: actions/cache@v3 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Cache Maven packages uses: actions/cache@v3 with: From 78b2fe82b70f355fe243ee105dd093e06d39b26a Mon Sep 17 00:00:00 2001 From: Machac Date: Thu, 18 Jan 2024 10:22:34 +0100 Subject: [PATCH 07/10] Github --- .github/workflows/pr-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 0ae923c0..aecafca3 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -8,8 +8,6 @@ jobs: name: Build runs-on: ubuntu-latest steps: - - name: List directory structure - run: ls -alh - uses: actions/checkout@v3 with: @@ -48,6 +46,7 @@ jobs: - name: Cache Maven packages uses: actions/cache@v3 with: + fetch-depth: 0 path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 From 3ffb71236f1d77df4395fb3195833e7ce7c74d17 Mon Sep 17 00:00:00 2001 From: Machac Date: Thu, 18 Jan 2024 10:28:17 +0100 Subject: [PATCH 08/10] Github --- .github/workflows/pr-build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index aecafca3..9061fe58 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -34,9 +34,12 @@ jobs: needs: build runs-on: ubuntu-latest timeout-minutes: 200 - steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up JDK 11 uses: actions/setup-java@v3 with: @@ -46,7 +49,6 @@ jobs: - name: Cache Maven packages uses: actions/cache@v3 with: - fetch-depth: 0 path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 From ae1c4295d5fde3fb76fd81c29376422ff1892de1 Mon Sep 17 00:00:00 2001 From: Machac Date: Thu, 18 Jan 2024 10:33:17 +0100 Subject: [PATCH 09/10] Github --- .github/workflows/pr-build.yml | 5 +++++ .github/workflows/release-build.yml | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 9061fe58..2d05e6df 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -34,6 +34,11 @@ jobs: needs: build runs-on: ubuntu-latest timeout-minutes: 200 + services: + mongo: + image: mongo:4.4 + ports: + - 27017:27017 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 26a4a2b7..af316a41 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -7,6 +7,11 @@ jobs: build: name: Build runs-on: ubuntu-latest + services: + mongo: + image: mongo:4.4 + ports: + - 27017:27017 steps: - uses: actions/checkout@v3 with: @@ -49,6 +54,8 @@ jobs: packages: write steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 - id: install-secret-key name: Install gpg secret key @@ -80,6 +87,8 @@ jobs: packages: write steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 - uses: actions/setup-java@v3 with: From 2561afbf38e3b9b5268e66ce455efb0eabc9b1c5 Mon Sep 17 00:00:00 2001 From: Machac Date: Thu, 18 Jan 2024 10:48:29 +0100 Subject: [PATCH 10/10] Github --- .../com/netgrif/quartz/mongodb/MongoDBJobStore.java | 6 ------ .../netgrif/quartz/mongodb/MongoStoreAssembler.java | 12 ++++++------ .../java/com/netgrif/mongo/quartz/FailoverTest.java | 10 +++++----- .../mongo/quartz/cluster/CheckinTaskTest.java | 1 + 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java b/src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java index 16e16e78..3b533677 100755 --- a/src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java +++ b/src/main/java/com/netgrif/quartz/mongodb/MongoDBJobStore.java @@ -14,8 +14,6 @@ import org.quartz.impl.matchers.GroupMatcher; import org.quartz.spi.*; import org.quartz.Calendar; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.*; import java.util.*; @@ -24,9 +22,6 @@ public class MongoDBJobStore implements JobStore, Constants { - private static final Logger log = LoggerFactory.getLogger(MongoDBJobStore.class); - - private MongoStoreAssembler assembler = new MongoStoreAssembler(); MongoConnector mongoConnector; @@ -102,7 +97,6 @@ protected ClassLoadHelper getClassLoaderHelper(ClassLoadHelper original) { public void initialize(ClassLoadHelper loadHelper, SchedulerSignaler signaler) throws SchedulerConfigException { Properties props = loadProperties(loadHelper); - log.info("Init MongoQuartz connector"); try { assembler.build(this, loadHelper, signaler, props); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { diff --git a/src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java b/src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java index 99b4db49..facee9d8 100755 --- a/src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java +++ b/src/main/java/com/netgrif/quartz/mongodb/MongoStoreAssembler.java @@ -42,8 +42,8 @@ public class MongoStoreAssembler { public void build(MongoDBJobStore jobStore, ClassLoadHelper loadHelper, SchedulerSignaler signaler, Properties quartzProps) - throws SchedulerConfigException, ClassNotFoundException, - IllegalAccessException, InstantiationException { + throws SchedulerConfigException, ClassNotFoundException, + IllegalAccessException, InstantiationException { mongoConnector = createMongoConnector(jobStore); JobDataConverter jobDataConverter = new JobDataConverter(jobStore.isJobDataAsBase64()); @@ -83,17 +83,17 @@ public void build(MongoDBJobStore jobStore, ClassLoadHelper loadHelper, private CheckinExecutor createCheckinExecutor(MongoDBJobStore jobStore, ClassLoadHelper loadHelper, Properties quartzProps) - throws ClassNotFoundException, InstantiationException, IllegalAccessException { + throws ClassNotFoundException, InstantiationException, IllegalAccessException { return new CheckinExecutor(createCheckinTask(jobStore, loadHelper), jobStore.clusterCheckinIntervalMillis, jobStore.instanceId); } private Runnable createCheckinTask(MongoDBJobStore jobStore, ClassLoadHelper loadHelper) - throws ClassNotFoundException, IllegalAccessException, InstantiationException { + throws ClassNotFoundException, IllegalAccessException, InstantiationException { Runnable errorHandler; Class aClass; if (jobStore.getCheckInErrorHandler() == null) { - // TOTO je blbe :/ + // TODO: Refactor aClass = KamikazeErrorHandler.class; } else { aClass = loadHelper.loadClass(jobStore.getCheckInErrorHandler()); @@ -121,7 +121,7 @@ private LocksDao createLocksDao(MongoDBJobStore jobStore) { private LockManager createLockManager(MongoDBJobStore jobStore) { ExpiryCalculator expiryCalculator = new ExpiryCalculator(schedulerDao, - Clock.SYSTEM_CLOCK, jobStore.jobTimeoutMillis, jobStore.triggerTimeoutMillis,jobStore.isClustered()); + Clock.SYSTEM_CLOCK, jobStore.jobTimeoutMillis, jobStore.triggerTimeoutMillis, jobStore.isClustered()); return new LockManager(locksDao, expiryCalculator); } diff --git a/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java b/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java index e2109a6c..a699bd4e 100644 --- a/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java +++ b/src/test/java/com/netgrif/mongo/quartz/FailoverTest.java @@ -20,7 +20,7 @@ public class FailoverTest { - private static final long quartzFinishWaittimeSecs = 2L; + private static final long QUARTZ_FINISH_WAITTIME_SECS = 2L; @BeforeEach @@ -88,7 +88,7 @@ public void shouldExecuteOneShotTriggerOnlyOnce() throws InterruptedException, S List cluster = QuartzHelper.createCluster("single-node"); - TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + TimeUnit.SECONDS.sleep(QUARTZ_FINISH_WAITTIME_SECS); assertEquals(0, MongoHelper.getCount("triggers")); assertEquals(0, MongoHelper.getCount("locks")); @@ -107,7 +107,7 @@ public void shouldReexecuteOtherTriggerFromFailedExecution() throws Exception { DeadJob.job2RunSignaler.await(2, TimeUnit.SECONDS); assertEquals(0, DeadJob.job2RunSignaler.getCount()); - TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + TimeUnit.SECONDS.sleep(QUARTZ_FINISH_WAITTIME_SECS); QuartzHelper.shutdown(cluster); } @@ -122,7 +122,7 @@ public void shouldRecoverOwnOneShotTrigger() throws Exception { DeadJob.job3RunSignaler.await(2, TimeUnit.SECONDS); assertEquals(0, DeadJob.job3RunSignaler.getCount()); - TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + TimeUnit.SECONDS.sleep(QUARTZ_FINISH_WAITTIME_SECS); assertEquals(0, MongoHelper.getCount("triggers")); assertEquals(0, MongoHelper.getCount("jobs")); assertEquals(0, MongoHelper.getCount("locks")); @@ -145,7 +145,7 @@ public void shouldRecoverOwnRepeatingTrigger() throws Exception { DeadJob.job4RunSignaler.await(5, TimeUnit.SECONDS); assertEquals(0, DeadJob.job4RunSignaler.getCount()); - TimeUnit.SECONDS.sleep(quartzFinishWaittimeSecs); + TimeUnit.SECONDS.sleep(QUARTZ_FINISH_WAITTIME_SECS); assertEquals(0, MongoHelper.getCount("triggers")); assertEquals(0, MongoHelper.getCount("jobs")); assertEquals(0, MongoHelper.getCount("locks")); diff --git a/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java b/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java index 9871fcc2..d48d1fc7 100644 --- a/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java +++ b/src/test/java/com/netgrif/mongo/quartz/cluster/CheckinTaskTest.java @@ -1,4 +1,5 @@ package com.netgrif.mongo.quartz.cluster; public class CheckinTaskTest { + //TODO: plz create new test :) }