Skip to content

Task Scheduler

OpenTremor Core has no scheduler of its own — no periodic loop, no cron. OpenTremor-task-scheduler is a small standalone process that fills that gap by calling core’s admin HTTP endpoints on an interval, the same “talks to core at runtime, not the code level” relationship the dashboard and docs site have. See Data Retention, Platform Admin — Deleting an organization, and Platform Admin — Retrying a failed job for the three features this currently drives.

Reads a jobs: list from its own config file — {name, method, path, heartbeat_minutes} — and calls {core.base_url}{path} on that interval, forever. The three jobs shipped today:

jobs:
- name: retention_sweep
method: POST
path: /admin/retention/run
heartbeat_minutes: 15
- name: org_purge
method: POST
path: /admin/organizations/purge-pending
heartbeat_minutes: 60
- name: jobs_sweep
method: POST
path: /admin/jobs/sweep
heartbeat_minutes: 15

heartbeat_minutes is deliberately short and dumb for all three. The real schedule (retention.sweep_interval_hours / org_offboarding.grace_period_days / jobs.sweep_interval_hours, all admin-configurable on core itself) lives on core, which either self-gates (retention and jobs_sweep: a call before the interval has elapsed returns the previous result with skipped: true) or naturally no-ops (org purge: nothing to do until an org is actually past its grace period) instead of doing real work on every tick. The scheduler doesn’t know or care what “retention”, “org offboarding”, or “stuck job” mean — it just needs to ping often enough that a due action gets picked up promptly. More jobs are config additions here, not new scheduler code.

Authenticates with core’s bootstrap auth.api_key, not a per-service API key created via POST /auth/keys — a regular service account is always scoped to one org with an OrgRole (owner/admin/member/viewer) and can never be is_superadmin, which POST /admin/retention/run requires. The bootstrap key is the one credential in core that’s both usable with no database round-trip and always superadmin, by design (see configuration/reference/#auth) — reusing it here is the same bootstrap-independence reasoning that credential already exists for, not a new exception carved out for this repo.

Set OPENTREMOR_SCHEDULER_API_KEY to the target core instance’s auth.api_key — treat it with the same care as core’s own config (a secret store or Kubernetes Secret in production, never a plaintext value committed anywhere).

Terminal window
poetry install
CONFIG_FILE=configs/opentremor-task-scheduler.yaml \
OPENTREMOR_SCHEDULER_API_KEY=<core's auth.api_key> \
poetry run python src/server.py

Or via the workspace’s docker-compose.dev.yaml / docker-compose.prod.yaml, which already wire a task-scheduler service pointed at opentremor-core:8000.

  • GET /healthz — process liveness (used by the container HEALTHCHECK).
  • GET /jobs — last tick per configured job: timestamp, ok/error, HTTP status, a short response summary. This is only “did the heartbeat itself succeed” — core’s own GET /admin/retention/status is the durable record of what a sweep actually did.