Scheduler¶
imbi-scheduler triggers remote execution on a schedule. It runs on port 8005
and is served under /scheduler in the all-in-one image.
The scheduler triggers; it does not execute work. Every run is a single synchronous HTTP call, and the outcome is recorded. Two target kinds cover the platform:
| Target | Goes to | Runs as |
|---|---|---|
api |
imbi-api |
the scheduler's service account. A delegated user is phase 2: such a task is stored, but every firing is skipped until the exchange grant lands |
gateway |
imbi-gateway |
nothing — the endpoint has no bearer check and derives attribution from the payload |
Long-running work, agentic execution, and rule evaluation belong to whichever service owns them. The scheduler pokes that service and records what came back.
How a run happens¶
- A trigger comes due. The claiming query
(
FOR UPDATE SKIP LOCKEDoverscheduler.tasks) gives exactly one replica the claim: concurrent replicas receive disjoint task sets, and the claiming transaction advancesnext_run_atbefore committing. That bounds the claim, not delivery — execution is at-most-once, so see ADR 0001. - The task's identity is resolved at fire time, never at creation time. A
service_accounttask uses the scheduler's own client credential; adelegated_usertask will exchange that credential for a short-lived token scoped to the target user, onceimbi-apiimplements the exchange grant — until then such a task is stored but every firing isskipped(ADR 0003).gatewaytargets skip this step. - The target is rendered.
path,body,query, and header values are Jinja2 templates over{now, task, run, last_run}, matching the templating modelimbi-automationsuses so operators learn it once. - One HTTP call, bounded by the task's
timeout, retried per its policy. - The result is classified and written to
imbi.scheduler_runsin ClickHouse.
A failure to resolve identity is a skipped run, not a failed one, and it does
not consume retries — consent that has been revoked should stop a task quietly
rather than look like an outage.
Stores¶
| Data | Where |
|---|---|
| Task definitions, trigger state | Postgres, schema scheduler |
| Run history | ClickHouse, imbi.scheduler_runs |
| Consent for delegated tasks | The graph, owned by imbi-api. The scheduler stores only a consent_id |
The scheduler stores no secrets. See ADR 0002.
Relationship to pg_cron¶
Both are kept, deliberately. pg_cron is the system-level, in-database
operations tool; it runs SQL. imbi-scheduler is the user-level tool; it calls
endpoints and carries an identity. No overlap, no migration.
Design decisions¶
- ADR 0001: Trigger engine on psycopg3 rather than APScheduler
- ADR 0002: No encrypted credential store in v1
- ADR 0003: No local token-minting bridge
The imbi-api side of delegated execution is
ADR 0016.