Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions backend/__tests__/unit/services/pgBootService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,42 @@ describe('pgBootService — the route-table probe (TASK-168)', () => {
expect(routerIsMounted(appWith(layer(pgMessages)), pgMessages)).toBe(true);
});

// Production runs @sentry/node, which wraps every Express layer handle: the
// wrapper is a new function that exposes the original's properties. Identity
// on the handle then fails on a pod that has the route mounted (deploy
// 4e60f240, 2026-09-27). This builds a real Express app and wraps the layer
// the same way.
const wrapLikeSentry = (app, router) => {
const target = app._router.stack.find((l) => l.handle === router);
const original = target.handle;
const wrapper = function wrapped(...args) { return original.apply(this, args); };
Object.defineProperty(wrapper, 'stack', { get: () => original.stack });
target.handle = wrapper;
return target;
};

it('finds the mounted router when instrumentation has wrapped its layer handle', () => {
const express = require('express');
const app = express();
const pgMessages = express.Router();
pgMessages.get('/:id', (req, res) => res.sendStatus(401));
app.use('/api/pg/messages', pgMessages);
const target = wrapLikeSentry(app, pgMessages);
expect(target.handle).not.toBe(pgMessages);
expect(routerIsMounted(app, pgMessages)).toBe(true);
});

it('does not mistake a different wrapped router for this one', () => {
const express = require('express');
const app = express();
const other = express.Router();
other.get('/', (req, res) => res.sendStatus(200));
app.use('/api/pg/status', other);
wrapLikeSentry(app, other);
const pgMessages = express.Router();
expect(routerIsMounted(app, pgMessages)).toBe(false);
});

it('returns false when that router is absent, which is the incident', () => {
const pgMessages = { name: 'pg-messages' };
const pgStatus = { name: 'pg-status' };
Expand Down
11 changes: 11 additions & 0 deletions backend/services/pgBootService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,24 @@ export const PG_MESSAGE_PATH = '/api/pg/messages';
* IS the thing being mounted, so asking whether that object is in the stack is
* the same question with no translation step — and it stays correct if the path
* ever changes.
*
* The router's own `stack` array is the identity that survives instrumentation.
* In production `@sentry/node` (10.65) wraps every Express layer handle, so
* `layer.handle === router` is false on a pod that has the route mounted. The
* wrapper exposes the original's properties, so `layer.handle.stack` is still
* the router's stack. 2026-09-27: deploy 4e60f240 hung, because the new pod
* answered /api/pg/messages with 401 while /api/health/ready said "not mounted".
* A local reproduction with Sentry initialised gives identity false and stack
* true; without Sentry, both are true.
*/
export const routerIsMounted = (app: unknown, router: unknown): boolean => {
if (!router) return false;
const routerStack = (router as { stack?: unknown }).stack;
const walk = (candidate: any): boolean => {
const stack = (candidate && candidate.stack) || [];
return stack.some((layer: any) => {
if (layer.handle === router) return true;
if (routerStack && layer.handle && layer.handle.stack === routerStack) return true;
return Boolean(layer.handle && layer.handle.stack) && walk(layer.handle);
});
};
Expand Down
Loading