Feature/59 wrap async routes #66

Merged
bermudalamb merged 2 commits from feature/59-wrap-async-routes into main 2026-08-19 13:19:33 -05:00
Owner
No description provided.
bermudalamb added 2 commits 2026-08-19 13:18:43 -05:00
Express 4 does not forward a rejected promise from an async handler, so an unwrapped async route never responds at all — the request hangs until the client gives up, nothing reaches the error middleware, and monitoring sees an open connection rather than a 500. That silence is the shape of the 2026-08-17 incident, where an unhandled rejection left every item query hanging and the storefront rendered it as an empty shop. `asyncRoute` was written in response, but it was only applied to some routes: 30 handlers added afterwards were still bare, including register, login, the whole cart, and PayPal checkout.

Wraps all 30, plus two the issue's inventory missed. `attachCustomer` is a bare async middleware mounted globally in app.ts, so a rejection in its session lookup would hang every request in the application — including the 25 handlers that were already wrapped correctly, which meant the guarantee did not actually hold anywhere. The PayPal webhook registers on a second router named `webhookRouter`, so an audit grepping for `router.` walked straight past it.

Adds a unit test that scans the route sources and fails on any registration whose handler is not wrapped. A convention already half-forgotten once will be forgotten again, and enforcement is what the issue asked for; ESLint would be the better home for it but there is no ESLint in this repo yet (#60). The test walks parens rather than lines, so it also catches a handler whose `async` sits on its own line, and it matches any `*Router` name rather than just `router` — the two ways the existing bare handlers escaped notice. It is deleted along with `asyncRoute` if the project moves to Express 5, which forwards rejections natively.

No behaviour changes on the success path; the failure path turns a hung request into a logged 500.

Closes #59

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
docs: the asyncRoute guarantee now holds everywhere, and is enforced (#59)
SonarQube Analysis / sonarqube (pull_request) Successful in 2m33s
Tests / backend-unit (pull_request) Successful in 34s
Tests / frontend-e2e (pull_request) Failing after 9m31s
e58c8b4009
The note said the older route files were still unwrapped, which stopped being true with #59. Records where the guarantee now reaches — including the second `webhookRouter` and the globally-mounted `attachCustomer`, both of which an audit grepping for `router.` misses — and points at the test that enforces it, so the next person adding a route learns it from a failing build rather than from this file.
bermudalamb added this to the Code Quality and Hardening project 2026-08-19 13:19:04 -05:00
bermudalamb moved this to Review in Code Quality and Hardening on 2026-08-19 13:19:10 -05:00
bermudalamb self-assigned this 2026-08-19 13:19:25 -05:00
bermudalamb merged commit 259b3779c6 into main 2026-08-19 13:19:33 -05:00
bermudalamb deleted branch feature/59-wrap-async-routes 2026-08-19 13:19:33 -05:00
bermudalamb moved this to Ready for Release in Code Quality and Hardening on 2026-08-20 15:44:43 -05:00
bermudalamb moved this to Released in Code Quality and Hardening on 2026-08-21 12:11:59 -05:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bermudalamb/redefined-designs#66