Skip to main content

Module jitter

Module jitter 

Source
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 H tokens in a 5-field cron expression to concrete, deterministic values derived from seed. Each field’s H maps 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 two Hs in the same expression don’t collapse to the same number.