fix(relay): stop panicking the ingest worker on reactions to project events (#5294)

A NIP-25 reaction whose target is a project root or project comment
(kind
1621 issue, 1618 PR, or a kind-1 comment on one) carries no h tag, so
channel_id is None on the reaction write path. The conformance-trace
emission asserted a channel was always present:

channel: channel_label(channel_id.expect("reaction path has channel")),

so the worker panicked at ingest.rs:2824. The row was inserted before
the
panic, so the client saw a failed request for a persisted event and
retried,
and the duplicate branch carried the same expect, head-of-line blocking
a
durable publish queue forever.

Mirror the message write's three-way split at the same seam:
(Some, true) -> WriteInsert, (Some, false) -> WriteDuplicate, (None, _)
-> WriteInsertGlobal. The conformance vocabulary already models
channel-less
writes; only the reaction path was missing it.

Closes #4936

Signed-off-by: Taksh <takshkothari09@gmail.com>
Signed-off-by: Ravneet Arora <rarora@squareup.com>
This commit is contained in:
Taksh Kothari
2026-08-12 04:33:18 +05:30
committed by GitHub
parent d9dc76c0aa
commit 16b7ae7ce6

View File

@@ -2837,24 +2837,29 @@ async fn ingest_event_inner(
};
let pubkey_hex = auth.pubkey().to_hex();
// Spec WriteInsert (line 514) / WriteDuplicate (line 606): emit
// the abstract write action. The persist API returns
// `was_inserted` (true → Insert, false → Duplicate). This branch
// is the reaction path; channel_id is always Some here, so
// WriteInsertGlobal does not apply.
// Spec WriteInsert (line 514) / WriteDuplicate (line 606) /
// WriteInsertGlobal (line 559): emit the abstract write action. The
// persist API returns `was_inserted` (true → Insert/Global, false →
// Duplicate). Reactions on project events (issue/PR roots and their
// comments) carry no `h` tag, so `channel_id` can be `None` here —
// mirror the message write's three-way split instead of asserting a
// channel, which panicked the ingest worker on those events.
let claimed = claimed_community_from_event(&event);
let action = if was_inserted {
TraceAction::WriteInsert {
let action = match (channel_id, was_inserted) {
(Some(ch), true) => TraceAction::WriteInsert {
msg_id: msg_id_label(event.id.as_bytes()),
channel: channel_label(channel_id.expect("reaction path has channel")),
channel: channel_label(ch),
claimed_community: claimed,
}
} else {
TraceAction::WriteDuplicate {
},
(Some(ch), false) => TraceAction::WriteDuplicate {
msg_id: msg_id_label(event.id.as_bytes()),
channel: channel_label(channel_id.expect("reaction path has channel")),
channel: channel_label(ch),
claimed_community: claimed,
}
},
(None, _) => TraceAction::WriteInsertGlobal {
msg_id: msg_id_label(event.id.as_bytes()),
claimed_community: claimed,
},
};
emit(tracer, action, state_for_request(tenant, auth.pubkey()));
dispatch_persistent_event(