tpt-scheduler
RustLightweight, pure-Rust distributed job scheduler with exactly-once execution (Raft), typed job contracts, and built-in dead-letter queues — a modern alternative to cron and heavyweight orchestrators like Airflow/Temporal.
Languages
tpt-scheduler
A strongly-typed, distributed job-scheduling system written in pure Rust.
Define jobs as .tpt-job contracts, run them as a single-binary cron
replacement, or scale them out across a Raft-backed cluster with exactly-once
execution, typed inputs/outputs, retries, dead-letter queues, and optional
Wasm/OS-level sandboxing.
Dual-licensed MIT OR Apache-2.0.
Why tpt-scheduler?
| vs. | tpt-scheduler | Notes |
|---|---|---|
| cron | Typed jobs, retries, DLQ, distributed, observable. | Classic cron is stateless and fails silently. |
| Airflow | Single Rust binary, no Python/JVM, no heavyweight scheduler daemon. | Airflow is powerful but operationally heavy. |
| Temporal | Lightweight, Raft-native, no external datastore to operate. | Temporal needs a separate persistence service. |
tpt-scheduler targets teams that want cron-like simplicity with distributed
guarantees and a small footprint.
Quickstart (local mode)
No cluster required — run jobs on one machine.
# 1. Build the CLI
cargo build --release -p tpt-cli
export PATH="$PWD/target/release:$PATH"
# 2. Generate a signing keypair (job definitions are signed)
tpt keygen
# 3. Write a job (see examples/ for annotated samples)
cat > jobs/DailyReport.tpt-job <<'EOF'
job DailyReport {
schedule: "0 2 * * *";
timezone: "UTC";
input: ReportRequest { date: Date };
output: ReportSummary;
retry { max_attempts: 3; backoff: exponential(base: 2s, max: 1m); }
}
EOF
# 4. Validate without submitting
tpt job validate jobs/DailyReport.tpt-job
tpt job dry-run jobs/DailyReport.tpt-job # preview next run times
# 5. Submit and run locally (single-binary cron replacement)
tpt job submit jobs/DailyReport.tpt-job
tpt local run --jobs jobs --concurrency 4
# 6. Inspect state
tpt job list
tpt job inspect 1
tpt dlq list
Cluster mode (optional)
# Node 1 (bootstrap)
tpt cluster bootstrap --id 1 --addr 127.0.0.1:21001 --admin-addr 127.0.0.1:21101
# Node 2 (join)
tpt cluster join --id 2 --addr 127.0.0.1:21002 --admin-addr 127.0.0.1:21102 \
--seed 127.0.0.1:21101
# Status
tpt cluster status --addr 127.0.0.1:21101
CLI reference
| Command | Description |
|---|---|
tpt keygen | Generate an Ed25519 signing/verify keypair. |
tpt job submit <file> | Sign and store a .tpt-job definition. |
tpt job list / tpt job inspect <id> | List / inspect submitted jobs. |
tpt job validate <file> | Parse and semantically validate a .tpt-job file (no submit). |
tpt job dry-run <file> | Print the next scheduled run times (no submit). |
tpt local run | Run jobs locally as a single-binary cron replacement. |
tpt dlq list / tpt dlq requeue <id> | Inspect / requeue dead-lettered tasks. |
tpt dlq replay <id> | Re-execute a dead-lettered task exactly once. |
tpt cluster bootstrap / join / status | Manage a Raft cluster. |
Enable structured logs with RUST_LOG (e.g. RUST_LOG=info tpt ...).
Metrics
Pass --metrics-addr 127.0.0.1:21199 to tpt local run or tpt cluster bootstrap to expose a Prometheus-scrapable /metrics endpoint reporting
queue depth, succeeded/failed/retry counters, DLQ depth, and worker health.
Components
| Crate | Description |
|---|---|
tpt-cron-parser | Modern, timezone-aware cron expression + interval parser. |
tpt-job-schema | .tpt-job DSL lexer/parser, validation, and code generator. |
tpt-scheduler-core | Raft-based control plane managing state and leases. |
tpt-worker | Execution engine that pulls and runs typed tasks. |
tpt-cli | Command-line interface (tpt binary). |
tpt-client | Programmatic SDK for submitting/inspecting jobs without the CLI. |
tpt-metrics | Prometheus-compatible metrics registry + embedded /metrics endpoint. |
See docs/architecture.md for design rationale and the
topology.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Dependency license policy
Per deny.toml, no dependency may be Apache-2.0-only. Every crate used by
this workspace must be MIT-only or dual MIT/Apache-2.0. CI fails the build on
violation via cargo deny check licenses (and checks CVE/RustSec advisories).