Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 1x 10x 5x 4x 10x 10x 4x 1x | /**
* Event-listener wiring — boots all event-driven listeners that should run
* for the lifetime of the Express process. Today: the owner-left RTDB
* listener. Future event-driven additions plug in here so src/index.js
* stays a thin call-site.
*
* Architectural notes:
* - The presence checker is constructed here (not inside the listener) so
* the listener's contract stays platform-neutral and the path is
* centralised. The checker PROPAGATES errors (unlike the route-handler
* `isUserPresent` which fail-safes to "present") because the listener
* relies on errors to preserve the signal entry for retry.
* - Returns a stop() that detaches all listeners — used by tests and
* process shutdown hooks (`wireProcessShutdown` in process-shutdown.js).
* - INTENTIONALLY unconditional (not gated on NODE_ENV === 'production')
* despite `startCronJobs` being prod-only: event-driven RTDB listeners
* cost no Firestore quota (no polling), and they MUST run in local/dev
* so journey tests can exercise the full owner-disconnect flow against
* Firebase emulators. The asymmetry with crons is deliberate.
*/
const { registerOwnerLeftListener } = require('./owner-left-listener');
/**
* Build a presence checker that reads `rooms/{roomId}/presence/{userId}` and
* THROWS on RTDB read errors. The owner-left orchestrator catches the throw
* and rejects up to the listener, which leaves the signal entry in place
* for retry on next signal-fire or restart-scan.
*/
function buildPresenceChecker(rtdb) {
return async function presenceChecker(roomId, userId) {
const snap = await rtdb.ref(`rooms/${roomId}/presence/${userId}`).get();
return snap.exists();
};
}
/**
* Start all event listeners. Returns a stop() that detaches each.
*
* @param {object} args
* @param {object} args.db - firebase-admin Firestore
* @param {object} args.rtdb - firebase-admin Realtime Database
* @param {object} args.log - logger
* @returns {() => void}
*/
function startEventListeners({ db, rtdb, log }) {
const detachOwnerLeft = registerOwnerLeftListener({
db,
rtdb,
log,
presenceChecker: buildPresenceChecker(rtdb),
});
return function stop() {
detachOwnerLeft();
};
}
module.exports = {
startEventListeners,
// Exported for direct testing.
buildPresenceChecker,
};
|