feat(webhook): dispatch message.reaction events (WebSocket/webhook parity)#380
Merged
Merged
Conversation
…rity)
Reactions were broadcast over WebSocket only, so a webhook-only consumer
could not observe them. Dispatch message.reaction alongside the WS emit with
the same payload (the reaction event plus the post-apply reactions snapshot),
register it in WEBHOOK_EVENTS, and expose it in the dashboard event picker.
Reactions carry no unique id and are a read-modify-write (a sender can
re-apply the same emoji over time), so the idempotency key is salted with the
per-dispatch occurredAt — distinct occurrences get distinct keys while retries
of the same delivery stay stable. Wildcard ('*') subscribers will begin
receiving this event.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Message reactions were broadcast over WebSocket only — a webhook-only consumer could never observe reactions, an undocumented asymmetry (
message.reactionwas a subscribable WS event but not a webhook event).Change
message.reactioninWEBHOOK_EVENTS(among the dispatched events) and expose it in the dashboard event picker.SessionService.applyReaction, alongside the existing WebSocket emit, with the same payload ({ messageId, chatId, reaction, senderId, reactions }, wherereactionsis the post-apply snapshot). Dispatch is fire-and-forget and happens only after the reaction is persisted.Idempotency
A reaction carries no unique id and is a read-modify-write of the message's reactions map — the same sender can re-apply the same emoji over time (👍 → remove → 👍). Keying on
(sender, message)alone would collapse a genuine re-reaction onto the earlier one. The key is therefore salted with the per-dispatchoccurredAt(captured once, reused across retries) — the same mechanism the recurringsession.*lifecycle events use: distinct occurrences get distinct keys while retries of one delivery stay stable.Webhooks subscribed with the wildcard
'*'will begin receivingmessage.reactiondeliveries. Existing semantics for all other events are unchanged.Tests
idempotency.util.spec.ts: salt distinctness (re-reaction is a distinct event), retry-stability, two-sender distinctness.session.service.spec.ts: a reaction now dispatchesmessage.reactionwith the post-applyreactionssnapshot.lint+build+ fulljest(980) green; dashboardbuild+lintgreen. API spec updated.