Ticket 102 (splitting the engine into reader/primary/profile actors) was a single multi-thousand-line ticket covering a new actor topology, an EngineHandle API redesign, a query fan-out layer, moving alerts, and a full test-harness rewrite, with some design decisions deliberately left open. Splitting it into six sequenced tickets (profile actor skeleton + signaling, move metric computation, move alert evaluation, split the handle API, query fan-out, test harness rework) lets each land as its own reviewable commit instead of one large speculative rewrite. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TeyhRfMYjMditek6geDRoQ
2.5 KiB
2.5 KiB
105 — Move alert evaluation onto the profile actor
Summary
Alert rules are profile-scoped and read metric buckets
(alert_states: HashMap<String, AlertRuntimeState> lives on the
single actor's stack frame today), so per 0001-actor-split's
resolved decision, alert evaluation moves with metric computation.
Depends on 104-move-metric-computation-to-profile-actor landing
first — alert evaluation reads the metric buckets that ticket moves
onto ProfileSnapshot.
Where
src/engine/handle.rs:141—let mut alert_states: HashMap<String, AlertRuntimeState> = HashMap::new();, currently a local in the single actor'srun()loop.src/engine/handle.rs'sIngestarm — today, right afterwrite.mutate(...)publishes, the actor doeswrite.peek()and callsalerts::evaluate_alerts(&rules, &mut alert_states, &guard, sequence, timestamp, &text), then spawnsalerts::deliver_for_rulefor each fired alert. This whole block moves to wherever the profile actor's per-line processing lives (the watch-wake loop from ticket 103/104).src/engine/alerts.rs:139(AlertRuntimeState),:241(evaluate_alerts),:384(deliver_for_rule) — signatures take the rules list and a&EngineSnapshot-shaped guard; check whetherevaluate_alertsneeds to change its snapshot parameter type toProfileSnapshot(likely yes, since it reads bucket data that now lives there) or whether it can stay snapshot-shape-agnostic via whatever trait/accessor bucket-reading already uses.- Settings access for alert rules/ntfy config
(
src/engine/handle.rs:170-177,settings.lock().unwrap()) — this stays available to the profile actor the same way (it's aSettingsHandleclone, not primary-actor state), so no primary dependency here.
Scope
- Move
alert_statesownership to the profile actor's task-local state. - Move the post-publish
evaluate_alertscall anddeliver_for_rulespawn to fire from the profile actor's per-line processing, readingProfileSnapshot(post-metric-computation) instead of the primary'sEngineSnapshot. - Update
evaluate_alerts's signature insrc/engine/alerts.rsif it needs to accept a different snapshot type; keep its actual evaluation logic unchanged — this ticket is a relocation, not a rewrite of alert semantics. - Out of scope: any change to alert rule semantics, ntfy delivery, or
the
AlertRuntimeStatemodel itself — purely which actor owns and drives evaluation.