Skip to main content
Scenario: A user reports they never got notified when their build finished. You didn’t write the notification pipeline, and it spans an event emitter, a queue, a consumer, and two delivery channels. Grepping for “notification” turns up a dozen files — before you can fix anything, you need to know which of them are actually on this path, and in what order.

Make revolte map the flow

Open a session in the repo and describe the trigger the same way you’d describe it to a teammate — no file names required.
Five hops, in actual call order. Skim it against what you already know before moving on — the next part builds on this map, so it’s worth correcting now if a hop looks off.

Drill into the weak point

Stay in the same session so you don’t have to re-establish context. Pick the hop that looks riskiest — usually wherever two things happen back to back without visible error handling — and narrow in on it one question at a time.
No. Both websocketChannel.send() and pushChannel.send() are single-attempt, best-effort calls — no retry on either one.
No retries isn’t the whole story on its own — a flaky send on one channel shouldn’t matter if the other still fires.
Unclear from a static read. Both sends live inside the same try/catch, so whether pushChannel.send() runs after a websocket failure depends on exactly where execution goes when the throw happens.
No — the throw jumps straight to the catch block, which only logs at debug level. pushChannel.send() is never reached. One flaky channel silently kills the other.
That’s the kind of failure a text search doesn’t surface — it takes following the event through the queue and reading how the error is actually handled.

Turn it into a fix

The failure mode is confirmed, so ask for the fix directly.
  • Each channel send gets its own try/catch.
  • Failures log at warn with the channel name and notification id.
  • New test: push still fires when the websocket send throws.
Review the diff and run the new test locally before opening a PR, same as with any change — tracing the flow gets you to that point faster, it doesn’t replace it.

Why this matters

Async boundaries — queues, consumers, fan-out — are exactly where a human loses the thread scanning files by hand. Tracing the actual execution path, including how errors are swallowed, turns “user says they didn’t get notified” into a specific line of code and a fix, in one pass.