Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scheduler: add db-scheduler module #3511

Merged
merged 1 commit into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 215 additions & 0 deletions docs/asciidoc/modules/db-scheduler.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
== db-scheduler

Task scheduler module using https://github.com/kagkarlsson/db-scheduler[db-scheduler].

=== Usage

1) Add the dependencies (hikari):

[dependency, artifactId="jooby-hikari:DataSource via HikariCP, jooby-db-scheduler:Db Scheduler Module"]
.

2) Add database driver (mySQL here):

[dependency, groupId="mysql", artifactId="mysql-connector-java", version="${mysql-connector-java.version}"]
.

3) Install DbScheduler. Add SampleJob:

.Java
[source, java, role="primary"]
----
import io.jooby.dbscheduler.DbSchedulerModule;

{
install(new HikariModule());
install(new DbSchedulerModule(Tasks.recurring(...)));
}
----

.Kotlin
[source, kt, role="secondary"]
----
import io.jooby.dbscheduler.DbSchedulerModule

{
install(DbSchedulerModule(Tasks.recurring(...)))
}
----

=== Tasks

Tasks are created as described in https://github.com/kagkarlsson/db-scheduler[db-scheduler documentation]. Optionally,
you can annotate a method with the javadoc:dbscheduler.Scheduled[] annotation:

.Sample Job
[source, java, role="primary"]
----
import io.jooby.dbscheduler.Scheduled;

public class SampleJob {

@Scheduled("1m")
public void everyMinute() {
...
}
}
----

.Kotlin
[source, kt, role="secondary"]
----
import io.jooby.dbscheduler.Scheduled

class SampleJob {

@Scheduled("1m")
fun everyMinute() : Unit {
...
}
}
----

Once you annotate your method you must create task from them with:

.Bean Tasks
[source, java]
----
import io.jooby.dbscheduler.BeanTasks;

{
install(new HikariModule());
install(new DbSchedulerModule(BeanTasks.recurring(this, SampleJob.class)));
}
----

A task method must follow these rules:

- Must be a public method
- Possible arguments: none (zero), `TaskInstance`, `ExecutionContext`, `task data` or any other application service.
- Return value: Task can return a value, which is persisted by DbScheduler. This is known as task data or task state.

=== Scheduled

The javadoc:dbscheduler.Scheduled[] annotation supports simple and cron triggers as well as property references:

.Same as .fixedDelay(Duration) with duration.
----
@Scheduled("1h")
----

.Same as .fixedDelay(Duration) with duration set to N seconds.
----
@Scheduled("FIXED_DELAY|Ns")
----

.Same as .daily(LocalTime) with optional time zone (e.g. Europe/Rome, UTC)
----
@Scheduled("DAILY|12:30,15:30...(|time_zone)")
----

.Cron, every 5 minutes
----
@Scheduled("0 0/5 * * * ?")
----

.Cron, fires every 5 minutes, at 10 seconds after the minute (i.e. 10:00:10 am, 10:05:10 am, etc.)
----
@Scheduled("10 0/5 * * * ?")
----

.Property reference
----
@Scheduled("mytask.trigger")
----

The `mytask.trigger` must be defined in your application property file. It could be a any of previous expressions.

=== Configuration

Configuration from properties files is fully supported, just need to add javadoc:dbscheduler.DbSchedulerProperties[] properties to your
application configuration file:

.Options
[source, properties]
----
# Turn on/off scheduler.
db-scheduler.enabled = true
# Set number of threads to use, default is to use the number of available processor
db-scheduler.threads = 8
db-scheduler.pollingInterval = 10s
db-scheduler.alwaysPersistTimestampInUTC = true
db-scheduler.enableImmediateExecution = false
# No need to use registerShutdownHook, the scheduler is shutdown on application shutdown
db-scheduler.registerShutdownHook = false
db-scheduler.shutdownMaxWait = 1s
----

Check more configuration options at https://github.com/kagkarlsson/db-scheduler?tab=readme-ov-file#configuration[configuration]

=== REST API

This modules comes with a simple REST API (sort of) to manage tasks:

.Scheduler API
[source, java, role="primary"]
----
import io.jooby.dbscheduler.DbSchedulerApp;
import io.jooby.dbscheduler.DbSchedulerModule;

