Monitor Rust scheduled tasks: tokio-cron-scheduler and reqwest ping on Ok/Err
In a tokio-cron-scheduler async job closure, call your job
function and match the Result: on
Ok GET the ping URL; on Err POST the error
string to /fail. Spawn with tokio::task::spawn
to catch panics via the JoinHandle. Absence detection
handles OOM kills and crashed processes. Free, no monitor cap.
The snippets
Create a monitor in
the console, set the
schedule plus a grace window, and add these crates to
Cargo.toml: tokio-cron-scheduler,
reqwest, tokio.
tokio-cron-scheduler — match on Ok/Err
Catch panics via JoinHandle
Rust panics in async tasks unwind the task but the scheduler
keeps running. Spawning the job body as a separate task and
awaiting the JoinHandle lets you detect a panic
and send a /fail ping:
Plain tokio interval (no cron syntax)
If you don't need cron syntax, a tokio::time::interval
loop is simpler and avoids an extra crate. The same
match pattern applies:
Why OOM kills still need absence detection
Even Rust can be OOM-killed. The spawned task and the scheduler both vanish with the process; no async code runs. Absence detection is the correct safety net: no ping within schedule+grace → incident. See also the Go monitoring guide for a similar defer-based pattern, and the LastPing MCP server for AI-agent provisioning.
What this catches
The match reports what it can; the silence reports the rest.
- A returned Err — the
/failping opens an incident immediately with the error string stored. - A panic — caught via
JoinHandle::awaitreturningErr(JoinError); the payload is POST'd to/fail. - OOM kill or SIGKILL — no async code runs; the missing ping opens the incident after the grace window.
- The binary never started — missing cron entry, deployment failure. Absence → incident.
- Recovery — the next successful run closes the incident and sends a recovery notice automatically.
Questions people ask
Front-loaded answers — the most important fact first.
-
What crates do I need?
tokio-cron-schedulerfor scheduling,reqwestfor HTTP, andtokiowith the full feature set. A plaintokio::time::intervalloop removes the scheduler dependency if cron syntax isn't needed. -
How do I catch panics in async Rust?
Spawn the job body with
tokio::task::spawnand await the returnedJoinHandle. If the handle returnsErr(JoinError)the task panicked; format the error and POST it to/fail. -
Can I use a different HTTP client?
Yes.
hyper,ureq(blocking), or the standard library'sstd::net::TcpStreamwith a manual HTTP request all work. The ping is a plain GET or POST — no special client required. -
Is this free?
Yes. LastPing is free and fully hosted with no monitor cap and no paid tier. See how it compares to Healthchecks.io and Cronitor.
Even Rust can be OOM-killed. Absence detection is the safety net.
One match arm now beats debugging a silent batch window later. First alert wired up in about a minute — and LastPing monitors itself the same way.