Use case · Replay

Replay a session, byte for byte

The replay producer is the one advancer. For each recorded event it advances virtual time to the event's timestamp, then feeds it to the same engine code that ran live — so the rebuilt state is byte-identical to the run that produced the recording.

The replay loop

Construct a VirtualClockat the session start, then walk the recorded events. Advance to each event's timestamp before handing it to the engine — the identical handle path used live.

use ferro_replay::VirtualClock;

let clock = VirtualClock::new(session_start_ns);

for event in recorded_session {
    // Advance virtual time to the event, waking any timers due in the
    // interval in deadline order before the event is processed.
    clock.advance_to(event.local_ns).await;
    engine.handle(event).await;
}

// The engine's state hashes equal to the live run that recorded it.
One advancer

In production exactly one component — the replay producer — calls advance_to; nothing else may. This single-writer rule is what makes “live and replay share one code path” literally true, and the same machinery drives state-rebuild on restart.

Why it reproduces exactly

Three properties of advance_to combine to make replay deterministic:

// 1. Due waiters pop in (deadline, registration-order) — stable order.
// 2. now is set to each waiter's deadline before it wakes, and the loop
//    yields so the woken task runs while now == its deadline
//    (wakes-before-further-advance) — timers never see time run ahead.
// 3. Cancelled sleeps are discarded O(1) on pop, so a busy timeline's
//    dead waiters don't perturb ordering or cost a scheduler round-trip.

Runtime requirement

These guarantees hold on a current-thread runtime; a multi-thread scheduler would reintroduce wake-order races. A replay binary therefore structurally selects the current-thread scheduler wherever the replay producer is configured.

Keep it honest

Replay only reproduces if no component read time off-timeline during the live run. The wallclock gate is what guarantees that — without it, a single stray wall-clock read silently breaks reproducibility.