Quartz workflow scheduler
|
Preview — This feature is functional and tested, but backward compatibility is not guaranteed across releases. |
The Open Workflow specification allows you to define workflows that execute automatically on a recurring schedule.
By default, the Open Workflow SDK engine uses a lightweight, in-memory implementation (based on ScheduledExecutorService and the cron-utils library) to trigger these executions.
Additionally, Quarkus Flow provides a native Quarkus scheduler for standalone deployments. However, for a production-grade Quarkus application deployed as a cluster of multiple instances, you must back the Quartz scheduler with a persistent, clustered JDBC job store (store-type=jdbc-cmt, clustered=true) to guarantee correct behavior. The reverse is also true: do not use it for standalone deployments.
This guide shows how to:
-
Enable the Quartz Flow Scheduler.
-
Define a recurring schedule in your workflow.
Quarkus Flow does not set Quartz clustering properties for applications that add the Quartz
extension. Configure them explicitly for a JDBC job store. Each distinct application sharing a
Quartz database needs a unique, stable quarkus.quartz.instance-name; all replicas of that
application must use the same name. This value becomes Quartz’s SCHED_NAME, which partitions
the shared Quartz tables. Changing it leaves existing jobs under the old name. Set
quarkus.quartz.instance-id=AUTO so each replica has its own Quartz instance ID.
Prerequisites
-
A Quarkus application with Quarkus Flow set up.
1. Add the Quartz Scheduler dependency
To replace the default engine scheduler with the Quartz Scheduler, the first step is to add the quarkus-flow-quartz-scheduler extension to your project.
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-quartz-scheduler</artifactId>
<version>${project.version}</version>
</dependency>
Adding this dependency automatically wires Quarkus Flow to use the underlying Quarkus Quartz scheduling infrastructure. This gives you access to robust application lifecycle management and all standard Quarkus Scheduler configuration properties.
Quarkus Quartz scheduler requires persistence to properly function in a clustered environment.
Currently, Quarkus Quartz only supports relational DB.
Add the quarkus-flow-db-migration-quartz extension to get a versioned, packaged Flyway script that creates the tables Quarkus Quartz needs,
see Database Schema Migration for the full picture of what it ships and why it uses a named datasource.
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-db-migration-quartz</artifactId>
<version>${project.version}</version>
</dependency>
Point Quartz at a named datasource so its schema migration stays isolated from any Flyway history your application manages for its own tables,
then set up your DB connection details and driver as indicated in Quarkus Datasource guide.
quarkus-flow-db-migration-quartz only ships a PostgreSQL migration script, so the db-kind must be postgresql:
# Quartz configuration
quarkus.quartz.instance-name=${quarkus.application.name}
quarkus.quartz.clustered=true
quarkus.quartz.instance-id=AUTO
quarkus.quartz.store-type=jdbc-cmt
quarkus.quartz.datasource=flow-quartz
quarkus.quartz.misfire-policy.task-job=ignore-misfire-policy
# Datasource configuration - same DB Quartz will use, under the "flow-quartz" name.
quarkus.datasource.flow-quartz.db-kind=postgresql
quarkus.datasource.flow-quartz.username=<replace with your postgresql user>
quarkus.datasource.flow-quartz.password=<replace with your postgresql password>
quarkus.datasource.flow-quartz.jdbc.url=jdbc:postgresql://<replace with db host name>/<replace with your database name>
# flyway configuration
quarkus.flyway.flow-quartz.connect-retries=10
quarkus.flyway.flow-quartz.table=flyway_flow_quartz_history
quarkus.flyway.flow-quartz.locations=db/flow-migration/quartz/postgresql
quarkus.flyway.flow-quartz.migrate-at-start=true
This is the setup for a genuinely new database with no QRTZ_* tables yet,
the migration above runs as an ordinary first migration, no baseline needed.
If your database already has these tables (from a prior manual Flyway setup, or Quarkus Quartz’s own bootstrap),
see Database Schema Migration's baseline guidance instead.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
|
Upgrading from a setup where the QRTZ_\* script shipped on Flyway’s default classpath location inside |
2. Define a schedule in your workflow
You can define a schedule directly in your workflow definition. The specification supports three scheduling formats:
-
cron: A Quartz CRON expression. -
every: An ISO-8601 duration (e.g.,PT15Mfor every 15 minutes) representing the interval between executions. -
after: An ISO-8601 duration representing a delay before the workflow starts.
Example: YAML Definition
Here is an example of a workflow that executes automatically every second using a CRON expression:
document:
dsl: '1.0.0'
namespace: org.acme
name: ScheduledJob
version: '1.0'
schedule:
cron: "* * * * * ?"
do:
- runTask:
call: http
with:
method: POST
endpoint: "https://api.example.com/sync"
Quartz cron format
The Open Workflow specification mandates that CRON expressions follow the standard Unix format.
The Quarkus Quartz Scheduler, however, uses the Quartz format. This means that, if you are using the Unix format in your workflow definition, you should change the CRON expression to use Quartz format.
See also
-
Open Workflow Specification: Scheduling — full details and edge cases for the
every,after, andcronsyntax.