Files
ottyl/tickets/107-query-fan-out-across-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

2.9 KiB

107 — Fan out and merge queries that need both raw logs and profile-derived data

Summary

Today, Logs/Timeline queries read raw log text and profile-derived params/metrics from a single EngineSnapshot in one pass — e.g. query.rs's log-entry building calls log_entry_params against compiled_params from the same snapshot the raw text came from. Once params/logs live on the primary and metrics live on the profile actor (per tickets 103-106), any query needing both becomes a real join across two snapshots instead of one borrow. This is the piece of 0001-actor-split's design explicitly called out as "a query-fan-out/merge layer is still needed."

Where

  • src/engine/snapshot/query.rs (handle_query_inner and the log- entry-building helpers around line 70-117 per prior research) — the read path that currently assumes one EngineSnapshot has everything a Logs/Timeline response needs.
  • src/engine/message.rs:12-27 (EngineQuery) — currently answered entirely off the primary's left_right reader (EngineHandle::ask/handle_query_ro, per 0001-actor-split's "queries already bypass this actor" note); after the split, some query variants need data from both actors' read sides.
  • src/api/mod.rs — wherever EngineQuery results are turned into HTTP responses; the merge/join logic likely belongs here or in a new helper alongside query.rs, not duplicated per handler.
  • Dashboard/PromQL panel queries (src/engine/promql.rs) — confirm whether these are profile-only reads (metrics live entirely on the profile actor) and therefore need no fan-out, versus Logs/ Timeline which do.

Scope

  • Identify every EngineQuery variant that currently reads both raw log data and profile-derived data (params, metrics) from one snapshot, and design the two-snapshot join for each — likely: read matching log entries from the primary by sequence range, then look up each entry's profile-derived fields (declared param values, metric-driven fields) from the profile actor's snapshot by the same sequence, filtering/merging results.
  • Confirm ordering/consistency expectations: the profile actor can lag the primary (per 0001-actor-split's accepted eviction/lag tradeoff), so a joined query may find a primary-side log entry with no corresponding profile-side data yet — decide and document the behavior (omit those fields vs. error) rather than leaving it implicit.
  • Update PromQL/dashboard panel query handling only if it's confirmed to need primary-side data too (e.g. ottyl_seq/ottyl_ts bare queries per prior ticket history) — otherwise leave it reading the profile actor alone.
  • Out of scope: query result caching or performance optimization beyond what's needed for correctness — this ticket is about producing correct joined results, not making them fast (see 0005-additional-read-indexes for read-path performance work, which should be sequenced after this settles).