inngest
Version:
Official SDK for Inngest.com. Inngest is the reliability layer for modern applications. Inngest combines durable execution, events, and queues into a zero-infra platform with built-in observability.
1 lines • 3.4 kB
Source Map (JSON)
{"version":3,"file":"heartbeat.cjs","names":["accessor: ConnectionAccessor","wakeSignal: WakeSignal","logger: Logger","WAKE_REASON","ensureUnsharedArrayBuffer","ConnectMessage","GatewayMessageType"],"sources":["../../../../../src/components/connect/strategies/core/heartbeat.ts"],"sourcesContent":["/**\n * Heartbeat management for the active WebSocket connection.\n *\n * Sends periodic heartbeat pings and marks the connection as dead when\n * two consecutive heartbeats go unacknowledged, waking the reconcile loop\n * to trigger reconnection.\n */\n\nimport type { Logger } from \"../../../../middleware/logger.ts\";\nimport {\n ConnectMessage,\n GatewayMessageType,\n} from \"../../../../proto/src/components/connect/protobuf/connect.ts\";\nimport { ensureUnsharedArrayBuffer } from \"../../buffer.ts\";\nimport {\n type ConnectionAccessor,\n WAKE_REASON,\n type WakeSignal,\n} from \"./types.ts\";\n\nexport class HeartbeatManager {\n private interval: ReturnType<typeof setInterval> | undefined;\n private intervalMs = 10_000;\n onHeartbeatSent: (() => void) | undefined;\n\n constructor(\n private readonly accessor: ConnectionAccessor,\n private readonly wakeSignal: WakeSignal,\n private readonly logger: Logger,\n ) {}\n\n /**\n * Update the heartbeat interval. Restarts the timer if the interval changed\n * or if it wasn't running yet.\n */\n updateInterval(ms: number): void {\n if (ms === this.intervalMs && this.interval) return;\n this.intervalMs = ms;\n this.stop();\n this.start();\n }\n\n /** Stop the heartbeat timer. */\n stop(): void {\n clearInterval(this.interval);\n this.interval = undefined;\n }\n\n private start(): void {\n if (this.interval) return;\n this.interval = setInterval(() => this.tick(), this.intervalMs);\n }\n\n private tick(): void {\n const conn = this.accessor.activeConnection;\n if (!conn || conn.ws.readyState !== WebSocket.OPEN) return;\n\n if (conn.pendingHeartbeats >= 2) {\n this.logger.warn(\n { connectionId: conn.id },\n \"Consecutive heartbeats missed, reconnecting\",\n );\n conn.dead = true;\n this.wakeSignal.wake(WAKE_REASON.HeartbeatMissed);\n return;\n }\n\n conn.pendingHeartbeats++;\n conn.ws.send(\n ensureUnsharedArrayBuffer(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_HEARTBEAT,\n }),\n ).finish(),\n ),\n );\n\n this.logger.debug({ connectionId: conn.id }, \"Heartbeat sent\");\n this.onHeartbeatSent?.();\n }\n}\n"],"mappings":";;;;;AAoBA,IAAa,mBAAb,MAA8B;CAC5B,AAAQ;CACR,AAAQ,aAAa;CACrB;CAEA,YACE,AAAiBA,UACjB,AAAiBC,YACjB,AAAiBC,QACjB;EAHiB;EACA;EACA;;;;;;CAOnB,eAAe,IAAkB;AAC/B,MAAI,OAAO,KAAK,cAAc,KAAK,SAAU;AAC7C,OAAK,aAAa;AAClB,OAAK,MAAM;AACX,OAAK,OAAO;;;CAId,OAAa;AACX,gBAAc,KAAK,SAAS;AAC5B,OAAK,WAAW;;CAGlB,AAAQ,QAAc;AACpB,MAAI,KAAK,SAAU;AACnB,OAAK,WAAW,kBAAkB,KAAK,MAAM,EAAE,KAAK,WAAW;;CAGjE,AAAQ,OAAa;EACnB,MAAM,OAAO,KAAK,SAAS;AAC3B,MAAI,CAAC,QAAQ,KAAK,GAAG,eAAe,UAAU,KAAM;AAEpD,MAAI,KAAK,qBAAqB,GAAG;AAC/B,QAAK,OAAO,KACV,EAAE,cAAc,KAAK,IAAI,EACzB,8CACD;AACD,QAAK,OAAO;AACZ,QAAK,WAAW,KAAKC,0BAAY,gBAAgB;AACjD;;AAGF,OAAK;AACL,OAAK,GAAG,KACNC,yCACEC,+BAAe,OACbA,+BAAe,OAAO,EACpB,MAAMC,mCAAmB,kBAC1B,CAAC,CACH,CAAC,QAAQ,CACX,CACF;AAED,OAAK,OAAO,MAAM,EAAE,cAAc,KAAK,IAAI,EAAE,iBAAiB;AAC9D,OAAK,mBAAmB"}