Skip to main content

Recurring jobs

A recurring job runs on a cron schedule and takes no payload. Implement RecurringJob and put the schedule on @FlareJob:

import com.zeridion.flare.worker.FlareJob;
import com.zeridion.flare.worker.JobContext;
import com.zeridion.flare.worker.RecurringJob;

@FlareJob(name = "NightlyCleanup", cron = "0 3 * * *", queue = "maintenance", timezone = "UTC")
public final class NightlyCleanup implements RecurringJob {
public void execute(JobContext ctx) throws Exception {
db.purgeExpiredSessions();
}
}

Register it with registerRecurring:

FlareWorker.builder(client)
.registerRecurring(NightlyCleanup.class, NightlyCleanup::new)
.build();

How the schedule is applied

When the worker starts, it announces every recurring schedule to Flare as part of registration. Flare owns the timer: it evaluates the cron expression and, on each due tick, enqueues a run that the worker picks up through the same poll loop as any other job. Your worker does not run its own scheduler.

Always set the timezone

cron alone is ambiguous — 0 3 * * * means "03:00", but 03:00 where? Set timezone to an IANA zone (for example "UTC", "America/New_York", "Europe/Berlin") so the schedule fires at the wall-clock time you intend. If you omit it, Flare applies a default zone, which is almost certainly not what a non-UTC schedule wants.

Idempotency still applies

Like payload jobs, a recurring run is delivered at-least-once, so the handler must be safe to run more than once for the same scheduled occurrence. Guard any non-idempotent side effect on ctx.jobId().

Configuration carried with the schedule

queue, maxAttempts, and timeoutSeconds from the annotation are announced alongside the schedule, so a recurring run is retried and timed out using the same rules as a directly-enqueued job.