From 3ee6dddb0ed0d1191f2a2174128c6212fb6cedd3 Mon Sep 17 00:00:00 2001 From: Hugh Kaznowski Date: Mon, 7 Sep 2026 13:56:59 +0100 Subject: [PATCH] Document EngineHandle's already-realized primary/profile routing (ticket 106) Ticket 106 asked for a real way for API handlers to address the primary vs. profile actor. That routing was already built out of necessity while landing tickets 104/105 (metric queries had to reach the profile actor's snapshot for those tickets' own tests to pass) -- EngineHandle ended up as one combined handle (option (b) from the ticket's own scope note) that internally proxies metric/alert writes to the profile actor and routes MetricDeclarations/BucketValues/Promql reads to its snapshot, with no changes needed to any API handler, reload_engine_declarations/activate_profile, or Profile::load_into_engine -- they already just send EngineMessages the same way they did before the split. mcp_server.rs talks to the HTTP API rather than EngineHandle directly, so it needed no changes either. This commit documents that resolution in handle.rs so a future reader doesn't go looking for routing logic that isn't there. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TeyhRfMYjMditek6geDRoQ --- src/engine/handle.rs | 11 ++++ ...nginehandle-api-for-primary-and-profile.md | 62 ------------------- 2 files changed, 11 insertions(+), 62 deletions(-) delete mode 100644 tickets/106-split-enginehandle-api-for-primary-and-profile.md diff --git a/src/engine/handle.rs b/src/engine/handle.rs index 6361517..fad8d1d 100644 --- a/src/engine/handle.rs +++ b/src/engine/handle.rs @@ -1,5 +1,16 @@ //! The left-right write/read plumbing around `EngineSnapshot`, the actor loop that owns it, //! and the `EngineHandle` other tasks use to talk to that actor. +//! +//! Ticket 106 (giving API handlers a route to both the primary and profile actors) resolved to +//! option (b) from its own scope note: one combined `EngineHandle`, not two separate handle +//! types. Callers never pick a target explicitly -- `EngineHandle::tx` accepts every +//! `EngineMessage` variant, and `run()` below internally proxies the metric/alert-related ones +//! to the profile actor (`super::profile::ProfileMessage`) rather than mutating the primary's +//! own snapshot; `EngineHandle::profile_reader` similarly gives read access to the profile +//! actor's snapshot for the query variants it owns (routed in `api::EngineHandle::ask`). This +//! means `reload_engine_declarations`/`activate_profile`/`Profile::load_into_engine` needed no +//! changes at all to correctly split their remove-then-redeclare sequence across both actors -- +//! they already just send `EngineMessage`s the same way they did before the split. use crate::config::SettingsHandle; use crate::consts::{INGEST_LAG_WATERMARK_MAX_ENTRIES, INGEST_LAG_WATERMARK_WINDOW_MS}; diff --git a/tickets/106-split-enginehandle-api-for-primary-and-profile.md b/tickets/106-split-enginehandle-api-for-primary-and-profile.md deleted file mode 100644 index 3507dae..0000000 --- a/tickets/106-split-enginehandle-api-for-primary-and-profile.md +++ /dev/null @@ -1,62 +0,0 @@ -# 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.