@replit/river 0.16.1 → 0.17.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/README.md +25 -11
- package/dist/{chunk-Q6WPGM3K.js → chunk-7IQO434V.js} +11 -3
- package/dist/{chunk-7SPCAA6Q.js → chunk-LQMPJI3S.js} +101 -97
- package/dist/{chunk-GFRAOY75.js → chunk-VH3NGOXQ.js} +8 -17
- package/dist/{chunk-L65XWBX2.js → chunk-VJRLJ3JU.js} +1 -1
- package/dist/{chunk-XLJGKNV2.js → chunk-Y6DLSCKU.js} +1 -1
- package/dist/{connection-94896f3b.d.ts → connection-0767dc6b.d.ts} +1 -1
- package/dist/{connection-99346822.d.ts → connection-f31edbcd.d.ts} +1 -1
- package/dist/{index-2e402bb8.d.ts → index-8df0bdfb.d.ts} +27 -31
- package/dist/{procedures-f0226890.d.ts → procedures-b5ddb54d.d.ts} +1 -1
- package/dist/router/index.cjs +12 -4
- package/dist/router/index.d.cts +8 -4
- package/dist/router/index.d.ts +8 -4
- package/dist/router/index.js +2 -2
- package/dist/transport/impls/uds/client.cjs +80 -69
- package/dist/transport/impls/uds/client.d.cts +2 -2
- package/dist/transport/impls/uds/client.d.ts +2 -2
- package/dist/transport/impls/uds/client.js +3 -3
- package/dist/transport/impls/uds/server.cjs +82 -94
- package/dist/transport/impls/uds/server.d.cts +2 -2
- package/dist/transport/impls/uds/server.d.ts +2 -2
- package/dist/transport/impls/uds/server.js +3 -3
- package/dist/transport/impls/ws/client.cjs +80 -69
- package/dist/transport/impls/ws/client.d.cts +2 -2
- package/dist/transport/impls/ws/client.d.ts +2 -2
- package/dist/transport/impls/ws/client.js +3 -3
- package/dist/transport/impls/ws/server.cjs +82 -94
- package/dist/transport/impls/ws/server.d.cts +2 -2
- package/dist/transport/impls/ws/server.d.ts +2 -2
- package/dist/transport/impls/ws/server.js +3 -3
- package/dist/transport/index.cjs +107 -115
- package/dist/transport/index.d.cts +1 -1
- package/dist/transport/index.d.ts +1 -1
- package/dist/transport/index.js +2 -2
- package/dist/util/testHelpers.cjs +45 -18
- package/dist/util/testHelpers.d.cts +4 -9
- package/dist/util/testHelpers.d.ts +4 -9
- package/dist/util/testHelpers.js +8 -14
- package/package.json +1 -1
|
@@ -170,7 +170,12 @@ declare class Session<ConnType extends Connection> {
|
|
|
170
170
|
/**
|
|
171
171
|
* The unique ID of this session.
|
|
172
172
|
*/
|
|
173
|
-
|
|
173
|
+
id: string;
|
|
174
|
+
/**
|
|
175
|
+
* What the other side advertised as their session ID
|
|
176
|
+
* for this session.
|
|
177
|
+
*/
|
|
178
|
+
advertisedSessionId?: string;
|
|
174
179
|
/**
|
|
175
180
|
* Number of messages we've sent along this session (excluding handshake and acks)
|
|
176
181
|
*/
|
|
@@ -191,8 +196,8 @@ declare class Session<ConnType extends Connection> {
|
|
|
191
196
|
/**
|
|
192
197
|
* The interval for sending heartbeats.
|
|
193
198
|
*/
|
|
194
|
-
private heartbeat
|
|
195
|
-
constructor(
|
|
199
|
+
private heartbeat;
|
|
200
|
+
constructor(conn: ConnType | undefined, from: TransportClientId, to: TransportClientId, options: SessionOptions);
|
|
196
201
|
/**
|
|
197
202
|
* Sends a message over the session's connection.
|
|
198
203
|
* If the connection is not ready or the message fails to send, the message can be buffered for retry unless skipped.
|
|
@@ -222,6 +227,7 @@ declare const ProtocolError: {
|
|
|
222
227
|
readonly RetriesExceeded: "conn_retry_exceeded";
|
|
223
228
|
readonly HandshakeFailed: "handshake_failed";
|
|
224
229
|
readonly UseAfterDestroy: "use_after_destroy";
|
|
230
|
+
readonly MessageOrderingViolated: "message_ordering_violated";
|
|
225
231
|
};
|
|
226
232
|
type ProtocolErrorType = (typeof ProtocolError)[keyof typeof ProtocolError];
|
|
227
233
|
interface EventMap {
|
|
@@ -308,14 +314,10 @@ declare class LeakyBucketRateLimit {
|
|
|
308
314
|
* @property {'destroyed'} destroyed - The transport is permanently destroyed and cannot be reopened.
|
|
309
315
|
*/
|
|
310
316
|
type TransportStatus = 'open' | 'closed' | 'destroyed';
|
|
311
|
-
type
|
|
312
|
-
type
|
|
313
|
-
type ProvidedClientTransportOptions =
|
|
314
|
-
|
|
315
|
-
} & ProvidedTransportOptions;
|
|
316
|
-
type ClientTransportOptions = SessionOptions & {
|
|
317
|
-
connectionRetryOptions: ConnectionRetryOptions;
|
|
318
|
-
};
|
|
317
|
+
type TransportOptions = SessionOptions;
|
|
318
|
+
type ProvidedTransportOptions = Partial<TransportOptions>;
|
|
319
|
+
type ProvidedClientTransportOptions = Partial<ClientTransportOptions>;
|
|
320
|
+
type ClientTransportOptions = SessionOptions & ConnectionRetryOptions;
|
|
319
321
|
/**
|
|
320
322
|
* Transports manage the lifecycle (creation/deletion) of sessions and connections. Its responsibilities include:
|
|
321
323
|
*
|
|
@@ -347,13 +349,6 @@ type ClientTransportOptions = SessionOptions & {
|
|
|
347
349
|
* @abstract
|
|
348
350
|
*/
|
|
349
351
|
declare abstract class Transport<ConnType extends Connection> {
|
|
350
|
-
/**
|
|
351
|
-
* Unique per instance of the transport.
|
|
352
|
-
* This allows us to distinguish reconnects to different
|
|
353
|
-
* transports.
|
|
354
|
-
*/
|
|
355
|
-
instanceId: string;
|
|
356
|
-
connectedInstanceIds: Map<string, string>;
|
|
357
352
|
/**
|
|
358
353
|
* A flag indicating whether the transport has been destroyed.
|
|
359
354
|
* A destroyed transport will not attempt to reconnect and cannot be used again.
|
|
@@ -404,8 +399,9 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
404
399
|
* and we know the identity of the connected client.
|
|
405
400
|
* @param conn The connection object.
|
|
406
401
|
*/
|
|
407
|
-
protected onConnect(conn: ConnType, connectedTo: TransportClientId,
|
|
408
|
-
|
|
402
|
+
protected onConnect(conn: ConnType, connectedTo: TransportClientId, advertisedSessionId: string): Session<ConnType>;
|
|
403
|
+
protected createSession(to: TransportClientId, conn?: ConnType): Session<ConnType>;
|
|
404
|
+
protected getOrCreateSession(to: TransportClientId, conn?: ConnType): Session<ConnType>;
|
|
409
405
|
protected deleteSession(session: Session<ConnType>): void;
|
|
410
406
|
/**
|
|
411
407
|
* The downstream implementation needs to call this when a connection is closed.
|
|
@@ -469,13 +465,16 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
469
465
|
*/
|
|
470
466
|
inflightConnectionPromises: Map<TransportClientId, Promise<ConnType>>;
|
|
471
467
|
retryBudget: LeakyBucketRateLimit;
|
|
472
|
-
|
|
473
|
-
|
|
468
|
+
/**
|
|
469
|
+
* A flag indicating whether the transport should automatically reconnect
|
|
470
|
+
* when a connection is dropped.
|
|
471
|
+
* Realistically, this should always be true for clients unless you are writing
|
|
472
|
+
* tests or a special case where you don't want to reconnect.
|
|
473
|
+
*/
|
|
474
|
+
reconnectOnConnectionDrop: boolean;
|
|
475
|
+
constructor(clientId: TransportClientId, providedOptions?: ProvidedClientTransportOptions);
|
|
474
476
|
protected handleConnection(conn: ConnType, to: TransportClientId): void;
|
|
475
|
-
receiveHandshakeResponseMessage(data: Uint8Array):
|
|
476
|
-
instanceId: string;
|
|
477
|
-
from: string;
|
|
478
|
-
};
|
|
477
|
+
receiveHandshakeResponseMessage(data: Uint8Array, conn: ConnType): Session<ConnType> | false;
|
|
479
478
|
/**
|
|
480
479
|
* Abstract method that creates a new {@link Connection} object.
|
|
481
480
|
* This should call {@link handleConnection} when the connection is created.
|
|
@@ -496,10 +495,7 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
496
495
|
declare abstract class ServerTransport<ConnType extends Connection> extends Transport<ConnType> {
|
|
497
496
|
constructor(clientId: TransportClientId, providedOptions?: ProvidedTransportOptions);
|
|
498
497
|
protected handleConnection(conn: ConnType): void;
|
|
499
|
-
receiveHandshakeRequestMessage(data: Uint8Array, conn: ConnType):
|
|
500
|
-
instanceId: string;
|
|
501
|
-
from: string;
|
|
502
|
-
};
|
|
498
|
+
receiveHandshakeRequestMessage(data: Uint8Array, conn: ConnType): Session<ConnType> | false;
|
|
503
499
|
}
|
|
504
500
|
|
|
505
|
-
export { Connection as C, EventMap as E, OpaqueTransportMessage as O, PartialTransportMessage as P,
|
|
501
|
+
export { Connection as C, EventMap as E, OpaqueTransportMessage as O, PartialTransportMessage as P, SessionOptions as S, Transport as T, ClientTransport as a, TransportClientId as b, ProvidedClientTransportOptions as c, ServerTransport as d, ProvidedTransportOptions as e, Session as f, TransportStatus as g, TransportMessageSchema as h, OpaqueTransportMessageSchema as i, TransportMessage as j, isStreamOpen as k, isStreamClose as l, EventTypes as m, EventHandler as n, ProtocolError as o, ProtocolErrorType as p };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TObject, TUnion, TString, TSchema, TNever, TLiteral, Static } from '@sinclair/typebox';
|
|
2
2
|
import { Pushable } from 'it-pushable';
|
|
3
|
-
import { b as TransportClientId,
|
|
3
|
+
import { b as TransportClientId, f as Session, C as Connection } from './index-8df0bdfb.js';
|
|
4
4
|
|
|
5
5
|
type TLiteralString = TLiteral<string>;
|
|
6
6
|
type RiverErrorSchema = TObject<{
|
package/dist/router/index.cjs
CHANGED
|
@@ -567,14 +567,14 @@ var ControlMessageCloseSchema = import_typebox3.Type.Object({
|
|
|
567
567
|
var ControlMessageHandshakeRequestSchema = import_typebox3.Type.Object({
|
|
568
568
|
type: import_typebox3.Type.Literal("HANDSHAKE_REQ"),
|
|
569
569
|
protocolVersion: import_typebox3.Type.String(),
|
|
570
|
-
|
|
570
|
+
sessionId: import_typebox3.Type.String()
|
|
571
571
|
});
|
|
572
572
|
var ControlMessageHandshakeResponseSchema = import_typebox3.Type.Object({
|
|
573
573
|
type: import_typebox3.Type.Literal("HANDSHAKE_RESP"),
|
|
574
574
|
status: import_typebox3.Type.Union([
|
|
575
575
|
import_typebox3.Type.Object({
|
|
576
576
|
ok: import_typebox3.Type.Literal(true),
|
|
577
|
-
|
|
577
|
+
sessionId: import_typebox3.Type.String()
|
|
578
578
|
}),
|
|
579
579
|
import_typebox3.Type.Object({
|
|
580
580
|
ok: import_typebox3.Type.Literal(false),
|
|
@@ -655,8 +655,13 @@ function _createRecursiveProxy(callback, path) {
|
|
|
655
655
|
});
|
|
656
656
|
return proxy;
|
|
657
657
|
}
|
|
658
|
-
var
|
|
659
|
-
|
|
658
|
+
var defaultClientOptions = {
|
|
659
|
+
connectOnInvoke: true,
|
|
660
|
+
eagerlyConnect: true
|
|
661
|
+
};
|
|
662
|
+
var createClient = (transport, serverId, providedClientOptions = {}) => {
|
|
663
|
+
const options = { ...defaultClientOptions, ...providedClientOptions };
|
|
664
|
+
if (options.eagerlyConnect) {
|
|
660
665
|
void transport.connect(serverId);
|
|
661
666
|
}
|
|
662
667
|
return _createRecursiveProxy(async (opts) => {
|
|
@@ -672,6 +677,9 @@ var createClient = (transport, serverId, eagerlyConnect = true) => {
|
|
|
672
677
|
input
|
|
673
678
|
)}`
|
|
674
679
|
);
|
|
680
|
+
if (options.connectOnInvoke && !transport.connections.has(serverId)) {
|
|
681
|
+
void transport.connect(serverId);
|
|
682
|
+
}
|
|
675
683
|
if (procType === "rpc") {
|
|
676
684
|
return handleRpc(
|
|
677
685
|
transport,
|
package/dist/router/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TObject, TUnion, Static } from '@sinclair/typebox';
|
|
2
|
-
import { e as ProcedureMap, c as RiverUncaughtSchema, U as Unbranded, B as Branded, A as AnyProcedure, P as PayloadType, b as Result, R as RiverError, S as ServiceContext } from '../procedures-
|
|
3
|
-
export { E as Err, O as Ok, a as Procedure, d as ProcedureResult, f as RPCProcedure, m as RiverErrorSchema, j as ServiceContextWithState, k as ServiceContextWithTransportInfo, i as StreamProcedure, h as SubscriptionProcedure, l as UNCAUGHT_ERROR, g as UploadProcedure, V as ValidProcType } from '../procedures-
|
|
4
|
-
import {
|
|
2
|
+
import { e as ProcedureMap, c as RiverUncaughtSchema, U as Unbranded, B as Branded, A as AnyProcedure, P as PayloadType, b as Result, R as RiverError, S as ServiceContext } from '../procedures-b5ddb54d.js';
|
|
3
|
+
export { E as Err, O as Ok, a as Procedure, d as ProcedureResult, f as RPCProcedure, m as RiverErrorSchema, j as ServiceContextWithState, k as ServiceContextWithTransportInfo, i as StreamProcedure, h as SubscriptionProcedure, l as UNCAUGHT_ERROR, g as UploadProcedure, V as ValidProcType } from '../procedures-b5ddb54d.js';
|
|
4
|
+
import { d as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-8df0bdfb.js';
|
|
5
5
|
import { Pushable } from 'it-pushable';
|
|
6
6
|
import '../types-3e5768ec.js';
|
|
7
7
|
|
|
@@ -381,6 +381,10 @@ type ServiceClient<Router extends AnyService> = {
|
|
|
381
381
|
type ServerClient<Srv extends Server<ServiceSchemaMap>> = {
|
|
382
382
|
[SvcName in keyof Srv['services']]: ServiceClient<Srv['services'][SvcName]>;
|
|
383
383
|
};
|
|
384
|
+
interface ClientOptions {
|
|
385
|
+
connectOnInvoke: boolean;
|
|
386
|
+
eagerlyConnect: boolean;
|
|
387
|
+
}
|
|
384
388
|
/**
|
|
385
389
|
* Creates a client for a given server using the provided transport.
|
|
386
390
|
* Note that the client only needs the type of the server, not the actual
|
|
@@ -394,6 +398,6 @@ type ServerClient<Srv extends Server<ServiceSchemaMap>> = {
|
|
|
394
398
|
* @param {Transport} transport - The transport to use for communication.
|
|
395
399
|
* @returns The client for the server.
|
|
396
400
|
*/
|
|
397
|
-
declare const createClient: <Srv extends Server<ServiceSchemaMap>>(transport: ClientTransport<Connection>, serverId: TransportClientId,
|
|
401
|
+
declare const createClient: <Srv extends Server<ServiceSchemaMap>>(transport: ClientTransport<Connection>, serverId: TransportClientId, providedClientOptions?: Partial<ClientOptions>) => ServerClient<Srv>;
|
|
398
402
|
|
|
399
403
|
export { PayloadType, ProcErrors, ProcHandler, ProcInit, ProcInput, ProcOutput, ProcType, ProcedureMap, Result, RiverError, RiverUncaughtSchema, Server, ServerClient, Service, ServiceConfiguration, ServiceContext, ServiceSchema, createClient, createServer };
|
package/dist/router/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TObject, TUnion, Static } from '@sinclair/typebox';
|
|
2
|
-
import { e as ProcedureMap, c as RiverUncaughtSchema, U as Unbranded, B as Branded, A as AnyProcedure, P as PayloadType, b as Result, R as RiverError, S as ServiceContext } from '../procedures-
|
|
3
|
-
export { E as Err, O as Ok, a as Procedure, d as ProcedureResult, f as RPCProcedure, m as RiverErrorSchema, j as ServiceContextWithState, k as ServiceContextWithTransportInfo, i as StreamProcedure, h as SubscriptionProcedure, l as UNCAUGHT_ERROR, g as UploadProcedure, V as ValidProcType } from '../procedures-
|
|
4
|
-
import {
|
|
2
|
+
import { e as ProcedureMap, c as RiverUncaughtSchema, U as Unbranded, B as Branded, A as AnyProcedure, P as PayloadType, b as Result, R as RiverError, S as ServiceContext } from '../procedures-b5ddb54d.js';
|
|
3
|
+
export { E as Err, O as Ok, a as Procedure, d as ProcedureResult, f as RPCProcedure, m as RiverErrorSchema, j as ServiceContextWithState, k as ServiceContextWithTransportInfo, i as StreamProcedure, h as SubscriptionProcedure, l as UNCAUGHT_ERROR, g as UploadProcedure, V as ValidProcType } from '../procedures-b5ddb54d.js';
|
|
4
|
+
import { d as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-8df0bdfb.js';
|
|
5
5
|
import { Pushable } from 'it-pushable';
|
|
6
6
|
import '../types-3e5768ec.js';
|
|
7
7
|
|
|
@@ -381,6 +381,10 @@ type ServiceClient<Router extends AnyService> = {
|
|
|
381
381
|
type ServerClient<Srv extends Server<ServiceSchemaMap>> = {
|
|
382
382
|
[SvcName in keyof Srv['services']]: ServiceClient<Srv['services'][SvcName]>;
|
|
383
383
|
};
|
|
384
|
+
interface ClientOptions {
|
|
385
|
+
connectOnInvoke: boolean;
|
|
386
|
+
eagerlyConnect: boolean;
|
|
387
|
+
}
|
|
384
388
|
/**
|
|
385
389
|
* Creates a client for a given server using the provided transport.
|
|
386
390
|
* Note that the client only needs the type of the server, not the actual
|
|
@@ -394,6 +398,6 @@ type ServerClient<Srv extends Server<ServiceSchemaMap>> = {
|
|
|
394
398
|
* @param {Transport} transport - The transport to use for communication.
|
|
395
399
|
* @returns The client for the server.
|
|
396
400
|
*/
|
|
397
|
-
declare const createClient: <Srv extends Server<ServiceSchemaMap>>(transport: ClientTransport<Connection>, serverId: TransportClientId,
|
|
401
|
+
declare const createClient: <Srv extends Server<ServiceSchemaMap>>(transport: ClientTransport<Connection>, serverId: TransportClientId, providedClientOptions?: Partial<ClientOptions>) => ServerClient<Srv>;
|
|
398
402
|
|
|
399
403
|
export { PayloadType, ProcErrors, ProcHandler, ProcInit, ProcInput, ProcOutput, ProcType, ProcedureMap, Result, RiverError, RiverUncaughtSchema, Server, ServerClient, Service, ServiceConfiguration, ServiceContext, ServiceSchema, createClient, createServer };
|
package/dist/router/index.js
CHANGED
|
@@ -52,18 +52,18 @@ var ControlMessageAckSchema = import_typebox.Type.Object({
|
|
|
52
52
|
var ControlMessageCloseSchema = import_typebox.Type.Object({
|
|
53
53
|
type: import_typebox.Type.Literal("CLOSE")
|
|
54
54
|
});
|
|
55
|
-
var PROTOCOL_VERSION = "v1";
|
|
55
|
+
var PROTOCOL_VERSION = "v1.1";
|
|
56
56
|
var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
|
|
57
57
|
type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
|
|
58
58
|
protocolVersion: import_typebox.Type.String(),
|
|
59
|
-
|
|
59
|
+
sessionId: import_typebox.Type.String()
|
|
60
60
|
});
|
|
61
61
|
var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
|
|
62
62
|
type: import_typebox.Type.Literal("HANDSHAKE_RESP"),
|
|
63
63
|
status: import_typebox.Type.Union([
|
|
64
64
|
import_typebox.Type.Object({
|
|
65
65
|
ok: import_typebox.Type.Literal(true),
|
|
66
|
-
|
|
66
|
+
sessionId: import_typebox.Type.String()
|
|
67
67
|
}),
|
|
68
68
|
import_typebox.Type.Object({
|
|
69
69
|
ok: import_typebox.Type.Literal(false),
|
|
@@ -80,7 +80,7 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
|
|
|
80
80
|
var OpaqueTransportMessageSchema = TransportMessageSchema(
|
|
81
81
|
import_typebox.Type.Unknown()
|
|
82
82
|
);
|
|
83
|
-
function handshakeRequestMessage(from, to,
|
|
83
|
+
function handshakeRequestMessage(from, to, sessionId) {
|
|
84
84
|
return {
|
|
85
85
|
id: (0, import_nanoid.nanoid)(),
|
|
86
86
|
from,
|
|
@@ -92,7 +92,7 @@ function handshakeRequestMessage(from, to, instanceId) {
|
|
|
92
92
|
payload: {
|
|
93
93
|
type: "HANDSHAKE_REQ",
|
|
94
94
|
protocolVersion: PROTOCOL_VERSION,
|
|
95
|
-
|
|
95
|
+
sessionId
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
}
|
|
@@ -125,7 +125,12 @@ var Session = class {
|
|
|
125
125
|
/**
|
|
126
126
|
* The unique ID of this session.
|
|
127
127
|
*/
|
|
128
|
-
|
|
128
|
+
id;
|
|
129
|
+
/**
|
|
130
|
+
* What the other side advertised as their session ID
|
|
131
|
+
* for this session.
|
|
132
|
+
*/
|
|
133
|
+
advertisedSessionId;
|
|
129
134
|
/**
|
|
130
135
|
* Number of messages we've sent along this session (excluding handshake and acks)
|
|
131
136
|
*/
|
|
@@ -147,11 +152,11 @@ var Session = class {
|
|
|
147
152
|
* The interval for sending heartbeats.
|
|
148
153
|
*/
|
|
149
154
|
heartbeat;
|
|
150
|
-
constructor(
|
|
155
|
+
constructor(conn, from, to, options) {
|
|
156
|
+
this.id = `session-${nanoid2(12)}`;
|
|
151
157
|
this.options = options;
|
|
152
|
-
this.debugId = `sess-${unsafeId()}`;
|
|
153
158
|
this.from = from;
|
|
154
|
-
this.to =
|
|
159
|
+
this.to = to;
|
|
155
160
|
this.connection = conn;
|
|
156
161
|
this.codec = options.codec;
|
|
157
162
|
this.heartbeatMisses = 0;
|
|
@@ -191,7 +196,7 @@ var Session = class {
|
|
|
191
196
|
log?.info(
|
|
192
197
|
`${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
|
|
193
198
|
);
|
|
194
|
-
this.closeStaleConnection(
|
|
199
|
+
this.closeStaleConnection();
|
|
195
200
|
}
|
|
196
201
|
return;
|
|
197
202
|
}
|
|
@@ -222,33 +227,37 @@ var Session = class {
|
|
|
222
227
|
log?.debug(`${this.from} -- resending ${msg.id} (seq: ${msg.seq})`);
|
|
223
228
|
const ok = this.connection.send(this.codec.toBuffer(msg));
|
|
224
229
|
if (!ok) {
|
|
225
|
-
const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.
|
|
230
|
+
const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.id}) (if you hit this code path something is seriously wrong)`;
|
|
226
231
|
log?.error(msg2);
|
|
227
232
|
throw new Error(msg2);
|
|
228
233
|
}
|
|
229
234
|
}
|
|
230
235
|
}
|
|
231
236
|
updateBookkeeping(ack, seq) {
|
|
237
|
+
if (seq + 1 < this.ack) {
|
|
238
|
+
log?.error(`${this.from} -- received stale seq ${seq} + 1 < ${this.ack}`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
232
241
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq > ack);
|
|
233
242
|
this.ack = seq + 1;
|
|
234
243
|
}
|
|
235
244
|
closeStaleConnection(conn) {
|
|
236
|
-
if (
|
|
245
|
+
if (this.connection === void 0 || this.connection === conn)
|
|
237
246
|
return;
|
|
238
247
|
log?.info(
|
|
239
|
-
`${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.
|
|
248
|
+
`${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.id}) to ${this.to}`
|
|
240
249
|
);
|
|
241
250
|
this.connection.close();
|
|
242
251
|
this.connection = void 0;
|
|
243
252
|
}
|
|
244
253
|
replaceWithNewConnection(newConn) {
|
|
245
|
-
this.closeStaleConnection(
|
|
254
|
+
this.closeStaleConnection(newConn);
|
|
246
255
|
this.cancelGrace();
|
|
247
256
|
this.connection = newConn;
|
|
248
257
|
}
|
|
249
258
|
beginGrace(cb) {
|
|
250
259
|
log?.info(
|
|
251
|
-
`${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.
|
|
260
|
+
`${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.id}) to ${this.to} is closed`
|
|
252
261
|
);
|
|
253
262
|
this.disconnectionGrace = setTimeout(() => {
|
|
254
263
|
this.close();
|
|
@@ -259,11 +268,12 @@ var Session = class {
|
|
|
259
268
|
cancelGrace() {
|
|
260
269
|
this.heartbeatMisses = 0;
|
|
261
270
|
clearTimeout(this.disconnectionGrace);
|
|
271
|
+
this.disconnectionGrace = void 0;
|
|
262
272
|
}
|
|
263
273
|
// closed when we want to discard the whole session
|
|
264
274
|
// (i.e. shutdown or session disconnect)
|
|
265
275
|
close() {
|
|
266
|
-
this.closeStaleConnection(
|
|
276
|
+
this.closeStaleConnection();
|
|
267
277
|
this.cancelGrace();
|
|
268
278
|
this.resetBufferedMessages();
|
|
269
279
|
clearInterval(this.heartbeat);
|
|
@@ -392,7 +402,8 @@ var import_value = require("@sinclair/typebox/value");
|
|
|
392
402
|
var ProtocolError = {
|
|
393
403
|
RetriesExceeded: "conn_retry_exceeded",
|
|
394
404
|
HandshakeFailed: "handshake_failed",
|
|
395
|
-
UseAfterDestroy: "use_after_destroy"
|
|
405
|
+
UseAfterDestroy: "use_after_destroy",
|
|
406
|
+
MessageOrderingViolated: "message_ordering_violated"
|
|
396
407
|
};
|
|
397
408
|
var EventDispatcher = class {
|
|
398
409
|
eventListeners = {};
|
|
@@ -421,9 +432,6 @@ var EventDispatcher = class {
|
|
|
421
432
|
}
|
|
422
433
|
};
|
|
423
434
|
|
|
424
|
-
// transport/transport.ts
|
|
425
|
-
var import_nanoid3 = require("nanoid");
|
|
426
|
-
|
|
427
435
|
// util/stringify.ts
|
|
428
436
|
function coerceErrorString(err) {
|
|
429
437
|
if (err instanceof Error) {
|
|
@@ -570,17 +578,10 @@ var defaultConnectionRetryOptions = {
|
|
|
570
578
|
budgetRestoreIntervalMs: 200
|
|
571
579
|
};
|
|
572
580
|
var defaultClientTransportOptions = {
|
|
573
|
-
|
|
574
|
-
...
|
|
581
|
+
...defaultTransportOptions,
|
|
582
|
+
...defaultConnectionRetryOptions
|
|
575
583
|
};
|
|
576
584
|
var Transport = class {
|
|
577
|
-
/**
|
|
578
|
-
* Unique per instance of the transport.
|
|
579
|
-
* This allows us to distinguish reconnects to different
|
|
580
|
-
* transports.
|
|
581
|
-
*/
|
|
582
|
-
instanceId = (0, import_nanoid3.nanoid)();
|
|
583
|
-
connectedInstanceIds = /* @__PURE__ */ new Map();
|
|
584
585
|
/**
|
|
585
586
|
* A flag indicating whether the transport has been destroyed.
|
|
586
587
|
* A destroyed transport will not attempt to reconnect and cannot be used again.
|
|
@@ -633,41 +634,41 @@ var Transport = class {
|
|
|
633
634
|
* and we know the identity of the connected client.
|
|
634
635
|
* @param conn The connection object.
|
|
635
636
|
*/
|
|
636
|
-
onConnect(conn, connectedTo,
|
|
637
|
+
onConnect(conn, connectedTo, advertisedSessionId) {
|
|
637
638
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
638
639
|
status: "connect",
|
|
639
640
|
conn
|
|
640
641
|
});
|
|
641
642
|
let oldSession = this.sessions.get(connectedTo);
|
|
642
|
-
|
|
643
|
-
if (oldSession && lastInstanceId !== void 0 && lastInstanceId !== instanceId) {
|
|
643
|
+
if (oldSession?.advertisedSessionId && oldSession.advertisedSessionId !== advertisedSessionId) {
|
|
644
644
|
log?.warn(
|
|
645
|
-
`${this.clientId} -- connection from ${connectedTo} is a different
|
|
645
|
+
`${this.clientId} -- connection from ${connectedTo} is a different session (id: ${advertisedSessionId}, last connected to: ${oldSession.advertisedSessionId}), starting a new session`
|
|
646
646
|
);
|
|
647
647
|
oldSession.close();
|
|
648
648
|
this.deleteSession(oldSession);
|
|
649
649
|
oldSession = void 0;
|
|
650
650
|
}
|
|
651
|
-
this.connectedInstanceIds.set(connectedTo, instanceId);
|
|
652
651
|
if (oldSession === void 0) {
|
|
653
652
|
const newSession = this.createSession(connectedTo, conn);
|
|
653
|
+
newSession.advertisedSessionId = advertisedSessionId;
|
|
654
654
|
log?.info(
|
|
655
|
-
`${this.clientId} -- new connection (id: ${conn.debugId}) for new session (id: ${newSession.
|
|
655
|
+
`${this.clientId} -- new connection (id: ${conn.debugId}) for new session (id: ${newSession.id}) to ${connectedTo}`
|
|
656
656
|
);
|
|
657
657
|
return newSession;
|
|
658
658
|
}
|
|
659
659
|
log?.info(
|
|
660
|
-
`${this.clientId} -- new connection (id: ${conn.debugId}) for existing session (id: ${oldSession.
|
|
660
|
+
`${this.clientId} -- new connection (id: ${conn.debugId}) for existing session (id: ${oldSession.id}) to ${connectedTo}`
|
|
661
661
|
);
|
|
662
662
|
oldSession.replaceWithNewConnection(conn);
|
|
663
663
|
oldSession.sendBufferedMessages();
|
|
664
|
+
oldSession.advertisedSessionId = advertisedSessionId;
|
|
664
665
|
return oldSession;
|
|
665
666
|
}
|
|
666
|
-
createSession(
|
|
667
|
+
createSession(to, conn) {
|
|
667
668
|
const session = new Session(
|
|
668
|
-
this.clientId,
|
|
669
|
-
connectedTo,
|
|
670
669
|
conn,
|
|
670
|
+
this.clientId,
|
|
671
|
+
to,
|
|
671
672
|
this.options
|
|
672
673
|
);
|
|
673
674
|
this.sessions.set(session.to, session);
|
|
@@ -677,10 +678,20 @@ var Transport = class {
|
|
|
677
678
|
});
|
|
678
679
|
return session;
|
|
679
680
|
}
|
|
681
|
+
getOrCreateSession(to, conn) {
|
|
682
|
+
let session = this.sessions.get(to);
|
|
683
|
+
if (!session) {
|
|
684
|
+
session = this.createSession(to, conn);
|
|
685
|
+
log?.info(
|
|
686
|
+
`${this.clientId} -- no session for ${to}, created a new one (id: ${session.id})`
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
return session;
|
|
690
|
+
}
|
|
680
691
|
deleteSession(session) {
|
|
681
692
|
this.sessions.delete(session.to);
|
|
682
693
|
log?.info(
|
|
683
|
-
`${this.clientId} -- session ${session.
|
|
694
|
+
`${this.clientId} -- session ${session.id} disconnect from ${session.to}`
|
|
684
695
|
);
|
|
685
696
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
686
697
|
status: "disconnect",
|
|
@@ -748,11 +759,14 @@ var Transport = class {
|
|
|
748
759
|
)}`
|
|
749
760
|
);
|
|
750
761
|
} else {
|
|
762
|
+
const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
|
|
751
763
|
log?.error(
|
|
752
|
-
`${this.clientId} --
|
|
764
|
+
`${this.clientId} -- fatal: ${errMsg}, marking connection as dead: ${JSON.stringify(
|
|
765
|
+
msg
|
|
766
|
+
)}`
|
|
753
767
|
);
|
|
768
|
+
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
754
769
|
session.close();
|
|
755
|
-
this.deleteSession(session);
|
|
756
770
|
}
|
|
757
771
|
return;
|
|
758
772
|
}
|
|
@@ -799,14 +813,7 @@ var Transport = class {
|
|
|
799
813
|
);
|
|
800
814
|
return void 0;
|
|
801
815
|
}
|
|
802
|
-
|
|
803
|
-
if (!session) {
|
|
804
|
-
session = this.createSession(to, void 0);
|
|
805
|
-
log?.info(
|
|
806
|
-
`${this.clientId} -- no session for ${to}, created a new one (id: ${session.debugId})`
|
|
807
|
-
);
|
|
808
|
-
}
|
|
809
|
-
return session.send(msg);
|
|
816
|
+
return this.getOrCreateSession(to).send(msg);
|
|
810
817
|
}
|
|
811
818
|
// control helpers
|
|
812
819
|
sendCloseStream(to, streamId) {
|
|
@@ -858,7 +865,13 @@ var ClientTransport = class extends Transport {
|
|
|
858
865
|
*/
|
|
859
866
|
inflightConnectionPromises;
|
|
860
867
|
retryBudget;
|
|
861
|
-
|
|
868
|
+
/**
|
|
869
|
+
* A flag indicating whether the transport should automatically reconnect
|
|
870
|
+
* when a connection is dropped.
|
|
871
|
+
* Realistically, this should always be true for clients unless you are writing
|
|
872
|
+
* tests or a special case where you don't want to reconnect.
|
|
873
|
+
*/
|
|
874
|
+
reconnectOnConnectionDrop = true;
|
|
862
875
|
constructor(clientId, providedOptions) {
|
|
863
876
|
super(clientId, providedOptions);
|
|
864
877
|
this.options = {
|
|
@@ -866,21 +879,20 @@ var ClientTransport = class extends Transport {
|
|
|
866
879
|
...providedOptions
|
|
867
880
|
};
|
|
868
881
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
869
|
-
this.retryBudget = new LeakyBucketRateLimit(
|
|
870
|
-
this.options.connectionRetryOptions
|
|
871
|
-
);
|
|
882
|
+
this.retryBudget = new LeakyBucketRateLimit(this.options);
|
|
872
883
|
}
|
|
873
884
|
handleConnection(conn, to) {
|
|
874
885
|
if (this.state !== "open")
|
|
875
886
|
return;
|
|
876
887
|
let session = void 0;
|
|
877
888
|
const handshakeHandler = (data) => {
|
|
878
|
-
const
|
|
879
|
-
if (!
|
|
889
|
+
const maybeSession = this.receiveHandshakeResponseMessage(data, conn);
|
|
890
|
+
if (!maybeSession) {
|
|
880
891
|
conn.close();
|
|
881
892
|
return;
|
|
893
|
+
} else {
|
|
894
|
+
session = maybeSession;
|
|
882
895
|
}
|
|
883
|
-
session = this.onConnect(conn, handshake.from, handshake.instanceId);
|
|
884
896
|
conn.removeDataListener(handshakeHandler);
|
|
885
897
|
conn.addDataListener((data2) => {
|
|
886
898
|
const parsed = this.parseMsg(data2);
|
|
@@ -900,7 +912,7 @@ var ClientTransport = class extends Transport {
|
|
|
900
912
|
`${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
|
|
901
913
|
);
|
|
902
914
|
this.inflightConnectionPromises.delete(to);
|
|
903
|
-
if (this.
|
|
915
|
+
if (this.reconnectOnConnectionDrop) {
|
|
904
916
|
void this.connect(to);
|
|
905
917
|
}
|
|
906
918
|
});
|
|
@@ -910,7 +922,7 @@ var ClientTransport = class extends Transport {
|
|
|
910
922
|
);
|
|
911
923
|
});
|
|
912
924
|
}
|
|
913
|
-
receiveHandshakeResponseMessage(data) {
|
|
925
|
+
receiveHandshakeResponseMessage(data, conn) {
|
|
914
926
|
const parsed = this.parseMsg(data);
|
|
915
927
|
if (!parsed) {
|
|
916
928
|
this.protocolError(
|
|
@@ -943,12 +955,14 @@ var ClientTransport = class extends Transport {
|
|
|
943
955
|
);
|
|
944
956
|
return false;
|
|
945
957
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
958
|
+
log?.debug(`${this.clientId} -- handshake from ${parsed.from} ok`);
|
|
959
|
+
const session = this.onConnect(
|
|
960
|
+
conn,
|
|
961
|
+
parsed.from,
|
|
962
|
+
parsed.payload.status.sessionId
|
|
949
963
|
);
|
|
950
964
|
this.retryBudget.startRestoringBudget(parsed.from);
|
|
951
|
-
return
|
|
965
|
+
return session;
|
|
952
966
|
}
|
|
953
967
|
/**
|
|
954
968
|
* Manually attempts to connect to a client.
|
|
@@ -1006,7 +1020,7 @@ var ClientTransport = class extends Transport {
|
|
|
1006
1020
|
} catch (error) {
|
|
1007
1021
|
this.inflightConnectionPromises.delete(to);
|
|
1008
1022
|
const errStr = coerceErrorString(error);
|
|
1009
|
-
if (!this.
|
|
1023
|
+
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
1010
1024
|
log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
|
|
1011
1025
|
} else {
|
|
1012
1026
|
log?.warn(
|
|
@@ -1017,11 +1031,8 @@ var ClientTransport = class extends Transport {
|
|
|
1017
1031
|
}
|
|
1018
1032
|
}
|
|
1019
1033
|
sendHandshake(to, conn) {
|
|
1020
|
-
const
|
|
1021
|
-
|
|
1022
|
-
to,
|
|
1023
|
-
this.instanceId
|
|
1024
|
-
);
|
|
1034
|
+
const session = this.getOrCreateSession(to, conn);
|
|
1035
|
+
const requestMsg = handshakeRequestMessage(this.clientId, to, session.id);
|
|
1025
1036
|
log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
|
|
1026
1037
|
conn.send(this.codec.toBuffer(requestMsg));
|
|
1027
1038
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-
|
|
2
|
-
import { U as UdsConnection } from '../../../connection-
|
|
1
|
+
import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-8df0bdfb.js';
|
|
2
|
+
import { U as UdsConnection } from '../../../connection-0767dc6b.js';
|
|
3
3
|
import '../../../types-3e5768ec.js';
|
|
4
4
|
import '@sinclair/typebox';
|
|
5
5
|
import 'node:net';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-
|
|
2
|
-
import { U as UdsConnection } from '../../../connection-
|
|
1
|
+
import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-8df0bdfb.js';
|
|
2
|
+
import { U as UdsConnection } from '../../../connection-0767dc6b.js';
|
|
3
3
|
import '../../../types-3e5768ec.js';
|
|
4
4
|
import '@sinclair/typebox';
|
|
5
5
|
import 'node:net';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UdsConnection
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-VJRLJ3JU.js";
|
|
4
4
|
import {
|
|
5
5
|
ClientTransport
|
|
6
|
-
} from "../../../chunk-
|
|
7
|
-
import "../../../chunk-
|
|
6
|
+
} from "../../../chunk-LQMPJI3S.js";
|
|
7
|
+
import "../../../chunk-VH3NGOXQ.js";
|
|
8
8
|
import {
|
|
9
9
|
log
|
|
10
10
|
} from "../../../chunk-H4BYJELI.js";
|