@replit/river 0.24.2 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-URKXJ2WE.js → chunk-4GCILF7L.js} +4 -4
- package/dist/{chunk-STDBD66K.js → chunk-6NPQ43ZP.js} +2 -2
- package/dist/{chunk-STDBD66K.js.map → chunk-6NPQ43ZP.js.map} +1 -1
- package/dist/{chunk-PP4OAZJY.js → chunk-BMSEVPGM.js} +2 -2
- package/dist/{chunk-XSYDUFV4.js → chunk-FEMGSUEE.js} +3 -3
- package/dist/{chunk-TQ44W7PR.js → chunk-JTZVFCMT.js} +32 -16
- package/dist/{chunk-TQ44W7PR.js.map → chunk-JTZVFCMT.js.map} +1 -1
- package/dist/{chunk-AEQFIGBA.js → chunk-N2UT2H2D.js} +28 -23
- package/dist/chunk-N2UT2H2D.js.map +1 -0
- package/dist/{chunk-U4UKZXWA.js → chunk-XVGZYVNR.js} +34 -13
- package/dist/chunk-XVGZYVNR.js.map +1 -0
- package/dist/{client-2ba72e89.d.ts → client-1321630c.d.ts} +1 -1
- package/dist/{connection-55cba970.d.ts → connection-bd907ca6.d.ts} +1 -1
- package/dist/{handshake-0b88e8fc.d.ts → handshake-3772d7ca.d.ts} +4 -2
- package/dist/router/index.cjs +31 -15
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +7 -7
- package/dist/router/index.d.ts +7 -7
- package/dist/router/index.js +2 -2
- package/dist/{server-732e7014.d.ts → server-f0fd2b98.d.ts} +1 -1
- package/dist/{services-adfd0bc3.d.ts → services-8d14ae16.d.ts} +2 -2
- package/dist/transport/impls/ws/client.cjs +33 -12
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +3 -3
- package/dist/transport/impls/ws/client.d.ts +3 -3
- package/dist/transport/impls/ws/client.js +7 -7
- package/dist/transport/impls/ws/server.cjs +57 -31
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +3 -3
- package/dist/transport/impls/ws/server.d.ts +3 -3
- package/dist/transport/impls/ws/server.js +5 -5
- package/dist/transport/index.cjs +57 -31
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +3 -3
- package/dist/transport/index.d.ts +3 -3
- package/dist/transport/index.js +7 -7
- package/dist/util/testHelpers.cjs +33 -27
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +4 -7
- package/dist/util/testHelpers.d.ts +4 -7
- package/dist/util/testHelpers.js +3 -14
- package/dist/util/testHelpers.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-25IYT6G3.js +0 -106
- package/dist/chunk-25IYT6G3.js.map +0 -1
- package/dist/chunk-AEQFIGBA.js.map +0 -1
- package/dist/chunk-U4UKZXWA.js.map +0 -1
- package/dist/connection-c6db05d9.d.ts +0 -31
- package/dist/transport/impls/uds/client.cjs +0 -1684
- package/dist/transport/impls/uds/client.cjs.map +0 -1
- package/dist/transport/impls/uds/client.d.cts +0 -18
- package/dist/transport/impls/uds/client.d.ts +0 -18
- package/dist/transport/impls/uds/client.js +0 -38
- package/dist/transport/impls/uds/client.js.map +0 -1
- package/dist/transport/impls/uds/server.cjs +0 -1650
- package/dist/transport/impls/uds/server.cjs.map +0 -1
- package/dist/transport/impls/uds/server.d.cts +0 -19
- package/dist/transport/impls/uds/server.d.ts +0 -19
- package/dist/transport/impls/uds/server.js +0 -33
- package/dist/transport/impls/uds/server.js.map +0 -1
- /package/dist/{chunk-URKXJ2WE.js.map → chunk-4GCILF7L.js.map} +0 -0
- /package/dist/{chunk-PP4OAZJY.js.map → chunk-BMSEVPGM.js.map} +0 -0
- /package/dist/{chunk-XSYDUFV4.js.map → chunk-FEMGSUEE.js.map} +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ProtocolError,
|
|
3
3
|
Transport
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FEMGSUEE.js";
|
|
5
5
|
import {
|
|
6
6
|
SessionStateGraph,
|
|
7
7
|
defaultServerTransportOptions
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XVGZYVNR.js";
|
|
9
9
|
import {
|
|
10
10
|
ControlMessageHandshakeRequestSchema,
|
|
11
11
|
PROTOCOL_VERSION,
|
|
12
12
|
coerceErrorString,
|
|
13
13
|
handshakeResponseMessage
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-6NPQ43ZP.js";
|
|
15
15
|
|
|
16
16
|
// transport/server.ts
|
|
17
17
|
import { SpanStatusCode } from "@opentelemetry/api";
|
|
@@ -202,10 +202,10 @@ var ServerTransport = class extends Transport {
|
|
|
202
202
|
return;
|
|
203
203
|
}
|
|
204
204
|
let connectCase = "new session";
|
|
205
|
+
const clientNextExpectedSeq = msg.payload.expectedSessionState.nextExpectedSeq;
|
|
206
|
+
const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;
|
|
205
207
|
if (oldSession && oldSession.id === msg.payload.sessionId) {
|
|
206
208
|
connectCase = "transparent reconnection";
|
|
207
|
-
const clientNextExpectedSeq = msg.payload.expectedSessionState.nextExpectedSeq;
|
|
208
|
-
const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;
|
|
209
209
|
const ourNextSeq = oldSession.nextSeq();
|
|
210
210
|
const ourAck = oldSession.ack;
|
|
211
211
|
if (clientNextSentSeq > ourAck) {
|
|
@@ -261,26 +261,31 @@ var ServerTransport = class extends Transport {
|
|
|
261
261
|
this.updateSession(oldSession);
|
|
262
262
|
} else if (oldSession) {
|
|
263
263
|
connectCase = "hard reconnection";
|
|
264
|
+
this.log?.info(
|
|
265
|
+
`client is reconnecting to a new session (${msg.payload.sessionId}) with an old session (${oldSession.id}) already existing, closing old session`,
|
|
266
|
+
{
|
|
267
|
+
...session.loggingMetadata,
|
|
268
|
+
connectedTo: msg.from,
|
|
269
|
+
sessionId: msg.payload.sessionId
|
|
270
|
+
}
|
|
271
|
+
);
|
|
264
272
|
this.deleteSession(oldSession);
|
|
265
273
|
oldSession = void 0;
|
|
266
|
-
}
|
|
274
|
+
}
|
|
275
|
+
if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {
|
|
267
276
|
connectCase = "unknown session";
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
277
|
+
this.rejectHandshakeRequest(
|
|
278
|
+
session,
|
|
279
|
+
msg.from,
|
|
280
|
+
`client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}`,
|
|
281
|
+
"SESSION_STATE_MISMATCH",
|
|
282
|
+
{
|
|
283
|
+
...session.loggingMetadata,
|
|
284
|
+
connectedTo: msg.from,
|
|
285
|
+
transportMessage: msg
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
return;
|
|
284
289
|
}
|
|
285
290
|
const sessionId = msg.payload.sessionId;
|
|
286
291
|
this.log?.info(
|
|
@@ -379,4 +384,4 @@ var ServerTransport = class extends Transport {
|
|
|
379
384
|
export {
|
|
380
385
|
ServerTransport
|
|
381
386
|
};
|
|
382
|
-
//# sourceMappingURL=chunk-
|
|
387
|
+
//# sourceMappingURL=chunk-N2UT2H2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../transport/server.ts"],"sourcesContent":["import { SpanStatusCode } from '@opentelemetry/api';\nimport { ParsedMetadata } from '../router/context';\nimport { ServerHandshakeOptions } from '../router/handshake';\nimport {\n ControlMessageHandshakeRequestSchema,\n HandshakeErrorResponseCodes,\n OpaqueTransportMessage,\n PROTOCOL_VERSION,\n PartialTransportMessage,\n TransportClientId,\n handshakeResponseMessage,\n} from './message';\nimport {\n ProvidedServerTransportOptions,\n ServerTransportOptions,\n defaultServerTransportOptions,\n} from './options';\nimport { Transport } from './transport';\nimport { coerceErrorString } from '../util/stringify';\nimport { Static } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { ProtocolError } from './events';\nimport { Connection } from './connection';\nimport { MessageMetadata } from '../logging';\nimport { SessionWaitingForHandshake } from './sessionStateMachine/SessionWaitingForHandshake';\nimport { Session, SessionState } from './sessionStateMachine/common';\nimport { SessionStateGraph } from './sessionStateMachine/transitions';\n\nexport abstract class ServerTransport<\n ConnType extends Connection,\n> extends Transport<ConnType> {\n /**\n * The options for this transport.\n */\n protected options: ServerTransportOptions;\n\n /**\n * Optional handshake options for the server.\n */\n handshakeExtensions?: ServerHandshakeOptions;\n\n /**\n * A map of session handshake data for each session.\n */\n sessionHandshakeMetadata = new Map<TransportClientId, ParsedMetadata>();\n pendingSessions = new Set<SessionWaitingForHandshake<ConnType>>();\n\n constructor(\n clientId: TransportClientId,\n providedOptions?: ProvidedServerTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.options = {\n ...defaultServerTransportOptions,\n ...providedOptions,\n };\n this.log?.info(`initiated server transport`, {\n clientId: this.clientId,\n protocolVersion: PROTOCOL_VERSION,\n });\n }\n\n extendHandshake(options: ServerHandshakeOptions) {\n this.handshakeExtensions = options;\n }\n\n send(to: string, msg: PartialTransportMessage): string {\n if (this.getStatus() === 'closed') {\n const err = 'transport is closed, cant send';\n this.log?.error(err, {\n clientId: this.clientId,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n throw new Error(err);\n }\n\n const session = this.sessions.get(to);\n if (!session) {\n const err = `session to ${to} does not exist`;\n this.log?.error(err, {\n clientId: this.clientId,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n throw new Error(err);\n }\n\n return session.send(msg);\n }\n\n protected deletePendingSession(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n ) {\n pendingSession.close();\n // we don't dispatch a session disconnect event\n // for a non-identified session, just delete directly\n\n this.pendingSessions.delete(pendingSession);\n }\n\n protected deleteSession(session: Session<ConnType>): void {\n this.sessionHandshakeMetadata.delete(session.to);\n super.deleteSession(session);\n }\n\n protected handleConnection(conn: ConnType) {\n if (this.getStatus() !== 'open') return;\n\n this.log?.info(`new incoming connection`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n });\n\n let receivedHandshake = false;\n const pendingSession = SessionStateGraph.entrypoints.WaitingForHandshake(\n this.clientId,\n conn,\n {\n onConnectionClosed: () => {\n this.log?.warn(\n `connection from unknown closed before handshake finished`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onConnectionErrored: (err) => {\n const errorString = coerceErrorString(err);\n this.log?.warn(\n `connection from unknown errored before handshake finished: ${errorString}`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onHandshakeTimeout: () => {\n this.log?.warn(\n `connection from unknown timed out before handshake finished`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onHandshake: (msg) => {\n if (receivedHandshake) {\n this.log?.error(\n `received multiple handshake messages from pending session`,\n {\n ...pendingSession.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n this.deletePendingSession(pendingSession);\n return;\n }\n\n // let this resolve async, we just need to make sure its only\n // called once so we don't race while transitioning to connected\n // onHandshakeRequest is async as custom validation may be async\n receivedHandshake = true;\n void this.onHandshakeRequest(pendingSession, msg);\n },\n onInvalidHandshake: (reason) => {\n this.log?.error(\n `invalid handshake: ${reason}`,\n pendingSession.loggingMetadata,\n );\n this.deletePendingSession(pendingSession);\n this.protocolError(ProtocolError.HandshakeFailed, reason);\n },\n },\n this.options,\n this.log,\n );\n\n this.pendingSessions.add(pendingSession);\n }\n\n private rejectHandshakeRequest(\n session: SessionWaitingForHandshake<ConnType>,\n to: TransportClientId,\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n metadata: MessageMetadata,\n ) {\n session.conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n this.log?.warn(reason, metadata);\n\n session.sendHandshake(\n handshakeResponseMessage({\n from: this.clientId,\n to,\n status: {\n ok: false,\n code,\n reason,\n },\n }),\n );\n\n this.protocolError(ProtocolError.HandshakeFailed, reason);\n this.deletePendingSession(session);\n }\n\n protected async onHandshakeRequest(\n session: SessionWaitingForHandshake<ConnType>,\n msg: OpaqueTransportMessage,\n ) {\n // invariant: msg is a handshake request\n if (!Value.Check(ControlMessageHandshakeRequestSchema, msg.payload)) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n 'received invalid handshake request',\n 'MALFORMED_HANDSHAKE',\n {\n ...session.loggingMetadata,\n transportMessage: msg,\n connectedTo: msg.from,\n validationErrors: [\n ...Value.Errors(ControlMessageHandshakeRequestSchema, msg.payload),\n ],\n },\n );\n\n return;\n }\n\n // invariant: handshake request passes all the validation\n const gotVersion = msg.payload.protocolVersion;\n if (gotVersion !== PROTOCOL_VERSION) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `expected protocol version ${PROTOCOL_VERSION}, got ${gotVersion}`,\n 'PROTOCOL_VERSION_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n let oldSession = this.sessions.get(msg.from);\n\n // invariant: must pass custom validation if defined\n const parsedMetadata = await this.validateHandshakeMetadata(\n session,\n oldSession,\n msg.payload.metadata,\n msg.from,\n );\n\n if (parsedMetadata === false) {\n return;\n }\n\n // 4 connect cases\n // 1. new session\n // we dont have a session and the client is requesting a new one\n // we can create the session as normal\n // 2. client is reconnecting to an existing session but we don't have it\n // reject this handshake, there's nothing we can do to salvage it\n // 3. transparent reconnect (old session exists and is the same as the client wants)\n // assign to old session\n // 4. hard reconnect (oldSession exists but but the client wants a new one)\n // we close the old session and create a new one\n let connectCase:\n | 'new session'\n | 'unknown session'\n | 'transparent reconnection'\n | 'hard reconnection' = 'new session';\n const clientNextExpectedSeq =\n msg.payload.expectedSessionState.nextExpectedSeq;\n const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;\n\n if (oldSession && oldSession.id === msg.payload.sessionId) {\n connectCase = 'transparent reconnection';\n\n // invariant: ordering must be correct\n const ourNextSeq = oldSession.nextSeq();\n const ourAck = oldSession.ack;\n\n // two incorrect cases where we cannot permit a reconnect:\n // - if the client is about to send a message in the future w.r.t to the server\n // - client.seq > server.ack => nextSentSeq > oldSession.ack\n if (clientNextSentSeq > ourAck) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `client is in the future: server wanted next message to be ${ourAck} but client would have sent ${clientNextSentSeq}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n // - if the server is about to send a message in the future w.r.t to the client\n // - server.seq > client.ack => oldSession.nextSeq() > nextExpectedSeq\n if (ourNextSeq > clientNextExpectedSeq) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `server is in the future: client wanted next message to be ${clientNextExpectedSeq} but server would have sent ${ourNextSeq}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n // transparent reconnect seems ok, proceed by transitioning old session\n // to not connected\n if (oldSession.state === SessionState.Connected) {\n const noConnectionSession =\n SessionStateGraph.transition.ConnectedToNoConnection(oldSession, {\n onSessionGracePeriodElapsed: () => {\n this.onSessionGracePeriodElapsed(noConnectionSession);\n },\n });\n\n oldSession = noConnectionSession;\n } else if (oldSession.state === SessionState.Handshaking) {\n const noConnectionSession =\n SessionStateGraph.transition.HandshakingToNoConnection(oldSession, {\n onSessionGracePeriodElapsed: () => {\n this.onSessionGracePeriodElapsed(noConnectionSession);\n },\n });\n\n oldSession = noConnectionSession;\n } else if (oldSession.state === SessionState.Connecting) {\n const noConnectionSession =\n SessionStateGraph.transition.ConnectingToNoConnection(oldSession, {\n onSessionGracePeriodElapsed: () => {\n this.onSessionGracePeriodElapsed(noConnectionSession);\n },\n });\n\n oldSession = noConnectionSession;\n }\n\n this.updateSession(oldSession);\n } else if (oldSession) {\n connectCase = 'hard reconnection';\n\n // just nuke the old session entirely and proceed as if this was new\n this.log?.info(\n `client is reconnecting to a new session (${msg.payload.sessionId}) with an old session (${oldSession.id}) already existing, closing old session`,\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n sessionId: msg.payload.sessionId,\n },\n );\n this.deleteSession(oldSession);\n oldSession = undefined;\n }\n\n if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {\n // we don't have a session, but the client is trying to reconnect\n // to an old session. we can't do anything about this, so we reject\n connectCase = 'unknown session';\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n return;\n }\n\n // from this point on, we're committed to connecting\n const sessionId = msg.payload.sessionId;\n this.log?.info(\n `handshake from ${msg.from} ok (${connectCase}), responding with handshake success`,\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n },\n );\n const responseMsg = handshakeResponseMessage({\n from: this.clientId,\n to: msg.from,\n status: {\n ok: true,\n sessionId,\n },\n });\n session.sendHandshake(responseMsg);\n\n // transition\n const connectedSession =\n SessionStateGraph.transition.WaitingForHandshakeToConnected(\n session,\n // by this point oldSession is either no connection or we dont have an old session\n oldSession,\n sessionId,\n msg.from,\n msg.tracing,\n {\n onConnectionErrored: (err) => {\n // just log, when we error we also emit close\n const errStr = coerceErrorString(err);\n this.log?.warn(\n `connection to ${connectedSession.to} errored: ${errStr}`,\n connectedSession.loggingMetadata,\n );\n },\n onConnectionClosed: () => {\n this.log?.info(\n `connection to ${connectedSession.to} closed`,\n connectedSession.loggingMetadata,\n );\n this.onConnClosed(connectedSession);\n },\n onMessage: (msg) => this.handleMsg(msg),\n onInvalidMessage: (reason) => {\n this.protocolError(ProtocolError.MessageOrderingViolated, reason);\n this.deleteSession(connectedSession);\n },\n },\n );\n\n this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);\n this.updateSession(connectedSession);\n this.pendingSessions.delete(session);\n connectedSession.startActiveHeartbeat();\n }\n\n private async validateHandshakeMetadata(\n handshakingSession: SessionWaitingForHandshake<ConnType>,\n existingSession: Session<ConnType> | undefined,\n rawMetadata: Static<\n typeof ControlMessageHandshakeRequestSchema\n >['metadata'],\n from: TransportClientId,\n ): Promise<ParsedMetadata | false> {\n let parsedMetadata: ParsedMetadata = {};\n if (this.handshakeExtensions) {\n // check that the metadata that was sent is the correct shape\n if (!Value.Check(this.handshakeExtensions.schema, rawMetadata)) {\n this.rejectHandshakeRequest(\n handshakingSession,\n from,\n 'received malformed handshake metadata',\n 'MALFORMED_HANDSHAKE_META',\n {\n ...handshakingSession.loggingMetadata,\n connectedTo: from,\n validationErrors: [\n ...Value.Errors(this.handshakeExtensions.schema, rawMetadata),\n ],\n },\n );\n\n return false;\n }\n\n const previousParsedMetadata = existingSession\n ? this.sessionHandshakeMetadata.get(existingSession.to)\n : undefined;\n\n parsedMetadata = await this.handshakeExtensions.validate(\n rawMetadata,\n previousParsedMetadata,\n );\n\n // handler rejected the connection\n if (parsedMetadata === false) {\n this.rejectHandshakeRequest(\n handshakingSession,\n from,\n 'rejected by handshake handler',\n 'REJECTED_BY_CUSTOM_HANDLER',\n {\n ...handshakingSession.loggingMetadata,\n connectedTo: from,\n clientId: this.clientId,\n },\n );\n\n return false;\n }\n }\n\n return parsedMetadata;\n }\n}\n"],"mappings":"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","names":["msg"]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createSessionTelemetryInfo,
|
|
4
4
|
generateId,
|
|
5
5
|
isAck
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6NPQ43ZP.js";
|
|
7
7
|
import {
|
|
8
8
|
NaiveJsonCodec
|
|
9
9
|
} from "./chunk-4PVU7J25.js";
|
|
@@ -344,15 +344,16 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
344
344
|
state = "Connected" /* Connected */;
|
|
345
345
|
conn;
|
|
346
346
|
listeners;
|
|
347
|
-
|
|
348
|
-
|
|
347
|
+
activeHeartbeatHandle;
|
|
348
|
+
activeHeartbeatMisses = 0;
|
|
349
|
+
passiveHeartbeatHandle;
|
|
349
350
|
get isActivelyHeartbeating() {
|
|
350
|
-
return this.
|
|
351
|
+
return this.activeHeartbeatHandle !== void 0;
|
|
351
352
|
}
|
|
352
353
|
updateBookkeeping(ack, seq) {
|
|
353
354
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
354
355
|
this.ack = seq + 1;
|
|
355
|
-
this.
|
|
356
|
+
this.activeHeartbeatMisses = 0;
|
|
356
357
|
}
|
|
357
358
|
send(msg) {
|
|
358
359
|
const constructedMsg = this.constructMsg(msg);
|
|
@@ -378,8 +379,8 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
378
379
|
}
|
|
379
380
|
}
|
|
380
381
|
startActiveHeartbeat() {
|
|
381
|
-
this.
|
|
382
|
-
const misses = this.
|
|
382
|
+
this.activeHeartbeatHandle = setInterval(() => {
|
|
383
|
+
const misses = this.activeHeartbeatMisses;
|
|
383
384
|
const missDuration = misses * this.options.heartbeatIntervalMs;
|
|
384
385
|
if (misses >= this.options.heartbeatsUntilDead) {
|
|
385
386
|
this.log?.info(
|
|
@@ -388,15 +389,32 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
388
389
|
);
|
|
389
390
|
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
390
391
|
this.conn.close();
|
|
391
|
-
clearInterval(this.
|
|
392
|
-
this.
|
|
392
|
+
clearInterval(this.activeHeartbeatHandle);
|
|
393
|
+
this.activeHeartbeatHandle = void 0;
|
|
393
394
|
return;
|
|
394
395
|
}
|
|
395
396
|
this.sendHeartbeat();
|
|
396
|
-
this.
|
|
397
|
+
this.activeHeartbeatMisses++;
|
|
397
398
|
}, this.options.heartbeatIntervalMs);
|
|
398
399
|
}
|
|
400
|
+
waitForNextHeartbeat() {
|
|
401
|
+
const duration = this.options.heartbeatsUntilDead * this.options.heartbeatIntervalMs;
|
|
402
|
+
if (this.passiveHeartbeatHandle) {
|
|
403
|
+
clearTimeout(this.passiveHeartbeatHandle);
|
|
404
|
+
this.passiveHeartbeatHandle = void 0;
|
|
405
|
+
}
|
|
406
|
+
this.passiveHeartbeatHandle = setTimeout(() => {
|
|
407
|
+
this.log?.info(
|
|
408
|
+
`closing connection to ${this.to} due to not receiving a heartbeat in the last ${duration}ms`,
|
|
409
|
+
this.loggingMetadata
|
|
410
|
+
);
|
|
411
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
412
|
+
this.conn.close();
|
|
413
|
+
this.passiveHeartbeatHandle = void 0;
|
|
414
|
+
}, duration);
|
|
415
|
+
}
|
|
399
416
|
sendHeartbeat() {
|
|
417
|
+
this.log?.debug("sending heartbeat", this.loggingMetadata);
|
|
400
418
|
this.send({
|
|
401
419
|
streamId: "heartbeat",
|
|
402
420
|
controlFlags: 1 /* AckBit */,
|
|
@@ -448,6 +466,7 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
448
466
|
});
|
|
449
467
|
if (!this.isActivelyHeartbeating) {
|
|
450
468
|
this.sendHeartbeat();
|
|
469
|
+
this.waitForNextHeartbeat();
|
|
451
470
|
}
|
|
452
471
|
};
|
|
453
472
|
_handleStateExit() {
|
|
@@ -455,8 +474,10 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
455
474
|
this.conn.removeDataListener(this.onMessageData);
|
|
456
475
|
this.conn.removeCloseListener(this.listeners.onConnectionClosed);
|
|
457
476
|
this.conn.removeErrorListener(this.listeners.onConnectionErrored);
|
|
458
|
-
clearInterval(this.
|
|
459
|
-
this.
|
|
477
|
+
clearInterval(this.activeHeartbeatHandle);
|
|
478
|
+
clearTimeout(this.passiveHeartbeatHandle);
|
|
479
|
+
this.activeHeartbeatHandle = void 0;
|
|
480
|
+
this.passiveHeartbeatHandle = void 0;
|
|
460
481
|
}
|
|
461
482
|
_handleClose() {
|
|
462
483
|
super._handleClose();
|
|
@@ -650,4 +671,4 @@ export {
|
|
|
650
671
|
SessionState,
|
|
651
672
|
SessionStateGraph
|
|
652
673
|
};
|
|
653
|
-
//# sourceMappingURL=chunk-
|
|
674
|
+
//# sourceMappingURL=chunk-XVGZYVNR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../transport/options.ts","../transport/sessionStateMachine/common.ts","../transport/sessionStateMachine/SessionConnecting.ts","../transport/sessionStateMachine/SessionNoConnection.ts","../transport/sessionStateMachine/SessionWaitingForHandshake.ts","../transport/sessionStateMachine/SessionHandshaking.ts","../transport/sessionStateMachine/SessionConnected.ts","../transport/sessionStateMachine/transitions.ts"],"sourcesContent":["import { NaiveJsonCodec } from '../codec/json';\nimport { ConnectionRetryOptions } from './rateLimit';\nimport { SessionOptions } from './sessionStateMachine/common';\n\nexport type TransportOptions = SessionOptions;\n\nexport type ProvidedTransportOptions = Partial<TransportOptions>;\n\nexport const defaultTransportOptions: TransportOptions = {\n heartbeatIntervalMs: 1_000,\n heartbeatsUntilDead: 2,\n sessionDisconnectGraceMs: 5_000,\n connectionTimeoutMs: 2_000,\n handshakeTimeoutMs: 1_000,\n codec: NaiveJsonCodec,\n};\n\nexport type ClientTransportOptions = TransportOptions & ConnectionRetryOptions;\n\nexport type ProvidedClientTransportOptions = Partial<ClientTransportOptions>;\n\nconst defaultConnectionRetryOptions: ConnectionRetryOptions = {\n baseIntervalMs: 250,\n maxJitterMs: 200,\n maxBackoffMs: 32_000,\n attemptBudgetCapacity: 5,\n budgetRestoreIntervalMs: 200,\n};\n\nexport const defaultClientTransportOptions: ClientTransportOptions = {\n ...defaultTransportOptions,\n ...defaultConnectionRetryOptions,\n};\n\nexport type ServerTransportOptions = TransportOptions;\n\nexport type ProvidedServerTransportOptions = Partial<ServerTransportOptions>;\n\nexport const defaultServerTransportOptions: ServerTransportOptions = {\n ...defaultTransportOptions,\n};\n","import { Logger, MessageMetadata } from '../../logging';\nimport { TelemetryInfo } from '../../tracing';\nimport {\n OpaqueTransportMessage,\n OpaqueTransportMessageSchema,\n PartialTransportMessage,\n TransportClientId,\n TransportMessage,\n} from '../message';\nimport { Value } from '@sinclair/typebox/value';\nimport { SessionNoConnection } from './SessionNoConnection';\nimport { SessionConnecting } from './SessionConnecting';\nimport { SessionHandshaking } from './SessionHandshaking';\nimport { SessionConnected } from './SessionConnected';\nimport { Codec } from '../../codec';\nimport { Connection } from '../connection';\nimport { generateId } from '../id';\n\nexport const enum SessionState {\n NoConnection = 'NoConnection',\n Connecting = 'Connecting',\n Handshaking = 'Handshaking',\n Connected = 'Connected',\n WaitingForHandshake = 'WaitingForHandshake',\n}\n\nexport type Session<ConnType extends Connection> =\n | SessionNoConnection\n | SessionConnecting<ConnType>\n | SessionHandshaking<ConnType>\n | SessionConnected<ConnType>;\n\nexport const ERR_CONSUMED = `session state has been consumed and is no longer valid`;\n\nabstract class StateMachineState {\n abstract readonly state: SessionState;\n\n /*\n * Whether this state has been consumed\n * and we've moved on to another state\n */\n _isConsumed: boolean;\n\n // called when we're transitioning to another state\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when the state is consumed\n // and we're transitioning to another state\n abstract _handleStateExit(): void;\n\n // called when we exit the state machine entirely\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when .close is closed\n abstract _handleClose(): void;\n\n close(): void {\n this._handleClose();\n }\n\n constructor() {\n this._isConsumed = false;\n\n // proxy helps us prevent access to properties after the state has been consumed\n // e.g. if we hold a reference to a state and try to access it after it's been consumed\n // we intercept the access and throw an error to help catch bugs\n return new Proxy(this, {\n get(target, prop) {\n // always allow access to _isConsumed, id, and state\n if (prop === '_isConsumed' || prop === 'id' || prop === 'state') {\n return Reflect.get(target, prop);\n }\n\n // modify _handleStateExit\n if (prop === '_handleStateExit') {\n return () => {\n target._isConsumed = true;\n target._handleStateExit();\n };\n }\n\n // modify _handleClose\n if (prop === '_handleClose') {\n return () => {\n target._handleStateExit();\n target._handleClose();\n };\n }\n\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: getting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.get(target, prop);\n },\n set(target, prop, value) {\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: setting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.set(target, prop, value);\n },\n });\n }\n}\n\nexport interface SessionOptions {\n /**\n * Frequency at which to send heartbeat acknowledgements\n */\n heartbeatIntervalMs: number;\n /**\n * Number of elapsed heartbeats without a response message before we consider\n * the connection dead.\n */\n heartbeatsUntilDead: number;\n /**\n * Duration to wait between connection disconnect and actual session disconnect\n */\n sessionDisconnectGraceMs: number;\n /**\n * Connection timeout in milliseconds\n */\n connectionTimeoutMs: number;\n /**\n * Handshake timeout in milliseconds\n */\n handshakeTimeoutMs: number;\n /**\n * The codec to use for encoding/decoding messages over the wire\n */\n codec: Codec;\n}\n\n// all session states have a from and options\nexport abstract class CommonSession extends StateMachineState {\n readonly from: TransportClientId;\n readonly options: SessionOptions;\n\n log?: Logger;\n abstract get loggingMetadata(): MessageMetadata;\n\n constructor(\n from: TransportClientId,\n options: SessionOptions,\n log: Logger | undefined,\n ) {\n super();\n this.from = from;\n this.options = options;\n this.log = log;\n }\n\n parseMsg(msg: Uint8Array): OpaqueTransportMessage | null {\n const parsedMsg = this.options.codec.fromBuffer(msg);\n\n if (parsedMsg === null) {\n const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));\n this.log?.error(\n `received malformed msg: ${decodedBuffer}`,\n this.loggingMetadata,\n );\n return null;\n }\n\n if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {\n this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {\n ...this.loggingMetadata,\n validationErrors: [\n ...Value.Errors(OpaqueTransportMessageSchema, parsedMsg),\n ],\n });\n\n return null;\n }\n\n return parsedMsg;\n }\n}\n\nexport type InheritedProperties = Pick<\n IdentifiedSession,\n 'id' | 'from' | 'to' | 'seq' | 'ack' | 'sendBuffer' | 'telemetry' | 'options'\n>;\n\nexport type SessionId = string;\n\n// all sessions where we know the other side's client id\nexport abstract class IdentifiedSession extends CommonSession {\n readonly id: SessionId;\n readonly telemetry: TelemetryInfo;\n readonly to: TransportClientId;\n\n /**\n * Index of the message we will send next (excluding handshake)\n */\n seq: number;\n\n /**\n * Number of unique messages we've received this session (excluding handshake)\n */\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n\n constructor(\n id: SessionId,\n from: TransportClientId,\n to: TransportClientId,\n seq: number,\n ack: number,\n sendBuffer: Array<OpaqueTransportMessage>,\n telemetry: TelemetryInfo,\n options: SessionOptions,\n log: Logger | undefined,\n ) {\n super(from, options, log);\n this.id = id;\n this.to = to;\n this.seq = seq;\n this.ack = ack;\n this.sendBuffer = sendBuffer;\n this.telemetry = telemetry;\n this.log = log;\n }\n\n get loggingMetadata(): MessageMetadata {\n const spanContext = this.telemetry.span.spanContext();\n\n return {\n clientId: this.from,\n connectedTo: this.to,\n sessionId: this.id,\n telemetry: {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n },\n };\n }\n\n constructMsg<Payload>(\n partialMsg: PartialTransportMessage<Payload>,\n ): TransportMessage<Payload> {\n const msg = {\n ...partialMsg,\n id: generateId(),\n to: this.to,\n from: this.from,\n seq: this.seq,\n ack: this.ack,\n };\n\n this.seq++;\n return msg;\n }\n\n nextSeq(): number {\n return this.sendBuffer.length > 0 ? this.sendBuffer[0].seq : this.seq;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n return constructedMsg.id;\n }\n\n _handleStateExit(): void {\n // noop\n }\n\n _handleClose(): void {\n // zero out the buffer\n this.sendBuffer.length = 0;\n this.telemetry.span.end();\n }\n}\n","import { Connection } from '../connection';\nimport { IdentifiedSession, SessionState } from './common';\n\nexport interface SessionConnectingListeners {\n onConnectionEstablished: (conn: Connection) => void;\n onConnectionFailed: (err: unknown) => void;\n\n // timeout related\n onConnectionTimeout: () => void;\n}\n\n/*\n * A session that is connecting but we don't have access to the raw connection\n * yet.\n *\n * Valid transitions:\n * - Connecting -> NoConnection (timeout)\n * - Connecting -> Handshaking (on connection established)\n */\nexport class SessionConnecting<\n ConnType extends Connection,\n> extends IdentifiedSession {\n readonly state = SessionState.Connecting as const;\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n\n connectionTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(\n connPromise: Promise<ConnType>,\n listeners: SessionConnectingListeners,\n ...args: ConstructorParameters<typeof IdentifiedSession>\n ) {\n super(...args);\n this.connPromise = connPromise;\n this.listeners = listeners;\n\n this.connectionTimeout = setTimeout(() => {\n listeners.onConnectionTimeout();\n }, this.options.connectionTimeoutMs);\n\n connPromise.then(\n (conn) => {\n if (this._isConsumed) return;\n listeners.onConnectionEstablished(conn);\n },\n (err) => {\n if (this._isConsumed) return;\n listeners.onConnectionFailed(err);\n },\n );\n }\n\n // close a pending connection if it resolves, ignore errors if the promise\n // ends up rejected anyways\n bestEffortClose() {\n void this.connPromise\n .then((conn) => conn.close())\n .catch(() => {\n // ignore errors\n });\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = undefined;\n }\n\n _handleClose(): void {\n // close the pending connection if it resolves\n this.bestEffortClose();\n super._handleClose();\n }\n}\n","import { IdentifiedSession, SessionState } from './common';\n\nexport interface SessionNoConnectionListeners {\n // timeout related\n onSessionGracePeriodElapsed: () => void;\n}\n\n/*\n * A session that is not connected and cannot send or receive messages.\n *\n * Valid transitions:\n * - NoConnection -> Connecting (on connect)\n */\nexport class SessionNoConnection extends IdentifiedSession {\n readonly state = SessionState.NoConnection as const;\n listeners: SessionNoConnectionListeners;\n\n gracePeriodTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(\n listeners: SessionNoConnectionListeners,\n ...args: ConstructorParameters<typeof IdentifiedSession>\n ) {\n super(...args);\n this.listeners = listeners;\n\n this.gracePeriodTimeout = setTimeout(() => {\n this.listeners.onSessionGracePeriodElapsed();\n }, this.options.sessionDisconnectGraceMs);\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.gracePeriodTimeout) {\n clearTimeout(this.gracePeriodTimeout);\n this.gracePeriodTimeout = undefined;\n }\n }\n}\n","import { MessageMetadata } from '../../logging';\nimport { Connection } from '../connection';\nimport { TransportMessage } from '../message';\nimport { SessionHandshakingListeners } from './SessionHandshaking';\nimport { CommonSession, SessionState } from './common';\n\n/*\n * Server-side session that has a connection but is waiting for the client to identify itself.\n *\n * Valid transitions:\n * - WaitingForHandshake -> NoConnection (on close)\n * - WaitingForHandshake -> Connected (on handshake)\n */\nexport class SessionWaitingForHandshake<\n ConnType extends Connection,\n> extends CommonSession {\n readonly state = SessionState.WaitingForHandshake as const;\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ...args: ConstructorParameters<typeof CommonSession>\n ) {\n super(...args);\n this.conn = conn;\n this.listeners = listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(listeners.onConnectionErrored);\n this.conn.addCloseListener(listeners.onConnectionClosed);\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake('could not parse message');\n return;\n }\n\n // after this fires, the listener is responsible for transitioning the session\n // and thus removing the handshake timeout\n this.listeners.onHandshake(parsedMsg);\n };\n\n get loggingMetadata(): MessageMetadata {\n return {\n clientId: this.from,\n connId: this.conn.id,\n };\n }\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n\n _handleClose(): void {\n this.conn.close();\n }\n}\n","import { Connection } from '../connection';\nimport { OpaqueTransportMessage, TransportMessage } from '../message';\nimport { IdentifiedSession, SessionState } from './common';\n\nexport interface SessionHandshakingListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (reason: string) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\n/*\n * A session that is handshaking and waiting for the other side to identify itself.\n *\n * Valid transitions:\n * - Handshaking -> NoConnection (on close)\n * - Handshaking -> Connected (on handshake)\n */\nexport class SessionHandshaking<\n ConnType extends Connection,\n> extends IdentifiedSession {\n readonly state = SessionState.Handshaking as const;\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n\n handshakeTimeout: ReturnType<typeof setTimeout>;\n\n constructor(\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ...args: ConstructorParameters<typeof IdentifiedSession>\n ) {\n super(...args);\n this.conn = conn;\n this.listeners = listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(listeners.onConnectionErrored);\n this.conn.addCloseListener(listeners.onConnectionClosed);\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake('could not parse message');\n return;\n }\n\n this.listeners.onHandshake(parsedMsg);\n };\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n clearTimeout(this.handshakeTimeout);\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport {\n ControlFlags,\n ControlMessageAckSchema,\n OpaqueTransportMessage,\n PartialTransportMessage,\n isAck,\n} from '../message';\nimport { IdentifiedSession, SessionState } from './common';\nimport { Connection } from '../connection';\nimport { SpanStatusCode } from '@opentelemetry/api';\n\nexport interface SessionConnectedListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onMessage: (msg: OpaqueTransportMessage) => void;\n onInvalidMessage: (reason: string) => void;\n}\n\n/*\n * A session that is connected and can send and receive messages.\n *\n * Valid transitions:\n * - Connected -> NoConnection (on close)\n */\nexport class SessionConnected<\n ConnType extends Connection,\n> extends IdentifiedSession {\n readonly state = SessionState.Connected as const;\n conn: ConnType;\n listeners: SessionConnectedListeners;\n\n private activeHeartbeatHandle?: ReturnType<typeof setInterval> | undefined;\n private activeHeartbeatMisses = 0;\n\n private passiveHeartbeatHandle?: ReturnType<typeof setTimeout> | undefined;\n\n get isActivelyHeartbeating() {\n return this.activeHeartbeatHandle !== undefined;\n }\n\n updateBookkeeping(ack: number, seq: number) {\n this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);\n this.ack = seq + 1;\n this.activeHeartbeatMisses = 0;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n this.conn.send(this.options.codec.toBuffer(constructedMsg));\n return constructedMsg.id;\n }\n\n constructor(\n conn: ConnType,\n listeners: SessionConnectedListeners,\n ...args: ConstructorParameters<typeof IdentifiedSession>\n ) {\n super(...args);\n this.conn = conn;\n this.listeners = listeners;\n\n this.conn.addDataListener(this.onMessageData);\n this.conn.addCloseListener(listeners.onConnectionClosed);\n this.conn.addErrorListener(listeners.onConnectionErrored);\n\n // send any buffered messages\n if (this.sendBuffer.length > 0) {\n this.log?.debug(\n `sending ${this.sendBuffer.length} buffered messages`,\n this.loggingMetadata,\n );\n }\n\n for (const msg of this.sendBuffer) {\n conn.send(this.options.codec.toBuffer(msg));\n }\n\n // dont explicity clear the buffer, we'll just filter out old messages\n // when we receive an ack\n }\n\n startActiveHeartbeat() {\n this.activeHeartbeatHandle = setInterval(() => {\n const misses = this.activeHeartbeatMisses;\n const missDuration = misses * this.options.heartbeatIntervalMs;\n if (misses >= this.options.heartbeatsUntilDead) {\n this.log?.info(\n `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,\n this.loggingMetadata,\n );\n this.telemetry.span.addEvent('closing connection due to inactivity');\n this.conn.close();\n clearInterval(this.activeHeartbeatHandle);\n this.activeHeartbeatHandle = undefined;\n return;\n }\n\n this.sendHeartbeat();\n this.activeHeartbeatMisses++;\n }, this.options.heartbeatIntervalMs);\n }\n\n waitForNextHeartbeat() {\n const duration =\n this.options.heartbeatsUntilDead * this.options.heartbeatIntervalMs;\n\n if (this.passiveHeartbeatHandle) {\n clearTimeout(this.passiveHeartbeatHandle);\n this.passiveHeartbeatHandle = undefined;\n }\n\n this.passiveHeartbeatHandle = setTimeout(() => {\n this.log?.info(\n `closing connection to ${this.to} due to not receiving a heartbeat in the last ${duration}ms`,\n this.loggingMetadata,\n );\n this.telemetry.span.addEvent('closing connection due to inactivity');\n this.conn.close();\n this.passiveHeartbeatHandle = undefined;\n }, duration);\n }\n\n private sendHeartbeat() {\n this.log?.debug('sending heartbeat', this.loggingMetadata);\n this.send({\n streamId: 'heartbeat',\n controlFlags: ControlFlags.AckBit,\n payload: {\n type: 'ACK',\n } satisfies Static<typeof ControlMessageAckSchema>,\n });\n }\n\n onMessageData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) return;\n\n // check message ordering here\n if (parsedMsg.seq !== this.ack) {\n if (parsedMsg.seq < this.ack) {\n this.log?.debug(\n `received duplicate msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack}), discarding`,\n {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n },\n );\n } else {\n const reason = `received out-of-order msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;\n this.log?.error(reason, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n tags: ['invariant-violation'],\n });\n this.telemetry.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n this.listeners.onInvalidMessage(reason);\n }\n\n return;\n }\n\n // message is ok to update bookkeeping with\n this.log?.debug(`received msg`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n this.updateBookkeeping(parsedMsg.ack, parsedMsg.seq);\n\n // dispatch directly if its not an explicit ack\n if (!isAck(parsedMsg.controlFlags)) {\n this.listeners.onMessage(parsedMsg);\n return;\n }\n\n // discard acks (unless we aren't heartbeating in which case just respond)\n this.log?.debug(`discarding msg (ack bit set)`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n // if we are not actively heartbeating, we are in passive\n // heartbeat mode and should send a response to the ack\n if (!this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n this.waitForNextHeartbeat();\n }\n };\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onMessageData);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n clearInterval(this.activeHeartbeatHandle);\n clearTimeout(this.passiveHeartbeatHandle);\n this.activeHeartbeatHandle = undefined;\n this.passiveHeartbeatHandle = undefined;\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import { OpaqueTransportMessage, TransportClientId } from '..';\nimport {\n SessionConnecting,\n SessionConnectingListeners,\n} from './SessionConnecting';\nimport {\n SessionNoConnection,\n SessionNoConnectionListeners,\n} from './SessionNoConnection';\nimport { IdentifiedSession, SessionOptions } from './common';\nimport { PropagationContext, createSessionTelemetryInfo } from '../../tracing';\nimport { SessionWaitingForHandshake } from './SessionWaitingForHandshake';\nimport {\n SessionHandshaking,\n SessionHandshakingListeners,\n} from './SessionHandshaking';\nimport {\n SessionConnected,\n SessionConnectedListeners,\n} from './SessionConnected';\nimport { generateId } from '../id';\nimport { Connection } from '../connection';\nimport { Logger } from '../../logging';\n\nfunction inheritSharedSession(\n session: IdentifiedSession,\n): ConstructorParameters<typeof IdentifiedSession> {\n return [\n session.id,\n session.from,\n session.to,\n session.seq,\n session.ack,\n session.sendBuffer,\n session.telemetry,\n session.options,\n session.log,\n ];\n}\n\n/*\n * Session state machine:\n * 1. SessionNoConnection is the client entrypoint as\n * we know who the other side is already, we just need to connect\n * 5. SessionWaitingForHandshake is the server entrypoint\n * as we have a connection but don't know who the other side is yet\n *\n * 1. SessionNoConnection ◄──┐\n * │ reconnect / connect attempt │\n * ▼ │\n * 2. SessionConnecting │\n * │ connect success ──────────────┤ connect failure\n * ▼ │\n * 3. SessionHandshaking │\n * │ handshake success ┌──────┤ connection drop\n * 5. WaitingForHandshake │ handshake failure ─────┤ │\n * │ handshake success ▼ │ │ connection drop\n * ├───────────────────────► 4. SessionConnected │ │ heartbeat misses\n * │ │ invalid message ───────┼──────┘\n * │ ▼ │\n * └───────────────────────► x. Destroy Session ◄─────┘\n * handshake failure\n */\nexport const SessionStateGraph = {\n entrypoints: {\n NoConnection(\n to: TransportClientId,\n from: TransportClientId,\n listeners: SessionNoConnectionListeners,\n options: SessionOptions,\n log?: Logger,\n ) {\n const id = `session-${generateId()}`;\n const telemetry = createSessionTelemetryInfo(id, to, from);\n const sendBuffer: Array<OpaqueTransportMessage> = [];\n\n const session = new SessionNoConnection(\n listeners,\n id,\n from,\n to,\n 0,\n 0,\n sendBuffer,\n telemetry,\n options,\n log,\n );\n\n session.log?.info(`session ${session.id} created in NoConnection state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n WaitingForHandshake<ConnType extends Connection>(\n from: TransportClientId,\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n options: SessionOptions,\n log?: Logger,\n ): SessionWaitingForHandshake<ConnType> {\n const session = new SessionWaitingForHandshake(\n conn,\n listeners,\n from,\n options,\n log,\n );\n\n session.log?.info(`session created in WaitingForHandshake state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n },\n // All of the transitions 'move'/'consume' the old session and return a new one.\n // After a session is transitioned, any usage of the old session will throw.\n transition: {\n // happy path transitions\n NoConnectionToConnecting<ConnType extends Connection>(\n oldSession: SessionNoConnection,\n connPromise: Promise<ConnType>,\n listeners: SessionConnectingListeners,\n ): SessionConnecting<ConnType> {\n const carriedState = inheritSharedSession(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionConnecting(\n connPromise,\n listeners,\n ...carriedState,\n );\n session.log?.info(\n `session ${session.id} transition from NoConnection to Connecting`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n return session;\n },\n ConnectingToHandshaking<ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ): SessionHandshaking<ConnType> {\n const carriedState = inheritSharedSession(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionHandshaking(conn, listeners, ...carriedState);\n session.log?.info(\n `session ${session.id} transition from Connecting to Handshaking`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToConnected<ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionConnectedListeners,\n ): SessionConnected<ConnType> {\n const carriedState = inheritSharedSession(oldSession);\n const conn = oldSession.conn;\n oldSession._handleStateExit();\n\n const session = new SessionConnected(conn, listeners, ...carriedState);\n session.log?.info(\n `session ${session.id} transition from Handshaking to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n WaitingForHandshakeToConnected<ConnType extends Connection>(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n oldSession: SessionNoConnection | undefined,\n sessionId: string,\n to: TransportClientId,\n propagationCtx: PropagationContext | undefined,\n listeners: SessionConnectedListeners,\n ): SessionConnected<ConnType> {\n const conn = pendingSession.conn;\n const { from, options } = pendingSession;\n const carriedState: ConstructorParameters<typeof IdentifiedSession> =\n oldSession\n ? // old session exists, inherit state\n inheritSharedSession(oldSession)\n : // old session does not exist, create new state\n [\n sessionId,\n from,\n to,\n 0,\n 0,\n [],\n createSessionTelemetryInfo(sessionId, to, from, propagationCtx),\n options,\n pendingSession.log,\n ];\n\n pendingSession._handleStateExit();\n oldSession?._handleStateExit();\n\n const session = new SessionConnected(conn, listeners, ...carriedState);\n session.log?.info(\n `session ${session.id} transition from WaitingForHandshake to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n // disconnect paths\n ConnectingToNoConnection<ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection {\n const carriedState = inheritSharedSession(oldSession);\n oldSession.bestEffortClose();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection(listeners, ...carriedState);\n session.log?.info(\n `session ${session.id} transition from Connecting to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToNoConnection<ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection {\n const carriedState = inheritSharedSession(oldSession);\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection(listeners, ...carriedState);\n session.log?.info(\n `session ${session.id} transition from Handshaking to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectedToNoConnection<ConnType extends Connection>(\n oldSession: SessionConnected<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection {\n const carriedState = inheritSharedSession(oldSession);\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection(listeners, ...carriedState);\n session.log?.info(\n `session ${session.id} transition from Connected to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n },\n} as const;\n"],"mappings":"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","names":["SessionState"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Connection, T as Transport, o as ClientTransportOptions, L as LeakyBucketRateLimit, p as ClientHandshakeOptions, b as ProvidedClientTransportOptions, f as SessionConnecting, e as SessionNoConnection, g as SessionHandshaking, h as SessionConnected } from './handshake-
|
|
1
|
+
import { C as Connection, T as Transport, o as ClientTransportOptions, L as LeakyBucketRateLimit, p as ClientHandshakeOptions, b as ProvidedClientTransportOptions, f as SessionConnecting, e as SessionNoConnection, g as SessionHandshaking, h as SessionConnected } from './handshake-3772d7ca.js';
|
|
2
2
|
import { c as TransportClientId, P as PartialTransportMessage, b as OpaqueTransportMessage } from './message-e6c560fd.js';
|
|
3
3
|
|
|
4
4
|
declare abstract class ClientTransport<ConnType extends Connection> extends Transport<ConnType> {
|
|
@@ -114,13 +114,15 @@ declare class SessionConnected<ConnType extends Connection> extends IdentifiedSe
|
|
|
114
114
|
readonly state: SessionState.Connected;
|
|
115
115
|
conn: ConnType;
|
|
116
116
|
listeners: SessionConnectedListeners;
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
private activeHeartbeatHandle?;
|
|
118
|
+
private activeHeartbeatMisses;
|
|
119
|
+
private passiveHeartbeatHandle?;
|
|
119
120
|
get isActivelyHeartbeating(): boolean;
|
|
120
121
|
updateBookkeeping(ack: number, seq: number): void;
|
|
121
122
|
send(msg: PartialTransportMessage): string;
|
|
122
123
|
constructor(conn: ConnType, listeners: SessionConnectedListeners, ...args: ConstructorParameters<typeof IdentifiedSession>);
|
|
123
124
|
startActiveHeartbeat(): void;
|
|
125
|
+
waitForNextHeartbeat(): void;
|
|
124
126
|
private sendHeartbeat;
|
|
125
127
|
onMessageData: (msg: Uint8Array) => void;
|
|
126
128
|
_handleStateExit(): void;
|
package/dist/router/index.cjs
CHANGED
|
@@ -752,7 +752,7 @@ function Err(error) {
|
|
|
752
752
|
var import_api = require("@opentelemetry/api");
|
|
753
753
|
|
|
754
754
|
// package.json
|
|
755
|
-
var version = "0.
|
|
755
|
+
var version = "0.25.0";
|
|
756
756
|
|
|
757
757
|
// tracing/index.ts
|
|
758
758
|
function getPropagationContext(ctx) {
|
|
@@ -950,23 +950,31 @@ function handleStream(transport, serverId, init, serviceName, procedureName) {
|
|
|
950
950
|
}
|
|
951
951
|
const pipeInputToTransport = async () => {
|
|
952
952
|
for await (const rawIn of inputStream) {
|
|
953
|
-
const
|
|
953
|
+
const m2 = {
|
|
954
954
|
streamId,
|
|
955
955
|
payload: rawIn,
|
|
956
956
|
controlFlags: 0
|
|
957
957
|
};
|
|
958
958
|
if (firstMessage) {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
959
|
+
m2.serviceName = serviceName;
|
|
960
|
+
m2.procedureName = procedureName;
|
|
961
|
+
m2.tracing = getPropagationContext(ctx);
|
|
962
|
+
m2.controlFlags |= 2 /* StreamOpenBit */;
|
|
963
963
|
firstMessage = false;
|
|
964
964
|
}
|
|
965
|
-
transport.send(serverId,
|
|
965
|
+
transport.send(serverId, m2);
|
|
966
966
|
}
|
|
967
967
|
if (!healthyClose)
|
|
968
968
|
return;
|
|
969
|
-
|
|
969
|
+
const m = closeStreamMessage(streamId);
|
|
970
|
+
if (firstMessage) {
|
|
971
|
+
m.serviceName = serviceName;
|
|
972
|
+
m.procedureName = procedureName;
|
|
973
|
+
m.tracing = getPropagationContext(ctx);
|
|
974
|
+
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
975
|
+
firstMessage = false;
|
|
976
|
+
}
|
|
977
|
+
transport.send(serverId, m);
|
|
970
978
|
};
|
|
971
979
|
void pipeInputToTransport();
|
|
972
980
|
function onMessage(msg) {
|
|
@@ -1082,23 +1090,31 @@ function handleUpload(transport, serverId, init, serviceName, procedureName) {
|
|
|
1082
1090
|
}
|
|
1083
1091
|
const pipeInputToTransport = async () => {
|
|
1084
1092
|
for await (const rawIn of inputStream) {
|
|
1085
|
-
const
|
|
1093
|
+
const m2 = {
|
|
1086
1094
|
streamId,
|
|
1087
1095
|
payload: rawIn,
|
|
1088
1096
|
controlFlags: 0
|
|
1089
1097
|
};
|
|
1090
1098
|
if (firstMessage) {
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1099
|
+
m2.serviceName = serviceName;
|
|
1100
|
+
m2.procedureName = procedureName;
|
|
1101
|
+
m2.tracing = getPropagationContext(ctx);
|
|
1102
|
+
m2.controlFlags |= 2 /* StreamOpenBit */;
|
|
1095
1103
|
firstMessage = false;
|
|
1096
1104
|
}
|
|
1097
|
-
transport.send(serverId,
|
|
1105
|
+
transport.send(serverId, m2);
|
|
1098
1106
|
}
|
|
1099
1107
|
if (!healthyClose)
|
|
1100
1108
|
return;
|
|
1101
|
-
|
|
1109
|
+
const m = closeStreamMessage(streamId);
|
|
1110
|
+
if (firstMessage) {
|
|
1111
|
+
m.serviceName = serviceName;
|
|
1112
|
+
m.procedureName = procedureName;
|
|
1113
|
+
m.tracing = getPropagationContext(ctx);
|
|
1114
|
+
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
1115
|
+
firstMessage = false;
|
|
1116
|
+
}
|
|
1117
|
+
transport.send(serverId, m);
|
|
1102
1118
|
};
|
|
1103
1119
|
void pipeInputToTransport();
|
|
1104
1120
|
const responsePromise = new Promise((resolve) => {
|