Expand description
Deterministic schedule jitter and Jenkins-style H substitution (ADR §4.1).
Jitter MUST be deterministic: HA operator replicas compute identical fire
times without coordinating, and a controller restart re-derives the same value
without persisting it (ADR §4.1, SKILL “Scheduling”). That rules out any RNG
and any reliance on the wall clock. The offset is a pure function of
(seed, slot_start).
§Why a hand-rolled hash
std::collections::hash_map::DefaultHasher is explicitly not guaranteed
stable across Rust releases, so a value persisted/expected by one build could
differ after a toolchain bump — fatal for “identical across replicas/restarts”.
We therefore inline FNV-1a (64-bit), whose constants are fixed by the
algorithm and will never change. No external dependency is added.
§Cron H
croner 2.x does not implement Jenkins-style H. Kopiur treats H as
“deterministic hashed jitter within the field’s range,” resolved here (not in
the cron parser). substitute_h rewrites each H in a 5-field cron to a
concrete value derived from the same FNV hash of the seed, so the resolved
expression is stable per BackupSchedule and parseable by croner.
crate::validate::validate_cron validates the shape by substituting a fixed
placeholder; this function produces the spread.
Functions§
- offset
- Deterministic jitter offset in
[0, max), derived from a stable hash of(seed, slot_start_unix). NO RNG, NO clock. - substitute_
h - Resolve Jenkins-style
Htokens in a 5-field cron expression to concrete, deterministic values derived fromseed. Each field’sHmaps into that field’s natural range (minute 0–59, hour 0–23, day-of-month 1–28, month 1–12, day-of-week 0–6) using a distinct mix of the seed hash, so twoHs in the same expression don’t collapse to the same number.