{
install(new DbScheduler(SampleJob.class));

mount("/scheduler", new DbSchedulerApp());
}
----

.Kotlin
[source, kt, role="secondary"]
----
import io.jooby.dbscheduler.DbSchedulerApp
import io.jooby.dbscheduler.DbSchedulerModule

{
install(DbScheduler(SampleJob::class.java))

mount("/scheduler", DbSchedulerApp())
}
----

The API supports all these operations:

.List all tasks
----
GET /
----

.Running tasks
----
GET /running
----

.List tasks
----
GET /{taskName}
----

.Reschedule a task
----
GET /{taskName}/reschedule
----

.Pause schedule
----
GET /pause
----

.Resume
----
GET /resume
----

.State
----
GET /state
----
6 changes: 3 additions & 3 deletions docs/asciidoc/modules/modules.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ Available modules are listed next.
* link:/modules/thymeleaf[Thymeleaf]: Thymeleaf template engine.

=== Security
* link:/modules/jasypt[Jasypt]: Encripted configuration files.
* link:/modules/jasypt[Jasypt]: Encrypted configuration files.
* link:/modules/pac4j[Pac4j]: Security engine module.

=== Session Store
* link:/modules/caffeine[Caffeine]: In-memory session store using Caffeine cache.
* link:/modules/jwt-session-store[JWT]: JSON Web Token session store.
* link:/modules/redis#redis-http-session[Redis]: Save session data on redis.

=== Misc
* link:/modules/node[Node]: Node integration module.
=== Scheduler
* link:/modules/db-scheduler[DbScheduler]: Db scheduler module.
* link:/modules/quartz[Quartz]: Quartz scheduler module.

.
8 changes: 4 additions & 4 deletions docs/asciidoc/templates.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Templates are available via javadoc:ModelAndView[] and requires a javadoc:Templa
[source, java, role = "primary"]
----
{
install(new MyTemplateEngineModule()); <1>
install(new MyTemplateEngineModule()); <1>

get("/", ctx -> {
MyModel model = ...; <2>
MyModel model = ...; <2>
return new ModelAndView("index.html", model); <3>
});
}
Expand All @@ -22,8 +22,8 @@ Templates are available via javadoc:ModelAndView[] and requires a javadoc:Templa
install(MyTemplateEngineModule()) <1>

get("/") { ctx ->
val model = MyModel(...) <2>
ModelAndView("index.html", model) <3>
val model = MyModel(...) <2>
ModelAndView("index.html", model) <3>
}
}
----
Expand Down
4 changes: 2 additions & 2 deletions docs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<dependency>
<groupId>me.tongfei</groupId>
<artifactId>progressbar</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
</dependency>

<dependency>
Expand Down Expand Up @@ -100,7 +100,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<version>3.4.1</version>
<executions>
<execution>
<id>asciidoctor</id>
Expand Down
4 changes: 2 additions & 2 deletions docs/src/main/java/io/jooby/adoc/DocGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
int adocCount =
Stream.of(treeDirs)
.map(throwingFunction(dir -> countAdoc(asciidoc.resolve(dir))))
.reduce(1, (a, b) -> a + b);
.reduce(1, Integer::sum);
int steps = 7 + (doAscii ? adocCount : 0);

ProgressBarBuilder pbb =
Expand All @@ -71,7 +71,7 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
.setInitialMax(steps)
.setTaskName("Building Site");

try (ProgressBar pb = pbb.build()) {
try (var pb = pbb.build()) {

Path outdir = asciidoc.resolve("site");
if (!Files.exists(outdir)) {
Expand Down
5 changes: 5 additions & 0 deletions modules/jooby-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@
<artifactId>jooby-conscrypt</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-db-scheduler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-distribution</artifactId>
Expand Down
43 changes: 43 additions & 0 deletions modules/jooby-db-scheduler/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<parent>
<groupId>io.jooby</groupId>
<artifactId>modules</artifactId>
<version>3.2.10-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<artifactId>jooby-db-scheduler</artifactId>

<dependencies>
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby</artifactId>
<version>${jooby.version}</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.github.kagkarlsson/db-scheduler -->
<dependency>
<groupId>com.github.kagkarlsson</groupId>
<artifactId>db-scheduler</artifactId>
<version>14.0.3</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Loading