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.