MCPcopy Create free account
hub / github.com/Noumena-Network/code / handleTransportPermanentClose

Function handleTransportPermanentClose

src/bridge/replBridge.ts:896–975  ·  view source on GitHub ↗

* Body of the transport's setOnClose callback, hoisted to initBridgeCore * scope so /bridge-kick can fire it directly. setOnClose wraps this with * a stale-transport guard; debugFireClose calls it bare. * * With autoReconnect:true, this only fires on: clean close (1000), * permanent s

(closeCode: number | undefined)

Source from the content-addressed store, hash-verified

894 * exhaustion. Transient drops are retried internally by the transport.
895 */
896 function handleTransportPermanentClose(closeCode: number | undefined): void {
897 logForDebugging(
898 `[bridge:repl] Transport permanently closed: code=${closeCode}`,
899 )
900 logEvent('ncode_bridge_repl_ws_closed', {
901 code: closeCode,
902 })
903 // Capture SSE seq high-water mark before nulling. When called from
904 // setOnClose the guard guarantees transport !== null; when fired from
905 // /bridge-kick it may already be null (e.g. fired twice) — skip.
906 if (transport) {
907 const closedSeq = transport.getLastSequenceNum()
908 if (closedSeq > lastTransportSequenceNum) {
909 lastTransportSequenceNum = closedSeq
910 }
911 transport = null
912 }
913 // Transport is gone — wake the poll loop out of its at-capacity
914 // heartbeat sleep so it's fast-polling by the time the reconnect
915 // below completes and the server re-queues work.
916 wakePollLoop()
917 // Reset flush state so writeMessages() hits the !transport guard
918 // (with a warning log) instead of silently queuing into a buffer
919 // that will never be drained. Unlike onWorkReceived (which
920 // preserves pending messages for the new transport), onClose is
921 // a permanent close — no new transport will drain these.
922 const dropped = flushGate.drop()
923 if (dropped > 0) {
924 logForDebugging(
925 `[bridge:repl] Dropping ${dropped} pending message(s) on transport close (code=${closeCode})`,
926 { level: 'warn' },
927 )
928 }
929
930 if (closeCode === 1000) {
931 // Clean close — session ended normally. Tear down the bridge.
932 onStateChange?.('failed', 'session ended')
933 pollController.abort()
934 triggerTeardown()
935 return
936 }
937
938 // Transport reconnect budget exhausted or permanent server
939 // rejection. By this point the env has usually been reaped
940 // server-side (BQ 2026-03-12: ~98% of ws_closed never recover
941 // via poll alone). stopWork(force=false) can't re-dispatch work
942 // from an archived env; reconnectEnvironmentWithSession can
943 // re-activate it via POST /bridge/reconnect, or fall through
944 // to a fresh session if the env is truly gone. The poll loop
945 // (already woken above) picks up the re-queued work once
946 // doReconnect completes.
947 onStateChange?.(
948 'reconnecting',
949 `Remote Control connection lost (code ${closeCode})`,
950 )
951 logForDebugging(
952 `[bridge:repl] Transport reconnect budget exhausted (code=${closeCode}), attempting env reconnect`,
953 )

Callers 1

wireTransportFunction · 0.85

Calls 7

onStateChangeFunction · 0.85
triggerTeardownFunction · 0.85
getLastSequenceNumMethod · 0.80
dropMethod · 0.80
logEventFunction · 0.70
logForDebuggingFunction · 0.50

Tested by

no test coverage detected