grafserv
Version:
A highly optimized server for GraphQL, powered by Grafast
61 lines • 2.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_WEBSOCKET_KEEPALIVE = void 0;
exports.handleWebSocketKeepalive = handleWebSocketKeepalive;
exports.DEFAULT_WEBSOCKET_KEEPALIVE = 12_000;
function handleWebSocketKeepalive(socket, preset) {
const keepaliveInterval = preset.grafserv?.websocketKeepalive ?? exports.DEFAULT_WEBSOCKET_KEEPALIVE;
if (!Number.isFinite(keepaliveInterval) || keepaliveInterval <= 0) {
// Keepalive disabled
return;
}
/**
* Sending a ping and waiting for a pong are mutually exclusive, so this
* timer is used for both.
*/
let timer = null;
/**
* Cleans up the timer, always call this before re-assigning timer (to ensure
* that an out-of-order pong doesn't cause two timers to run concurrently).
*/
const stopTimer = () => {
if (timer != null) {
clearTimeout(timer);
timer = null;
}
};
/** First half of a heart beat - send ping */
const sendPing = () => {
stopTimer();
// Schedule timeout
timer = setTimeout(handleTimeout, keepaliveInterval);
socket.ping();
};
/** Second half of a heart beat - receive pong */
const handlePong = () => {
stopTimer();
// Schedule the next ping
timer = setTimeout(sendPing, keepaliveInterval);
};
/** Terminal handler, due to timeout */
const handleTimeout = () => {
stopTimer();
releaseListeners();
// Kill the socket (after we've released the listeners)
socket.terminate();
};
/** Terminal handler, due to natural socket close */
const handleClose = (_code, _reason) => {
stopTimer();
releaseListeners();
};
const releaseListeners = () => {
socket.off("pong", handlePong);
socket.off("close", handleClose);
};
socket.on("pong", handlePong);
socket.on("close", handleClose);
// Schedule the first ping
timer = setTimeout(sendPing, keepaliveInterval);
}
//# sourceMappingURL=websocketKeepalive.js.map