VIOLET V0: reactor clock primitives + latency harness (gate PASSED)

clock.py: mono_ns single timebase; LatencyHistogram (raw reservoir, exact
nearest-rank percentiles); PlaneClock per-plane seq clocks with strict
staleness budgets (age==budget not stale — MHS FIX-9 lesson);
DeadlineScheduler — single-driver timer heap with EARLY-WAKE on
earlier-than-head insert (the jitter-budget mechanism), isolated callbacks.

harness.py: seeded deterministic event storms (sequence-hash asserted)
driving the REAL Rust ExecutionKernel via the MOCK bundle; reaction latency
measured producer-stamp→post-fold across the queue hop exactly as the
production account stream consumes; ACCOUNT_UPDATE wallet sentinel tracks
kernel k_capital so synthetic storms never trip capital_frozen; sustained
throughput reported alongside the gate.

V0 GATE (prod host, 50k events, 5k concurrent deadlines, burst 8/12ms ≈
667 ev/s offered): venue_event_reaction p99 7.19ms (<10ms budget),
deadline_jitter p99 4.86ms (<25ms), zero early fires. Capacity artifacts:
the 32/1ms and 16/12ms storms (archived reports) show intra-burst queueing
dominating beyond ~1.3k ev/s offered at ~0.33ms/fold. 17 unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-12 15:32:13 +02:00
parent 84e4a50e3f
commit 4b52fff8dd
8 changed files with 1084 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
"""V0: DeadlineScheduler — ordering, cancellation, early-wake, jitter."""
from __future__ import annotations
import asyncio
import random
import sys
sys.path.insert(0, "/mnt/dolphinng5_predict")
import pytest
from prod.clean_arch.violet.clock import DeadlineScheduler, LatencyHistogram, mono_ns
@pytest.mark.asyncio
async def test_deadlines_fire_in_due_order_after_shuffled_insert():
fired: list[int] = []
sched = DeadlineScheduler()
sched.start()
base = mono_ns()
order = list(range(1_000))
random.Random(7).shuffle(order)
for k in order:
due = base + (k + 1) * 1_000_000 # 1ms apart, shuffled insertion
sched.schedule_at(due, (lambda kk=k: fired.append(kk)))
await asyncio.sleep(1.3)
await sched.stop()
assert len(fired) == 1_000
assert fired == sorted(fired)
@pytest.mark.asyncio
async def test_cancellation_prevents_fire():
fired: list[str] = []
sched = DeadlineScheduler()
sched.start()
keep = sched.schedule_in(30, lambda: fired.append("keep"))
kill = sched.schedule_in(30, lambda: fired.append("kill"))
kill.cancel()
await asyncio.sleep(0.12)
await sched.stop()
assert fired == ["keep"]
assert kill.cancelled and not kill.fired
assert keep.fired
@pytest.mark.asyncio
async def test_early_wake_on_earlier_insert():
"""A deadline inserted BELOW the current head must fire on time even when
the driver was sleeping toward a much later head — the early-wake path."""
sched = DeadlineScheduler(max_sleep_ms=5_000) # tick alone would be too slow
jit = LatencyHistogram("j")
sched.jitter_hist = jit
sched.start()
fired_at: list[int] = []
sched.schedule_in(4_000, lambda: None) # far head; driver sleeps
await asyncio.sleep(0.05) # driver now parked
due = mono_ns() + 20_000_000 # 20ms from now
sched.schedule_at(due, lambda: fired_at.append(mono_ns()))
await asyncio.sleep(0.15)
await sched.stop()
assert fired_at, "early deadline never fired — early-wake broken"
lateness_ms = (fired_at[0] - due) / 1e6
assert lateness_ms < 25.0, f"early-wake too late: {lateness_ms:.1f}ms"
@pytest.mark.asyncio
async def test_no_early_fires_and_jitter_budget_under_cpu_noise():
jit = LatencyHistogram("jitter")
sched = DeadlineScheduler(jitter_hist=jit)
sched.start()
early = [0]
rng = random.Random(11)
dues = []
for _ in range(400):
due = mono_ns() + int(rng.uniform(10, 800) * 1e6)
dues.append(due)
sched.schedule_at(due, (lambda d=due: early.__setitem__(0, early[0] + 1) if mono_ns() < d else None))
async def cpu_noise():
end = mono_ns() + int(0.9e9)
while mono_ns() < end:
sum(i * i for i in range(2_000))
await asyncio.sleep(0)
noise = asyncio.create_task(cpu_noise())
await asyncio.sleep(1.0)
noise.cancel()
await sched.stop()
assert early[0] == 0, "deadline fired EARLY"
assert sched.fired_count == 400
p99_ms = jit.percentile_ns(0.99) / 1e6
assert p99_ms < 25.0, f"jitter p99 {p99_ms:.2f}ms exceeds 25ms budget"
@pytest.mark.asyncio
async def test_callback_exception_does_not_kill_driver():
errors: list[str] = []
sched = DeadlineScheduler(on_error=lambda dl, e: errors.append(str(e)))
sched.start()
fired: list[str] = []
sched.schedule_in(10, lambda: (_ for _ in ()).throw(RuntimeError("boom")))
sched.schedule_in(40, lambda: fired.append("after"))
await asyncio.sleep(0.12)
await sched.stop()
assert errors and "boom" in errors[0]
assert fired == ["after"], "driver died after callback exception"
if __name__ == "__main__":
raise SystemExit(pytest.main([__file__, "-v"]))