Extract connection close handling

master
dev 5 months ago
parent a153fa466f
commit c848da24c4

@ -23,6 +23,7 @@ Estado al cierre:
- `arts/conn/connection.ts` delega decode/routing de frames entrantes en `connection-message-router.ts`.
- `arts/conn/connection.ts` delega el intento open/auth/flush/join en `connection-connect.ts`.
- `arts/conn/connection.ts` delega current transport, attach/detach y close en `connection-transport-runtime.ts`.
- `arts/conn/connection.ts` delega cierre intencional y close-event handling en `connection-close.ts`.
- `arts/timr/engine-timers.ts` delega fan-out de listeners y diagnostico de listeners en `timer-events.ts`.
- `arts/timr/engine-timers.ts` delega la construccion de entradas internas en `timer-entry.ts`.
- `arts/timr/engine-timers.ts` delega cancelacion y seleccion por scope en `timer-cancel.ts`.

@ -0,0 +1,58 @@
import {
CONNECTION_ACK_REASON_CLOSED,
CONNECTION_STATE_CLOSED,
CONNECTION_STATE_CLOSING,
CONNECTION_STATE_FAILED,
CONNECTION_STATE_RECONNECTING,
TIMER_KEY_RECONNECT
} from './consts.ts';
import type { ConnectionAckRegistry } from './acks.ts';
import type { ConnectionStateTracker } from './connection-state.ts';
import type { ConnectionTimerControls } from './connection-timers.ts';
import type { ConnectionTransportRuntime } from './connection-transport-runtime.ts';
import type { ConnectionHeartbeat } from './heartbeat.ts';
import type { ConnectionCloseEvent, ConnectionState } from './types.ts';
export interface ConnectionCloseRuntime {
readonly timers: ConnectionTimerControls;
readonly heartbeat: ConnectionHeartbeat;
readonly acks: ConnectionAckRegistry;
readonly state: ConnectionStateTracker;
readonly transport: ConnectionTransportRuntime;
isDisposed(): boolean;
isIntentionalClose(): boolean;
setIntentionalClose(value: boolean): void;
shouldReconnect(): boolean;
scheduleReconnect(): void;
markClosed(state: ConnectionState, cause?: unknown): void;
}
export function handleConnectionTransportClose(
event: ConnectionCloseEvent,
runtime: ConnectionCloseRuntime
): void {
if (runtime.isDisposed()) return;
if (runtime.isIntentionalClose()) {
runtime.markClosed(CONNECTION_STATE_CLOSED);
return;
}
runtime.state.setError(event);
if (runtime.shouldReconnect()) {
runtime.markClosed(CONNECTION_STATE_RECONNECTING, event);
runtime.scheduleReconnect();
return;
}
runtime.markClosed(CONNECTION_STATE_FAILED, event);
}
export function closeConnectionTransport(reason: string, runtime: ConnectionCloseRuntime): void {
runtime.setIntentionalClose(true);
runtime.timers.cancel(TIMER_KEY_RECONNECT);
runtime.heartbeat.stop();
runtime.acks.resolveAll({ ok: false, reason: CONNECTION_ACK_REASON_CLOSED });
runtime.state.transition(CONNECTION_STATE_CLOSING);
runtime.transport.close(reason);
if (runtime.state.state !== CONNECTION_STATE_CLOSED) {
runtime.markClosed(CONNECTION_STATE_CLOSED);
}
}

@ -2,6 +2,11 @@ import type { TimerScheduler } from '$timr';
import { createConnectionAckRegistry } from './acks.ts';
import { wireBrowserReconnect } from './browser-reconnect.ts';
import { createConnectionChannelRegistry } from './channel-registry.ts';
import {
closeConnectionTransport,
handleConnectionTransportClose,
type ConnectionCloseRuntime
} from './connection-close.ts';
import { runConnectionConnect } from './connection-connect.ts';
import { createConnectionEventBus } from './connection-events.ts';
import { routeConnectionMessage } from './connection-message-router.ts';
@ -18,12 +23,9 @@ import {
CONNECTION_CONNECT_REASON_DISPOSED,
CONNECTION_DIAGNOSTIC_EVENTS,
CONNECTION_STATE_CLOSED,
CONNECTION_STATE_CLOSING,
CONNECTION_STATE_FAILED,
CONNECTION_STATE_OPEN,
CONNECTION_STATE_RECONNECTING,
CONNECTION_TRANSPORT_STATE_OPEN,
TIMER_KEY_RECONNECT
CONNECTION_TRANSPORT_STATE_OPEN
} from './consts.ts';
import {
createConnectionDiagnostics,
@ -136,18 +138,7 @@ export function createConnection<TChannels extends ConnectionChannelMap = Connec
}
function handleTransportClose(event: ConnectionCloseEvent): void {
if (disposed) return;
if (intentionalClose) {
markClosed(CONNECTION_STATE_CLOSED);
return;
}
stateTracker.setError(event);
if (shouldReconnect()) {
markClosed(CONNECTION_STATE_RECONNECTING, event);
scheduleReconnect();
return;
}
markClosed(CONNECTION_STATE_FAILED, event);
handleConnectionTransportClose(event, closeRuntime);
}
function handleTransportError(err: unknown): void {
@ -169,6 +160,21 @@ export function createConnection<TChannels extends ConnectionChannelMap = Connec
},
diagnostics
});
const closeRuntime: ConnectionCloseRuntime = {
timers,
heartbeat,
acks,
state: stateTracker,
transport: transportRuntime,
isDisposed: () => disposed,
isIntentionalClose: () => intentionalClose,
setIntentionalClose: (value) => {
intentionalClose = value;
},
shouldReconnect,
scheduleReconnect,
markClosed
};
function shouldReconnect(): boolean {
return reconnectPolicy.isEnabled({ disposed, intentionalClose });
@ -239,13 +245,7 @@ export function createConnection<TChannels extends ConnectionChannelMap = Connec
}
function closeTransport(reason: string): void {
intentionalClose = true;
timers.cancel(TIMER_KEY_RECONNECT);
heartbeat.stop();
acks.resolveAll({ ok: false, reason: CONNECTION_ACK_REASON_CLOSED });
stateTracker.transition(CONNECTION_STATE_CLOSING);
transportRuntime.close(reason);
if (stateTracker.state !== CONNECTION_STATE_CLOSED) markClosed(CONNECTION_STATE_CLOSED);
closeConnectionTransport(reason, closeRuntime);
}
function reportChannelListenerError(event: string, err: unknown): void {

Loading…
Cancel
Save

Powered by TurnKey Linux.