ic-timers 0.2.0

Observable and recovery-aware timers for Internet Computer canisters
Documentation

ic-timers

ic-timers is a higher-level wrapper around ic-cdk-timers for Internet Computer canisters. It does not replace the CDK timer provider: ic-cdk-timers still arms and clears the platform timers. This crate is intended to add one place for timer identity, scheduling policy, execution arbitration, observability, and lifecycle recovery.

This repository is currently a pre-alpha foundation, not a production timer runtime.

Why wrap ic-cdk-timers?

ic-cdk-timers provides the low-level mechanism a canister needs to schedule callbacks. That is the right boundary for a simple timer. The abstraction gets harder to operate when a framework, a database, and application code all schedule recurring work independently.

Direct, scattered use gives each subsystem its own private answers to questions such as:

  • Which logical timers exist in this canister, and who owns them?
  • Is a callback scheduled, running, overdue, cancelled, or stale?
  • When did it last run, what happened, and how expensive was it?
  • What should happen after an upgrade or a trapped callback?
  • Does “recurring” mean after-completion scheduling or a recovery watchdog?

We thought a wrapper was worthwhile because those are canister-wide concerns. If every consumer builds its own registry, recurrence loop, metrics, and upgrade restoration, operators still cannot obtain one reliable inventory and the most failure-sensitive logic is duplicated. ic-timers is intended to put that coordination above the proven CDK provider while keeping the provider dependency behind a small platform boundary.

The wrapper deliberately uses one-shot provider timers. A higher layer can then decide when a successor becomes authoritative: after successful work for ordinary recurrence, or before fallible work for a recovery watchdog. Those policies have different failure guarantees and should not be hidden behind the same interval helper.

What exists today

The current crate contains a compiling foundation extracted from Canic's timer implementation:

  • deterministic generation, cancellation, reconciliation, and stale-callback arbitration;
  • typed scheduling directives and overflow-safe deadline calculation; and
  • a deliberately thin one-shot boundary over ic-cdk-timers 1.0.0; and
  • candidate 0.2 provider-neutral identity, policy, state, outcome, counter, measurement, epoch, and canonical snapshot value types.

The shared canister-wide registry, live snapshot population, measured execution, lifecycle reconstruction, pre-armed watchdog recurrence, metrics adapters, and PocketIC recovery evidence are not implemented yet. Recovery-critical consumers should continue using their proven timer implementation until those guarantees exist. See the architecture note for the intended boundary and implementation order, and the proposed observability contract for the 0.2 snapshot and Canic metrics-parity requirements. The safety boundary lists the guarantees that are and are not currently backed by implementation evidence.

Intended use

Canic and IcyDB motivated the shared wrapper. Canic needs framework timers and lifecycle integration; IcyDB needs a recovery watchdog; an application may add more timers of its own. All of them should eventually declare timers into one canister-local registry so an operator can answer “what timers exist in this canister?” from one snapshot.

For a canister with one simple callback and no need for shared inventory, metrics, or recovery policy, using ic-cdk-timers directly remains the simpler choice.

Development

make update-dev
make ci

make update-dev installs the pinned Rust toolchain, Clippy, rustfmt, the Wasm target, and this repository's single formatting hook. Normal development uses Rust 1.97.1; make msrv checks the declared Rust 1.91.0 minimum separately. make help lists the smaller component targets.

License

MIT