Files
ottyl/tickets/106-split-enginehandle-api-for-primary-and-profile.md
T
Hugh KaznowskiandClaude Sonnet 5 2c1aaa6e9c Break ticket 102's actor split into reviewable sub-tickets (103-108)
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
2026-09-07 13:33:01 +01:00

3.2 KiB

106 — Give API handlers a real way to address the primary vs. the profile actor

Summary

By the time 104-move-metric-computation-to-profile-actor and 105-move-alert-evaluation-to-profile-actor land, metric/alert messages need to route to the profile actor while param/log messages stay on the primary — today's single EngineHandle (one mpsc::Sender

  • one IndexReader) can't express that. This ticket gives api.rs's handlers, and the runtime profile-switch path, a real API surface for both actors, per 0001-actor-split's resolved decision to decide during implementation whether that's two handle types or one internally-fanning-out handle.

Where

  • src/engine/handle.rs:74-78 (EngineHandle { tx, reader }) — the single handle type ApiState holds today.
  • src/api/mod.rs — ApiState's definition (wherever it stores the EngineHandle) and every handler that sends an EngineMessage; metric/alert-related routes need to target the profile actor's channel instead of the primary's.
  • src/api/mod.rs:812-852 (reload_engine_declarations, activate_profile) — today removes/redeclares params and metrics against one engine. After this split, param removal/redeclare stays primary-side, metric removal/redeclare targets the profile actor — this function needs to send to both.
  • src/config/profile.rs's load_into_engine (referenced in 0004-profile-switch-reindexing-cost at :332-384) — same dual-target concern at startup load time as well as runtime reactivation.
  • src/api/mcp_server.rs — check whether the MCP server's query surface holds its own EngineHandle reference that also needs the updated shape.

Scope

  • Decide and implement the concrete shape: either (a) ApiState holds two handles (primary: EngineHandle, profile: ProfileHandle) and each handler picks the right one, or (b) one combined handle type that internally holds both channels/readers and routes by message kind. Document the choice in the PR description since 0001-actor-split deliberately left it open.
  • Update every api.rs handler that currently sends a DeclareMetric/UpdateMetric/RemoveMetricDeclaration or alert- related message to target the profile actor; param-related messages (DeclareParam/RemoveParamDeclaration/ClearParams/ SetMaxLogs/EnsureSortHelperIndex) stay on the primary.
  • Update reload_engine_declarations/activate_profile and Profile::load_into_engine to split their remove-then-redeclare sequence across both actors correctly, preserving today's behavior (still fully synchronous from the caller's perspective — this ticket doesn't change the blocking nature of profile switching, only which actor(s) the messages go to; see 0004-profile-switch-reindexing-cost for the separate question of making that async).
  • Out of scope: the query fan-out layer for requests needing both raw logs and profile-derived data in one response — that's 107-query-fan-out-across-primary-and-profile. Read-only query handlers can be touched here only insofar as they need updating to compile against the new handle shape, not to actually merge two data sources yet.