pub fn after_secs(secs: u64) -> ActionExpand description
A kube::runtime::controller::Action that re-enqueues the
current object secs seconds from now — the one-line
Action::requeue(Duration::from_secs(secs)) two-link chain
lifted to ONE typed owner past the ★★ PRIME-DIRECTIVE ≥ 2
duplication threshold.
Pre-lift the SAME chain was hand-authored at 35 workspace-wide consumer sites across 5 files in the two ACTIVE reconciler crates:
tatara-reconciler::phase_machine— 22 sites feeding the module-levelTICK_RETRY/HEARTBEAT/SHORT_RETRYconstants at every FSM handler’s tail (thepending/forking/execing/running/attested/reconverging/releasing/exiting/failed/zombie/reapedarms).tatara-reconciler::controller— 5 sites feeding literal1(deletion-preemption + signal-arm re-poll), thectx.config.heartbeat_secondsslot (suspend), and30(reconcile-error sink +error_policy).tatara-reconciler::table_controller— 2 sites feeding30at the ProcessTable heartbeat + error policy.tatara-pool-reconciler::controller_pool— 3 sites feeding the reconcile-interval slot + literal15.tatara-pool-reconciler::controller_allocation— 3 sites feeding literal5(bind-retry), the reconcile-interval slot, and literal15.
All 35 sites walked the SAME two-link chain — take a whole-
second u64 (a literal, a named constant, or a config slot),
wrap it in a std::time::Duration via from_secs, then hand
the duration to Action::requeue. Differing only in the
second-count operand. Post-lift each callsite reads
tatara_process::requeue::after_secs(N) and the wrap +
requeue chain lives at ONE substrate owner.
Return-form axis: kube::runtime::controller::Action — the
exact type every kube-runtime reconcile fn returns as
Ok(...) and every error_policy returns bare. The u64
secs parameter matches Duration::from_secs’s own signature
so the migration is byte-identical: every pre-lift site fed a
u64 (either a literal, a named pub const N: u64 = ...;, or
a config field typed as u64) directly into Duration:: from_secs, and the same feed continues to work at
after_secs.
A future normalization — an injectable jitter overlay that
randomizes ±10% of secs to avoid a thundering herd of
synchronized reconcile ticks, a per-controller
floor/ceiling clamp so a mis-configured heartbeat can’t drive
the API server, an injectable deterministic clock so
integration tests can advance requeue budgets without waiting
wall-clock time, a per-fleet rate limiter that spreads bursts
across a sliding window, a tracing-annotated span carrying
the requeue reason for post-hoc audit — lands at THIS ONE
substrate primitive and every downstream retry sink across
the two active reconciler crates inherits the upgrade
mechanically. No per-site edit at any of the 35 listed
callers or at future consumers (a new phase handler, a new
controller crate, a per-Kind retry sink).
Sibling to the timed-decision primitives in crate::time
on the “second-count → typed timed value” axis: seconds_ago(N) -> DateTime<Utc> seeds a wall-clock anchor N seconds in the
past for elapsed_since consumers; after_secs(N) -> Action
seeds a kube-runtime requeue N seconds in the future. Both
carry the same “u64 seconds is the workspace’s canonical
short-time unit” invariant so a switch to a finer-grained unit
(a millisecond-precision retry budget for tight probes) would
land at both primitives together rather than as scattered per-
site conversions.