Push the channel_keys membership filter into the blob read query
Problem
Since !251344 (merged) the reconstruction filters channel_values to the header's channel_keys — but in Ruby, after the query. Workflow#reconstructed_channel_values fetches every channel ever blobbed on the ancestor chain, then #select_live_channels drops the dead ones post-decode. For chat workflows that means fetching and decompressing every branch:to:* routing channel, each re-seeded as a full snapshot at every group start, only to discard them.
Kibana p95 db_duration_s for getLatestCheckpoint (the gateway resume payload): 0.107s legacy vs 0.339s on blobs (dw_read_blobs_graphql:1) — the 3.2× matches IC-D29's "full reconstruction ≈ 3.3× a header read". Much of that gap is TOAST reads for channels the membership filter throws away.
Proposal
Push the membership into the SQL. The plumbing exists: accumulated_blobs_for(checkpoint, channels:) adds WHERE channel IN (...), served by the dedup index (project_id, workflow_id, thread_ts, channel, …).
def reconstructed_channel_values(checkpoint, channels: nil)
channels ||= channel_membership(checkpoint)
...- A NULL membership (pre-
channel_keysheader) keeps today's unfiltered read. - An explicit
channels:argument intersects with the membership rather than bypassing it. - Keep
#select_live_channelsas the final guard — the query filter is an optimization, not the correctness boundary. - Same treatment in
#blobs_by_thread_ts_for(the batched page read): filter by the union of the page headers'channel_keys, skipped when any header declares none.
Acceptance criteria
- The blob query for a membership-bearing header restricts
channeltochannel_keys. - NULL membership folds unfiltered (unchanged behavior, spec-pinned).
- Explicit
channels:callers (scoped trace reads) intersect with membership. - Query plans on the MR (before/after) from a chain with dead
branch:to:*channels. -
getLatestCheckpointp95 re-measured after deploy.
Related
- IC-D29 (channel-scoped reads), IC-D54 (NULL membership fallback)
- #613975 (closed) (membership filter, closed), #621934 (closed) (blob index for
latest_channel_message) - &23217 (closed)