Scheduling Plugins¶
When to read this: Agora's built-in interval schedules are not expressive enough and you need cron-style timing.
Use the scheduling family when simple fixed intervals are not expressive enough for how your jobs should run.
In the official agora-etl-plugins 0.4.x line, cron scheduling is an official
helper surface. It is intentionally narrow: it calculates and validates
calendar timing, while Agora core owns the worker runtime and distributed
coordination owns multi-replica lease safety.
Install¶
pip install "agora-etl-plugins[cron]"
What it does¶
The scheduling plugin adds cron-expression support on top of Agora's worker and runner model.
It provides:
- cron expression validation
- calculation of the next scheduled run time
That sounds small, but it matters when a job should follow calendar rules instead of just “every N seconds.”
When it is useful¶
- every weekday at a fixed local time
- every hour at minute 15
- first day of the month
- jobs that should align with business calendars instead of raw intervals
Production checklist¶
- Give every scheduled pipeline a stable
pipeline_id. - Use cron expressions for wall-clock schedules and fixed intervals for simple recurring delays.
- Pair cron schedules with distributed coordination when the same schedule runs on more than one worker replica.
- Keep business-calendar exceptions in application code unless they become a reusable scheduling abstraction.
Sample¶
This example validates a cron expression and computes the next delay before a worker should trigger the pipeline again.
import time
from agora_plugins.cron import seconds_until_next_run, validate_cron_expression
expression = "15 * * * *"
validate_cron_expression(expression)
delay_s = seconds_until_next_run(expression, time.time())
print(f"sleep for {delay_s:.1f} seconds before the next run")
What this shows:
- the cron plugin is about schedule calculation, not record movement
- validation happens before the worker loop trusts an expression
- it works well when jobs follow wall-clock rules instead of fixed intervals
Worker example¶
In practice the cron plugin is most often used through Schedule.cron(...)
inside a scheduled worker.
from agora.runner import Schedule, ScheduledPipeline, WorkerPool
async def build_daily_pipeline():
return make_pipeline()
def get_worker() -> WorkerPool:
pool = WorkerPool()
pool.register(
ScheduledPipeline(
factory=build_daily_pipeline,
schedule=Schedule.cron("0 2 * * 1-5"),
pipeline_id="weekday-2am-sync",
)
)
return pool
Use this when the question is not just "how long should I sleep?" but "how do I embed calendar timing into a real long-lived Agora worker?"
Why keep it as a plugin¶
Cron parsing pulls in calendar semantics and an extra dependency. That is useful for scheduled jobs, but it does not need to live in the core runtime for every installation.
Boundary¶
Use the scheduling plugin when the question is “when should this run next?”
If the question becomes “which worker in the fleet should own this run?”, that belongs to Distributed Coordination.