Skip to main content

after_secs

Function after_secs 

Source
pub fn after_secs(secs: u64) -> Action
Expand 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-level TICK_RETRY / HEARTBEAT / SHORT_RETRY constants at every FSM handler’s tail (the pending / forking / execing / running / attested / reconverging / releasing / exiting / failed / zombie / reaped arms).
  • tatara-reconciler::controller — 5 sites feeding literal 1 (deletion-preemption + signal-arm re-poll), the ctx.config.heartbeat_seconds slot (suspend), and 30 (reconcile-error sink + error_policy).
  • tatara-reconciler::table_controller — 2 sites feeding 30 at the ProcessTable heartbeat + error policy.
  • tatara-pool-reconciler::controller_pool — 3 sites feeding the reconcile-interval slot + literal 15.
  • tatara-pool-reconciler::controller_allocation — 3 sites feeding literal 5 (bind-retry), the reconcile-interval slot, and literal 15.

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.