Skip to content

Do not let a failed send break the page - #48

Merged
loevgaard merged 1 commit into
masterfrom
fix/16-sync-failures
Sep 7, 2026
Merged

Do not let a failed send break the page#48
loevgaard merged 1 commit into
masterfrom
fix/16-sync-failures

Conversation

@loevgaard

Copy link
Copy Markdown
Member

Fixes #16

Stacked on #47.

Problem

DispatchOnCommandBusSubscriber dispatches at PRIORITY_SEND, inside the visitor's request. Unless the application routes SendEvent to a transport, Messenger handles it synchronously and the SDK posts to graph.facebook.com right there. Client::sendEvent() throws ClientException for any non-200 response, Messenger wraps it in HandlerFailedException, and it propagates out of EventDispatcher::dispatch() into the controller that raised the event.

One expired access token therefore returned a 500 for every page that raises an event: product pages, checkout confirmation, registration.

Change

Dispatching is wrapped in a try/catch that logs at error level with the event name, event id and the exception. Only two things can reach it:

  1. The command is handled synchronously and Meta answered with an error.
  2. The command is routed to a transport and the transport itself is unavailable.

Neither is reachable once the command is routed to a working transport, because dispatch() then only hands the message to the transport and the handler runs in the worker. Messenger's retry and failure handling is untouched for routed setups.

The README now presents async routing as the expected setup with the reason spelled out, rather than as an aside after the configuration reference.

Tests

Three unit tests: the command is dispatched with the right event, nothing is dispatched without consent, and a bus that throws results in one error log record and no exception escaping.

@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.35%. Comparing base (2a07fca) to head (865684c).

Additional details and impacted files
@@                       Coverage Diff                       @@
##             fix/26-http-client-wiring      #48      +/-   ##
===============================================================
+ Coverage                        77.00%   77.35%   +0.34%     
- Complexity                         139      140       +1     
===============================================================
  Files                               30       30              
  Lines                              461      468       +7     
===============================================================
+ Hits                               355      362       +7     
  Misses                             106      106              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

With synchronous handling the http call to Meta happens inside the
visitor's request, and the SDK throws for any non-200 response, so an
expired access token returned a 500 for every page raising an event.

Catch and log at error level when dispatching. Routed setups are
unaffected, since the handler then runs in the worker.

Fixes #16
@loevgaard
loevgaard force-pushed the fix/26-http-client-wiring branch from 632c3c2 to 2a07fca Compare September 7, 2026 12:51
@loevgaard
loevgaard force-pushed the fix/16-sync-failures branch from bb2ba25 to 865684c Compare September 7, 2026 12:51
Base automatically changed from fix/26-http-client-wiring to master September 7, 2026 12:54
@loevgaard
loevgaard merged commit e1fb8ec into master Sep 7, 2026
47 checks passed
@loevgaard
loevgaard deleted the fix/16-sync-failures branch September 7, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Synchronous handling by default: Meta failures become visitor-facing 500s and every page waits for Meta

1 participant