Schedule Java pipelines
Create cron, interval and one-time schedules, then inspect, pause, trigger and archive them with typed APIs.
Schedules are durable server definitions. Create one from a producer, then let any compatible worker execute its pipelines. A Java process does not need to stay alive merely to keep the schedule registered.
The Java demo includes ScheduleExample.java. Build it as described in getting started, export the API settings in each terminal, and keep OrdersExample or WorkflowExample worker running.
Create a cron schedule
The typed API uses the same stages as an ordinary pipeline:
import io.pipelogiq.sdk.Pipelogiq;
import io.pipelogiq.sdk.core.client.CatchupPolicy;
import io.pipelogiq.sdk.core.client.OverlapPolicy;
import java.math.BigDecimal;
// Inside a method using the getting-started Order and stage classes:
try (var client = Pipelogiq.connect("pipelogiq.yml")) {
var schedule = client.schedule("weekday-orders")
.cron("0 9 * * 1-5", "Europe/Tallinn")
.overlapPolicy(OverlapPolicy.SKIP)
.catchup(CatchupPolicy.ONE)
.label("service", "orders")
.stage(ValidateOrder.class, new Order("scheduled", new BigDecimal("10.00")))
.stage(RecordOrder.class)
.apply();
System.out.println(schedule.name() + ": " + schedule.nextRunAt());
}This runs at 09:00 on weekdays in Europe/Tallinn. Cron uses five fields: minute, hour, day of month, month, day of week. It is not Quartz's six-field syntax with seconds. The server interprets the IANA time zone and daylight-saving transitions. .cron(expression) defaults to UTC.
Equivalent CLI:
java -cp 'target/classes:target/dependency/*' example.ScheduleExample cron demo-weekdays '0 9 * * 1-5' Europe/TallinnCreation prints the schedule's status, kind and next run time. apply() upserts an application-scoped, case-insensitive name. Reapplying an unchanged definition preserves its cursor and definition version; use distinct names for separate schedules.
Use an interval or one-time execution
Replace the timing method in the same draft with one of these alternatives:
.every(java.time.Duration.ofMinutes(10)).runOnceAt(java.time.Instant.now().plusSeconds(60))Intervals use whole seconds and must be at least 10 seconds. One-time schedules use an absolute instant and become archived after firing. The CLI accepts a relative delay for convenience:
java -cp 'target/classes:target/dependency/*' example.ScheduleExample interval demo-interval 60
java -cp 'target/classes:target/dependency/*' example.ScheduleExample once demo-once 60Each scheduled tick creates a new pipeline. The recurring example's order payload remains the same template each time; real recurring business logic should derive its processing window or business identity from the intended job, not assume every tick receives a new order ID.
Choose execution policies
| Setting | Choices and purpose |
|---|---|
.overlapPolicy(...) | SKIP, QUEUE, REPLACE, ALLOW; server policy when previous work is in flight |
.catchup(...) | NONE, ONE, ALL; server policy for missed schedule times |
.catchup(CatchupPolicy.ALL, max) | Bound catch-up generation; max is 1–1000 |
.jitter(Duration) | Whole-second dispatch jitter, from zero to one hour |
The example explicitly selects SKIP and ONE. These policies affect durable scheduling; they do not increase worker concurrency or change a stage's retry rules. Test catch-up, overlap and time-zone behavior against your server deployment before relying on them for business windows.
Stored definitions contain stages, labels and context. Request credentials and one-off request identity are not part of the reusable schedule definition.
Inspect and operate a schedule
java -cp 'target/classes:target/dependency/*' example.ScheduleExample list
java -cp 'target/classes:target/dependency/*' example.ScheduleExample get demo-weekdays
java -cp 'target/classes:target/dependency/*' example.ScheduleExample pause demo-weekdays
java -cp 'target/classes:target/dependency/*' example.ScheduleExample trigger demo-weekdays
java -cp 'target/classes:target/dependency/*' example.ScheduleExample history demo-weekdays
java -cp 'target/classes:target/dependency/*' example.ScheduleExample resume demo-weekdaystrigger prints a pipeline ID. Observe that execution with CreatePipelineExample wait <id> 60. Manual triggering does not advance the regular schedule cursor. An optional typed input override replaces the first stage's input for that manual run:
try (var client = Pipelogiq.connect("pipelogiq.yml")) {
var run = client.schedules().trigger("weekday-orders",
new Order("manual-001", new BigDecimal("20.00")));
System.out.println(run.pipelineId());
}This fragment uses the imports and Order class from the cron example. get exposes status, timing, definition version, health and last/next run information. history returns run outcomes and linked pipeline IDs, which can still be running when queried.
Read paginated history
The CLI prints the first page and its next cursor. To consume all pages, use the typed response:
try (var client = Pipelogiq.connect("pipelogiq.yml")) {
String cursor = null;
do {
var page = client.schedules().history("weekday-orders", cursor, 50);
for (var run : page.runs()) {
System.out.println(run.id() + " -> " + run.pipelineId() + " / " + run.pipelineStatus());
}
cursor = page.hasNext() ? page.nextCursor() : null;
} while (cursor != null);
}client.schedules().list(status, cursor, limit) provides equivalent pagination for definitions. list() and list(ScheduleStatus.ACTIVE) cover the common first-page cases without optional arguments. Named asynchronous variants are available for management operations.
Clean up the example schedules
Recurring schedules continue until paused or archived. Archive both recurring examples when finished:
java -cp 'target/classes:target/dependency/*' example.ScheduleExample archive demo-weekdays
java -cp 'target/classes:target/dependency/*' example.ScheduleExample archive demo-interval
java -cp 'target/classes:target/dependency/*' example.ScheduleExample get demo-onceArchive the one-time schedule too if it has not fired and you want to cancel its future tick. Archiving retains the definition and history; it does not cancel already-created pipelines. Use client.pipelines().cancel(id) for those.