/** Sockets can close while an asynchronous handler still owns a pending write. * Stop admission before calling this; do not release store ownership until both * the listener and every admitted handler have finished. */ export async function trackResponse(handler, req, res) { const finished = new Promise(resolve => { const done = () => { res.off('finish', done); res.off('close', done); resolve() } res.once('finish', done); res.once('close', done) }) await handler(req, res) await finished } export async function drainRequests(server, activeHandlers) { const listenerClosed = new Promise(resolve => server.close(resolve)) await Promise.all([...activeHandlers]) // Browser TLS preconnect sockets have no admitted request to finish and can // otherwise hold server.close until the browser's idle timeout. server.closeAllConnections() await listenerClosed }