In both templates
Both templates run Chronon next to the product UI, so recurring cleanup and scans share the same Valence-aware context as interactive requests.Typed scripts
Implemented
Register typed script parameters and handler metadata with #[chronon::script].
Schedules and run history
Implemented
Create cron, manual, and run-once jobs with durable revisions, attempts, status, and timings.
Worker pools and regions
Implemented
Pin a job to a pool and a region. Each worker claims one pool.
Gluon hardware placement
Partially Implemented
Run a pool's workers on a Gluon pool with its own minimum vCPU, memory and disk. The pool names are matched by hand for now.
Scheduler stores
Implemented
Run on memory, SQLite, Postgres, or Postgres with Redis through the SchedulerStore port.
Deployment modes
Implemented
Use embedded, coordinator-only, worker, or remote-coordinator builders without changing script handlers. Coordinators elect a leader, so only one runs the scheduler.
Captured actor context
Implemented
Rebuild execution context from stored actor JSON so scheduled work keeps an explicit identity.
Chronon operator UI
Implemented
Manage jobs and inspect scripts and runs on this host at /chronon.
Worker poolsPartially Implemented
Send heavy jobs to bigger machines
Pin a job to a pool with .pool("ocr"), and to a region with .region("us-east"). Each worker claims the one pool named in CHRONON_WORKER_POOL. On hosts managed by Gluon, the OCR workers can run on 8 vCPU, 32 GB machines while the nightly cleanup stays on small ones. Jobs without a pool run on the default pool, named general.let job = JobBuilder::new(&ocr_scan())
.name("ocr-scan")
.cron("*/15 * * * *")?
.pool("ocr")
.region("us-east")
.build()?;
// On the OCR workers: CHRONON_WORKER_POOL=ocrNeeds Gluon →Gluon doesn't set CHRONON_WORKER_POOL for you yet. Set it to match the Gluon pool the worker runs on.
Your jobsWorker poolGluon pool (minimum hardware)
nightly_cleanupno pool set
→general
→generalmin 2 vCPU · 4 GB
ocr_scan.pool("ocr").region("us-east")
→ocr
→ocrmin 8 vCPU · 32 GB
See it in action
Code sample
Taken from the getting-started docs. See all code samples on Resources.
Chronon jobChronon
Typed #[chronon::script] scheduled with JobBuilder
use std::sync::Arc;
use chronon::prelude::*;
use chronon::InMemorySchedulerStore;
#[chronon::script(name = "nightly_cleanup")]
async fn nightly_cleanup(
ctx: Box<dyn ScriptContext>,
retention_days: u32,
) -> chronon::Result<()> {
println!("{}: retaining {retention_days} days", ctx.label());
Ok(())
}
#[tokio::main]
async fn main() -> chronon::Result<()> {
let chronon = Chronon::builder()
.scheduler_store(Arc::new(InMemorySchedulerStore::new()))
.context_factory(Arc::new(JsonScriptContextFactory))
.embedded()
.auto_registry()
.build()?;
let nightly = JobBuilder::new(&nightly_cleanup())
.name("nightly-schedule")
.cron("0 2 * * *")?
.timezone("UTC")
.params(NightlyCleanupParams { retention_days: 7 })
.build()?;
chronon.coordinator_service().upsert_job(nightly).await?;
chronon.run().await
}