@replit/river 0.12.0 → 0.12.1
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-24O3BKZA.js → chunk-55XUAPC6.js} +1 -1
- package/dist/{chunk-IUDKWAOK.js → chunk-M6LY25P2.js} +1 -1
- package/dist/{chunk-ANGOKBE5.js → chunk-QEYN2Z6O.js} +63 -45
- package/dist/{chunk-4HOR4NUO.js → chunk-RDTTKCGV.js} +1 -1
- package/dist/{chunk-XOTIAXAH.js → chunk-TKINU53F.js} +1 -1
- package/dist/{chunk-WTOIOXB7.js → chunk-XFFS4UOD.js} +5 -3
- package/dist/{connection-2956a1c5.d.ts → connection-bf7811aa.d.ts} +1 -1
- package/dist/{connection-cd963ed5.d.ts → connection-d880aa4a.d.ts} +1 -1
- package/dist/{connection-aaea7c88.d.ts → connection-eb10d250.d.ts} +1 -1
- package/dist/{index-d91775d9.d.ts → index-0c0a69f6.d.ts} +9 -11
- package/dist/router/index.cjs +2 -1
- package/dist/router/index.d.cts +1 -1
- package/dist/router/index.d.ts +1 -1
- package/dist/router/index.js +2 -2
- package/dist/transport/impls/stdio/client.cjs +53 -35
- package/dist/transport/impls/stdio/client.d.cts +2 -2
- package/dist/transport/impls/stdio/client.d.ts +2 -2
- package/dist/transport/impls/stdio/client.js +3 -3
- package/dist/transport/impls/stdio/server.cjs +51 -29
- package/dist/transport/impls/stdio/server.d.cts +2 -2
- package/dist/transport/impls/stdio/server.d.ts +2 -2
- package/dist/transport/impls/stdio/server.js +3 -3
- package/dist/transport/impls/uds/client.cjs +53 -35
- 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 +51 -29
- 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 +59 -35
- 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 +9 -3
- package/dist/transport/impls/ws/server.cjs +51 -29
- 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 +67 -47
- 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.d.cts +1 -1
- package/dist/util/testHelpers.d.ts +1 -1
- package/dist/util/testHelpers.js +2 -2
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
bootResponseMessage,
|
|
11
11
|
coerceErrorString,
|
|
12
12
|
isAck
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XFFS4UOD.js";
|
|
14
14
|
import {
|
|
15
15
|
log
|
|
16
16
|
} from "./chunk-H4BYJELI.js";
|
|
@@ -53,9 +53,9 @@ var Connection = class {
|
|
|
53
53
|
this.debugId = `conn-${unsafeId()}`;
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
-
var HEARTBEAT_INTERVAL_MS =
|
|
57
|
-
var HEARTBEATS_TILL_DEAD =
|
|
58
|
-
var SESSION_DISCONNECT_GRACE_MS =
|
|
56
|
+
var HEARTBEAT_INTERVAL_MS = 1e3;
|
|
57
|
+
var HEARTBEATS_TILL_DEAD = 2;
|
|
58
|
+
var SESSION_DISCONNECT_GRACE_MS = 5e3;
|
|
59
59
|
var Session = class {
|
|
60
60
|
codec;
|
|
61
61
|
/**
|
|
@@ -138,11 +138,13 @@ var Session = class {
|
|
|
138
138
|
return fullMsg.id;
|
|
139
139
|
}
|
|
140
140
|
sendHeartbeat() {
|
|
141
|
-
if (this.heartbeatMisses >= HEARTBEATS_TILL_DEAD
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
if (this.heartbeatMisses >= HEARTBEATS_TILL_DEAD) {
|
|
142
|
+
if (this.connection) {
|
|
143
|
+
log?.info(
|
|
144
|
+
`${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
|
|
145
|
+
);
|
|
146
|
+
this.halfCloseConnection();
|
|
147
|
+
}
|
|
146
148
|
return;
|
|
147
149
|
}
|
|
148
150
|
this.send(
|
|
@@ -179,7 +181,6 @@ var Session = class {
|
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
updateBookkeeping(ack, seq) {
|
|
182
|
-
this.heartbeatMisses = 0;
|
|
183
184
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq > ack);
|
|
184
185
|
this.ack = seq + 1;
|
|
185
186
|
}
|
|
@@ -211,6 +212,7 @@ var Session = class {
|
|
|
211
212
|
}, SESSION_DISCONNECT_GRACE_MS);
|
|
212
213
|
}
|
|
213
214
|
cancelGrace() {
|
|
215
|
+
this.heartbeatMisses = 0;
|
|
214
216
|
clearTimeout(this.disconnectionGrace);
|
|
215
217
|
}
|
|
216
218
|
get connected() {
|
|
@@ -257,6 +259,13 @@ var defaultTransportOptions = {
|
|
|
257
259
|
codec: NaiveJsonCodec
|
|
258
260
|
};
|
|
259
261
|
var Transport = class {
|
|
262
|
+
/**
|
|
263
|
+
* Unique per instance of the transport.
|
|
264
|
+
* This allows us to distinguish reconnects to different
|
|
265
|
+
* transports.
|
|
266
|
+
*/
|
|
267
|
+
instanceId = nanoid2();
|
|
268
|
+
connectedInstanceIds = /* @__PURE__ */ new Map();
|
|
260
269
|
/**
|
|
261
270
|
* A flag indicating whether the transport has been destroyed.
|
|
262
271
|
* A destroyed transport will not attempt to reconnect and cannot be used again.
|
|
@@ -318,12 +327,23 @@ var Transport = class {
|
|
|
318
327
|
* and we know the identity of the connected client.
|
|
319
328
|
* @param conn The connection object.
|
|
320
329
|
*/
|
|
321
|
-
onConnect(conn, connectedTo) {
|
|
330
|
+
onConnect(conn, connectedTo, instanceId) {
|
|
322
331
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
323
332
|
status: "connect",
|
|
324
333
|
conn
|
|
325
334
|
});
|
|
326
|
-
|
|
335
|
+
let session = this.sessions.get(connectedTo);
|
|
336
|
+
const lastInstanceId = this.connectedInstanceIds.get(connectedTo);
|
|
337
|
+
if (session && lastInstanceId !== instanceId && lastInstanceId !== void 0) {
|
|
338
|
+
log?.debug(
|
|
339
|
+
`${this.clientId} -- handshake from ${connectedTo} has different server instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
|
|
340
|
+
);
|
|
341
|
+
session.resetBufferedMessages();
|
|
342
|
+
session.closeStaleConnection();
|
|
343
|
+
this.deleteSession(session);
|
|
344
|
+
session = void 0;
|
|
345
|
+
}
|
|
346
|
+
this.connectedInstanceIds.set(connectedTo, instanceId);
|
|
327
347
|
if (session === void 0) {
|
|
328
348
|
const newSession = this.createSession(connectedTo, conn);
|
|
329
349
|
log?.info(
|
|
@@ -389,11 +409,13 @@ var Transport = class {
|
|
|
389
409
|
const parsedMsg = this.codec.fromBuffer(msg);
|
|
390
410
|
if (parsedMsg === null) {
|
|
391
411
|
const decodedBuffer = new TextDecoder().decode(msg);
|
|
392
|
-
log?.
|
|
412
|
+
log?.error(
|
|
413
|
+
`${this.clientId} -- received malformed msg, killing conn: ${decodedBuffer}`
|
|
414
|
+
);
|
|
393
415
|
return null;
|
|
394
416
|
}
|
|
395
417
|
if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
396
|
-
log?.
|
|
418
|
+
log?.error(
|
|
397
419
|
`${this.clientId} -- received invalid msg: ${JSON.stringify(
|
|
398
420
|
parsedMsg
|
|
399
421
|
)}`
|
|
@@ -412,9 +434,6 @@ var Transport = class {
|
|
|
412
434
|
* @param msg The received message.
|
|
413
435
|
*/
|
|
414
436
|
handleMsg(msg) {
|
|
415
|
-
if (!msg) {
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
437
|
const session = this.sessionByClientId(msg.from);
|
|
419
438
|
session.cancelGrace();
|
|
420
439
|
log?.debug(`${this.clientId} -- received msg: ${JSON.stringify(msg)}`);
|
|
@@ -516,7 +535,6 @@ var ClientTransport = class extends Transport {
|
|
|
516
535
|
*/
|
|
517
536
|
inflightConnectionPromises;
|
|
518
537
|
tryReconnecting = true;
|
|
519
|
-
serverInstanceIds = /* @__PURE__ */ new Map();
|
|
520
538
|
constructor(clientId, providedOptions) {
|
|
521
539
|
super(clientId, providedOptions);
|
|
522
540
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
@@ -524,7 +542,14 @@ var ClientTransport = class extends Transport {
|
|
|
524
542
|
handleConnection(conn, to) {
|
|
525
543
|
const bootHandler = this.receiveWithBootSequence(conn, () => {
|
|
526
544
|
conn.removeDataListener(bootHandler);
|
|
527
|
-
conn.addDataListener((data) =>
|
|
545
|
+
conn.addDataListener((data) => {
|
|
546
|
+
const parsed = this.parseMsg(data);
|
|
547
|
+
if (!parsed) {
|
|
548
|
+
conn.close();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
this.handleMsg(parsed);
|
|
552
|
+
});
|
|
528
553
|
});
|
|
529
554
|
conn.addDataListener(bootHandler);
|
|
530
555
|
conn.addCloseListener(() => {
|
|
@@ -556,7 +581,7 @@ var ClientTransport = class extends Transport {
|
|
|
556
581
|
try {
|
|
557
582
|
const conn = await reconnectPromise;
|
|
558
583
|
this.state = "open";
|
|
559
|
-
const requestMsg = bootRequestMessage(this.clientId, to);
|
|
584
|
+
const requestMsg = bootRequestMessage(this.clientId, to, this.instanceId);
|
|
560
585
|
log?.debug(`${this.clientId} -- sending boot handshake to ${to}`);
|
|
561
586
|
conn.send(this.codec.toBuffer(requestMsg));
|
|
562
587
|
} catch (error) {
|
|
@@ -579,8 +604,10 @@ var ClientTransport = class extends Transport {
|
|
|
579
604
|
receiveWithBootSequence(conn, sessionCb) {
|
|
580
605
|
const bootHandler = (data) => {
|
|
581
606
|
const parsed = this.parseMsg(data);
|
|
582
|
-
if (!parsed)
|
|
607
|
+
if (!parsed) {
|
|
608
|
+
conn.close();
|
|
583
609
|
return;
|
|
610
|
+
}
|
|
584
611
|
if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
585
612
|
log?.warn(
|
|
586
613
|
`${this.clientId} -- received invalid handshake resp: ${JSON.stringify(parsed)}`
|
|
@@ -595,22 +622,11 @@ var ClientTransport = class extends Transport {
|
|
|
595
622
|
);
|
|
596
623
|
return;
|
|
597
624
|
}
|
|
598
|
-
const oldSession = this.sessions.get(parsed.from);
|
|
599
625
|
const serverInstanceId = parsed.payload.status.instanceId;
|
|
600
|
-
const lastServerInstanceId = this.serverInstanceIds.get(parsed.from);
|
|
601
|
-
if (oldSession && lastServerInstanceId !== serverInstanceId && lastServerInstanceId !== void 0) {
|
|
602
|
-
log?.debug(
|
|
603
|
-
`${this.clientId} -- handshake from ${parsed.from} has different server instance (got: ${serverInstanceId}, last connected to: ${lastServerInstanceId}), starting a new session`
|
|
604
|
-
);
|
|
605
|
-
oldSession.resetBufferedMessages();
|
|
606
|
-
oldSession.closeStaleConnection();
|
|
607
|
-
this.deleteSession(oldSession);
|
|
608
|
-
}
|
|
609
626
|
log?.debug(
|
|
610
627
|
`${this.clientId} -- handshake from ${parsed.from} ok (server instance: ${serverInstanceId})`
|
|
611
628
|
);
|
|
612
|
-
this.
|
|
613
|
-
sessionCb(this.onConnect(conn, parsed.from));
|
|
629
|
+
sessionCb(this.onConnect(conn, parsed.from, serverInstanceId));
|
|
614
630
|
};
|
|
615
631
|
return bootHandler;
|
|
616
632
|
}
|
|
@@ -621,14 +637,6 @@ var ClientTransport = class extends Transport {
|
|
|
621
637
|
}
|
|
622
638
|
};
|
|
623
639
|
var ServerTransport = class extends Transport {
|
|
624
|
-
/**
|
|
625
|
-
* Unique per instance of server transport.
|
|
626
|
-
* This allows us to distinguish reconnects to different
|
|
627
|
-
* server transports at the same reachable address and signal
|
|
628
|
-
* the appropriate session disconnect back to the client at the
|
|
629
|
-
* boot stage.
|
|
630
|
-
*/
|
|
631
|
-
instanceId = nanoid2();
|
|
632
640
|
constructor(clientId, providedOptions) {
|
|
633
641
|
super(clientId, providedOptions);
|
|
634
642
|
log?.info(
|
|
@@ -643,7 +651,14 @@ var ServerTransport = class extends Transport {
|
|
|
643
651
|
(establishedSession) => {
|
|
644
652
|
session = establishedSession;
|
|
645
653
|
conn.removeDataListener(bootHandler);
|
|
646
|
-
conn.addDataListener((data) =>
|
|
654
|
+
conn.addDataListener((data) => {
|
|
655
|
+
const parsed = this.parseMsg(data);
|
|
656
|
+
if (!parsed) {
|
|
657
|
+
conn.close();
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
this.handleMsg(parsed);
|
|
661
|
+
});
|
|
647
662
|
}
|
|
648
663
|
);
|
|
649
664
|
conn.addDataListener(bootHandler);
|
|
@@ -666,8 +681,10 @@ var ServerTransport = class extends Transport {
|
|
|
666
681
|
receiveWithBootSequence(conn, sessionCb) {
|
|
667
682
|
const bootHandler = (data) => {
|
|
668
683
|
const parsed = this.parseMsg(data);
|
|
669
|
-
if (!parsed)
|
|
684
|
+
if (!parsed) {
|
|
685
|
+
conn.close();
|
|
670
686
|
return;
|
|
687
|
+
}
|
|
671
688
|
if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
|
|
672
689
|
const responseMsg2 = bootResponseMessage(
|
|
673
690
|
this.clientId,
|
|
@@ -683,8 +700,9 @@ var ServerTransport = class extends Transport {
|
|
|
683
700
|
);
|
|
684
701
|
return;
|
|
685
702
|
}
|
|
703
|
+
const instanceId = parsed.payload.instanceId;
|
|
686
704
|
log?.debug(
|
|
687
|
-
`${this.clientId} -- handshake from ${parsed.from} ok, responding with handshake success`
|
|
705
|
+
`${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
|
|
688
706
|
);
|
|
689
707
|
const responseMsg = bootResponseMessage(
|
|
690
708
|
this.clientId,
|
|
@@ -693,7 +711,7 @@ var ServerTransport = class extends Transport {
|
|
|
693
711
|
true
|
|
694
712
|
);
|
|
695
713
|
conn.send(this.codec.toBuffer(responseMsg));
|
|
696
|
-
sessionCb(this.onConnect(conn, parsed.from));
|
|
714
|
+
sessionCb(this.onConnect(conn, parsed.from, instanceId));
|
|
697
715
|
};
|
|
698
716
|
return bootHandler;
|
|
699
717
|
}
|
|
@@ -22,7 +22,8 @@ var ControlMessageCloseSchema = Type.Object({
|
|
|
22
22
|
var PROTOCOL_VERSION = "v1";
|
|
23
23
|
var ControlMessageHandshakeRequestSchema = Type.Object({
|
|
24
24
|
type: Type.Literal("HANDSHAKE_REQ"),
|
|
25
|
-
protocolVersion: Type.Literal(PROTOCOL_VERSION)
|
|
25
|
+
protocolVersion: Type.Literal(PROTOCOL_VERSION),
|
|
26
|
+
instanceId: Type.String()
|
|
26
27
|
});
|
|
27
28
|
var ControlMessageHandshakeResponseSchema = Type.Object({
|
|
28
29
|
type: Type.Literal("HANDSHAKE_RESP"),
|
|
@@ -46,7 +47,7 @@ var ControlMessagePayloadSchema = Type.Union([
|
|
|
46
47
|
var OpaqueTransportMessageSchema = TransportMessageSchema(
|
|
47
48
|
Type.Unknown()
|
|
48
49
|
);
|
|
49
|
-
function bootRequestMessage(from, to) {
|
|
50
|
+
function bootRequestMessage(from, to, instanceId) {
|
|
50
51
|
return {
|
|
51
52
|
id: nanoid(),
|
|
52
53
|
from,
|
|
@@ -57,7 +58,8 @@ function bootRequestMessage(from, to) {
|
|
|
57
58
|
controlFlags: 0,
|
|
58
59
|
payload: {
|
|
59
60
|
type: "HANDSHAKE_REQ",
|
|
60
|
-
protocolVersion: PROTOCOL_VERSION
|
|
61
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
62
|
+
instanceId
|
|
61
63
|
}
|
|
62
64
|
};
|
|
63
65
|
}
|
|
@@ -295,6 +295,13 @@ interface TransportOptions {
|
|
|
295
295
|
* @abstract
|
|
296
296
|
*/
|
|
297
297
|
declare abstract class Transport<ConnType extends Connection> {
|
|
298
|
+
/**
|
|
299
|
+
* Unique per instance of the transport.
|
|
300
|
+
* This allows us to distinguish reconnects to different
|
|
301
|
+
* transports.
|
|
302
|
+
*/
|
|
303
|
+
instanceId: string;
|
|
304
|
+
connectedInstanceIds: Map<string, string>;
|
|
298
305
|
/**
|
|
299
306
|
* A flag indicating whether the transport has been destroyed.
|
|
300
307
|
* A destroyed transport will not attempt to reconnect and cannot be used again.
|
|
@@ -346,7 +353,7 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
346
353
|
* and we know the identity of the connected client.
|
|
347
354
|
* @param conn The connection object.
|
|
348
355
|
*/
|
|
349
|
-
protected onConnect(conn: ConnType, connectedTo: TransportClientId): Session<ConnType>;
|
|
356
|
+
protected onConnect(conn: ConnType, connectedTo: TransportClientId, instanceId: string): Session<ConnType>;
|
|
350
357
|
private createSession;
|
|
351
358
|
protected deleteSession(session: Session<ConnType>): void;
|
|
352
359
|
/**
|
|
@@ -365,7 +372,7 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
365
372
|
* You generally shouldn't need to override this in downstream transport implementations.
|
|
366
373
|
* @param msg The received message.
|
|
367
374
|
*/
|
|
368
|
-
handleMsg(msg: OpaqueTransportMessage
|
|
375
|
+
handleMsg(msg: OpaqueTransportMessage): void;
|
|
369
376
|
/**
|
|
370
377
|
* Adds a listener to this transport.
|
|
371
378
|
* @param the type of event to listen for
|
|
@@ -405,7 +412,6 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
405
412
|
*/
|
|
406
413
|
inflightConnectionPromises: Map<TransportClientId, Promise<ConnType>>;
|
|
407
414
|
tryReconnecting: boolean;
|
|
408
|
-
serverInstanceIds: Map<string, string>;
|
|
409
415
|
constructor(clientId: TransportClientId, providedOptions?: Partial<TransportOptions>);
|
|
410
416
|
protected handleConnection(conn: ConnType, to: TransportClientId): void;
|
|
411
417
|
/**
|
|
@@ -426,14 +432,6 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
426
432
|
onDisconnect(conn: ConnType, connectedTo: string | undefined): void;
|
|
427
433
|
}
|
|
428
434
|
declare abstract class ServerTransport<ConnType extends Connection> extends Transport<ConnType> {
|
|
429
|
-
/**
|
|
430
|
-
* Unique per instance of server transport.
|
|
431
|
-
* This allows us to distinguish reconnects to different
|
|
432
|
-
* server transports at the same reachable address and signal
|
|
433
|
-
* the appropriate session disconnect back to the client at the
|
|
434
|
-
* boot stage.
|
|
435
|
-
*/
|
|
436
|
-
instanceId: string;
|
|
437
435
|
constructor(clientId: TransportClientId, providedOptions?: Partial<TransportOptions>);
|
|
438
436
|
protected handleConnection(conn: ConnType): void;
|
|
439
437
|
receiveWithBootSequence(conn: ConnType, sessionCb: (sess: Session<ConnType>) => void): (data: Uint8Array) => void;
|
package/dist/router/index.cjs
CHANGED
|
@@ -427,7 +427,8 @@ var ControlMessageCloseSchema = import_typebox2.Type.Object({
|
|
|
427
427
|
var PROTOCOL_VERSION = "v1";
|
|
428
428
|
var ControlMessageHandshakeRequestSchema = import_typebox2.Type.Object({
|
|
429
429
|
type: import_typebox2.Type.Literal("HANDSHAKE_REQ"),
|
|
430
|
-
protocolVersion: import_typebox2.Type.Literal(PROTOCOL_VERSION)
|
|
430
|
+
protocolVersion: import_typebox2.Type.Literal(PROTOCOL_VERSION),
|
|
431
|
+
instanceId: import_typebox2.Type.String()
|
|
431
432
|
});
|
|
432
433
|
var ControlMessageHandshakeResponseSchema = import_typebox2.Type.Object({
|
|
433
434
|
type: import_typebox2.Type.Literal("HANDSHAKE_RESP"),
|
package/dist/router/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as AnyService, P as PayloadType, b as Result, R as RiverError, S as ServiceContext, d as ProcType, e as ProcInput, f as ProcOutput, g as ProcErrors, h as ProcHasInit, i as ProcInit } from '../builder-c593de11.js';
|
|
2
2
|
export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, o as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-c593de11.js';
|
|
3
|
-
import { T as Transport, C as Connection, b as TransportClientId } from '../index-
|
|
3
|
+
import { T as Transport, C as Connection, b as TransportClientId } from '../index-0c0a69f6.js';
|
|
4
4
|
import { Pushable } from 'it-pushable';
|
|
5
5
|
import { Static } from '@sinclair/typebox';
|
|
6
6
|
import '../types-3e5768ec.js';
|
package/dist/router/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as AnyService, P as PayloadType, b as Result, R as RiverError, S as ServiceContext, d as ProcType, e as ProcInput, f as ProcOutput, g as ProcErrors, h as ProcHasInit, i as ProcInit } from '../builder-c593de11.js';
|
|
2
2
|
export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, o as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-c593de11.js';
|
|
3
|
-
import { T as Transport, C as Connection, b as TransportClientId } from '../index-
|
|
3
|
+
import { T as Transport, C as Connection, b as TransportClientId } from '../index-0c0a69f6.js';
|
|
4
4
|
import { Pushable } from 'it-pushable';
|
|
5
5
|
import { Static } from '@sinclair/typebox';
|
|
6
6
|
import '../types-3e5768ec.js';
|
package/dist/router/index.js
CHANGED
|
@@ -54,7 +54,8 @@ var ControlMessageCloseSchema = import_typebox.Type.Object({
|
|
|
54
54
|
var PROTOCOL_VERSION = "v1";
|
|
55
55
|
var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
|
|
56
56
|
type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
|
|
57
|
-
protocolVersion: import_typebox.Type.Literal(PROTOCOL_VERSION)
|
|
57
|
+
protocolVersion: import_typebox.Type.Literal(PROTOCOL_VERSION),
|
|
58
|
+
instanceId: import_typebox.Type.String()
|
|
58
59
|
});
|
|
59
60
|
var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
|
|
60
61
|
type: import_typebox.Type.Literal("HANDSHAKE_RESP"),
|
|
@@ -78,7 +79,7 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
|
|
|
78
79
|
var OpaqueTransportMessageSchema = TransportMessageSchema(
|
|
79
80
|
import_typebox.Type.Unknown()
|
|
80
81
|
);
|
|
81
|
-
function bootRequestMessage(from, to) {
|
|
82
|
+
function bootRequestMessage(from, to, instanceId) {
|
|
82
83
|
return {
|
|
83
84
|
id: (0, import_nanoid.nanoid)(),
|
|
84
85
|
from,
|
|
@@ -89,7 +90,8 @@ function bootRequestMessage(from, to) {
|
|
|
89
90
|
controlFlags: 0,
|
|
90
91
|
payload: {
|
|
91
92
|
type: "HANDSHAKE_REQ",
|
|
92
|
-
protocolVersion: PROTOCOL_VERSION
|
|
93
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
94
|
+
instanceId
|
|
93
95
|
}
|
|
94
96
|
};
|
|
95
97
|
}
|
|
@@ -135,9 +137,9 @@ var Connection = class {
|
|
|
135
137
|
this.debugId = `conn-${unsafeId()}`;
|
|
136
138
|
}
|
|
137
139
|
};
|
|
138
|
-
var HEARTBEAT_INTERVAL_MS =
|
|
139
|
-
var HEARTBEATS_TILL_DEAD =
|
|
140
|
-
var SESSION_DISCONNECT_GRACE_MS =
|
|
140
|
+
var HEARTBEAT_INTERVAL_MS = 1e3;
|
|
141
|
+
var HEARTBEATS_TILL_DEAD = 2;
|
|
142
|
+
var SESSION_DISCONNECT_GRACE_MS = 5e3;
|
|
141
143
|
var Session = class {
|
|
142
144
|
codec;
|
|
143
145
|
/**
|
|
@@ -220,11 +222,13 @@ var Session = class {
|
|
|
220
222
|
return fullMsg.id;
|
|
221
223
|
}
|
|
222
224
|
sendHeartbeat() {
|
|
223
|
-
if (this.heartbeatMisses >= HEARTBEATS_TILL_DEAD
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
if (this.heartbeatMisses >= HEARTBEATS_TILL_DEAD) {
|
|
226
|
+
if (this.connection) {
|
|
227
|
+
log?.info(
|
|
228
|
+
`${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
|
|
229
|
+
);
|
|
230
|
+
this.halfCloseConnection();
|
|
231
|
+
}
|
|
228
232
|
return;
|
|
229
233
|
}
|
|
230
234
|
this.send(
|
|
@@ -261,7 +265,6 @@ var Session = class {
|
|
|
261
265
|
}
|
|
262
266
|
}
|
|
263
267
|
updateBookkeeping(ack, seq) {
|
|
264
|
-
this.heartbeatMisses = 0;
|
|
265
268
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq > ack);
|
|
266
269
|
this.ack = seq + 1;
|
|
267
270
|
}
|
|
@@ -293,6 +296,7 @@ var Session = class {
|
|
|
293
296
|
}, SESSION_DISCONNECT_GRACE_MS);
|
|
294
297
|
}
|
|
295
298
|
cancelGrace() {
|
|
299
|
+
this.heartbeatMisses = 0;
|
|
296
300
|
clearTimeout(this.disconnectionGrace);
|
|
297
301
|
}
|
|
298
302
|
get connected() {
|
|
@@ -400,6 +404,13 @@ var defaultTransportOptions = {
|
|
|
400
404
|
codec: NaiveJsonCodec
|
|
401
405
|
};
|
|
402
406
|
var Transport = class {
|
|
407
|
+
/**
|
|
408
|
+
* Unique per instance of the transport.
|
|
409
|
+
* This allows us to distinguish reconnects to different
|
|
410
|
+
* transports.
|
|
411
|
+
*/
|
|
412
|
+
instanceId = (0, import_nanoid3.nanoid)();
|
|
413
|
+
connectedInstanceIds = /* @__PURE__ */ new Map();
|
|
403
414
|
/**
|
|
404
415
|
* A flag indicating whether the transport has been destroyed.
|
|
405
416
|
* A destroyed transport will not attempt to reconnect and cannot be used again.
|
|
@@ -461,12 +472,23 @@ var Transport = class {
|
|
|
461
472
|
* and we know the identity of the connected client.
|
|
462
473
|
* @param conn The connection object.
|
|
463
474
|
*/
|
|
464
|
-
onConnect(conn, connectedTo) {
|
|
475
|
+
onConnect(conn, connectedTo, instanceId) {
|
|
465
476
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
466
477
|
status: "connect",
|
|
467
478
|
conn
|
|
468
479
|
});
|
|
469
|
-
|
|
480
|
+
let session = this.sessions.get(connectedTo);
|
|
481
|
+
const lastInstanceId = this.connectedInstanceIds.get(connectedTo);
|
|
482
|
+
if (session && lastInstanceId !== instanceId && lastInstanceId !== void 0) {
|
|
483
|
+
log?.debug(
|
|
484
|
+
`${this.clientId} -- handshake from ${connectedTo} has different server instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
|
|
485
|
+
);
|
|
486
|
+
session.resetBufferedMessages();
|
|
487
|
+
session.closeStaleConnection();
|
|
488
|
+
this.deleteSession(session);
|
|
489
|
+
session = void 0;
|
|
490
|
+
}
|
|
491
|
+
this.connectedInstanceIds.set(connectedTo, instanceId);
|
|
470
492
|
if (session === void 0) {
|
|
471
493
|
const newSession = this.createSession(connectedTo, conn);
|
|
472
494
|
log?.info(
|
|
@@ -532,11 +554,13 @@ var Transport = class {
|
|
|
532
554
|
const parsedMsg = this.codec.fromBuffer(msg);
|
|
533
555
|
if (parsedMsg === null) {
|
|
534
556
|
const decodedBuffer = new TextDecoder().decode(msg);
|
|
535
|
-
log?.
|
|
557
|
+
log?.error(
|
|
558
|
+
`${this.clientId} -- received malformed msg, killing conn: ${decodedBuffer}`
|
|
559
|
+
);
|
|
536
560
|
return null;
|
|
537
561
|
}
|
|
538
562
|
if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
539
|
-
log?.
|
|
563
|
+
log?.error(
|
|
540
564
|
`${this.clientId} -- received invalid msg: ${JSON.stringify(
|
|
541
565
|
parsedMsg
|
|
542
566
|
)}`
|
|
@@ -555,9 +579,6 @@ var Transport = class {
|
|
|
555
579
|
* @param msg The received message.
|
|
556
580
|
*/
|
|
557
581
|
handleMsg(msg) {
|
|
558
|
-
if (!msg) {
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
582
|
const session = this.sessionByClientId(msg.from);
|
|
562
583
|
session.cancelGrace();
|
|
563
584
|
log?.debug(`${this.clientId} -- received msg: ${JSON.stringify(msg)}`);
|
|
@@ -659,7 +680,6 @@ var ClientTransport = class extends Transport {
|
|
|
659
680
|
*/
|
|
660
681
|
inflightConnectionPromises;
|
|
661
682
|
tryReconnecting = true;
|
|
662
|
-
serverInstanceIds = /* @__PURE__ */ new Map();
|
|
663
683
|
constructor(clientId, providedOptions) {
|
|
664
684
|
super(clientId, providedOptions);
|
|
665
685
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
@@ -667,7 +687,14 @@ var ClientTransport = class extends Transport {
|
|
|
667
687
|
handleConnection(conn, to) {
|
|
668
688
|
const bootHandler = this.receiveWithBootSequence(conn, () => {
|
|
669
689
|
conn.removeDataListener(bootHandler);
|
|
670
|
-
conn.addDataListener((data) =>
|
|
690
|
+
conn.addDataListener((data) => {
|
|
691
|
+
const parsed = this.parseMsg(data);
|
|
692
|
+
if (!parsed) {
|
|
693
|
+
conn.close();
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
this.handleMsg(parsed);
|
|
697
|
+
});
|
|
671
698
|
});
|
|
672
699
|
conn.addDataListener(bootHandler);
|
|
673
700
|
conn.addCloseListener(() => {
|
|
@@ -699,7 +726,7 @@ var ClientTransport = class extends Transport {
|
|
|
699
726
|
try {
|
|
700
727
|
const conn = await reconnectPromise;
|
|
701
728
|
this.state = "open";
|
|
702
|
-
const requestMsg = bootRequestMessage(this.clientId, to);
|
|
729
|
+
const requestMsg = bootRequestMessage(this.clientId, to, this.instanceId);
|
|
703
730
|
log?.debug(`${this.clientId} -- sending boot handshake to ${to}`);
|
|
704
731
|
conn.send(this.codec.toBuffer(requestMsg));
|
|
705
732
|
} catch (error) {
|
|
@@ -722,8 +749,10 @@ var ClientTransport = class extends Transport {
|
|
|
722
749
|
receiveWithBootSequence(conn, sessionCb) {
|
|
723
750
|
const bootHandler = (data) => {
|
|
724
751
|
const parsed = this.parseMsg(data);
|
|
725
|
-
if (!parsed)
|
|
752
|
+
if (!parsed) {
|
|
753
|
+
conn.close();
|
|
726
754
|
return;
|
|
755
|
+
}
|
|
727
756
|
if (!import_value.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
728
757
|
log?.warn(
|
|
729
758
|
`${this.clientId} -- received invalid handshake resp: ${JSON.stringify(parsed)}`
|
|
@@ -738,22 +767,11 @@ var ClientTransport = class extends Transport {
|
|
|
738
767
|
);
|
|
739
768
|
return;
|
|
740
769
|
}
|
|
741
|
-
const oldSession = this.sessions.get(parsed.from);
|
|
742
770
|
const serverInstanceId = parsed.payload.status.instanceId;
|
|
743
|
-
const lastServerInstanceId = this.serverInstanceIds.get(parsed.from);
|
|
744
|
-
if (oldSession && lastServerInstanceId !== serverInstanceId && lastServerInstanceId !== void 0) {
|
|
745
|
-
log?.debug(
|
|
746
|
-
`${this.clientId} -- handshake from ${parsed.from} has different server instance (got: ${serverInstanceId}, last connected to: ${lastServerInstanceId}), starting a new session`
|
|
747
|
-
);
|
|
748
|
-
oldSession.resetBufferedMessages();
|
|
749
|
-
oldSession.closeStaleConnection();
|
|
750
|
-
this.deleteSession(oldSession);
|
|
751
|
-
}
|
|
752
771
|
log?.debug(
|
|
753
772
|
`${this.clientId} -- handshake from ${parsed.from} ok (server instance: ${serverInstanceId})`
|
|
754
773
|
);
|
|
755
|
-
this.
|
|
756
|
-
sessionCb(this.onConnect(conn, parsed.from));
|
|
774
|
+
sessionCb(this.onConnect(conn, parsed.from, serverInstanceId));
|
|
757
775
|
};
|
|
758
776
|
return bootHandler;
|
|
759
777
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ClientTransport, b as TransportClientId, c as TransportOptions } from '../../../index-
|
|
2
|
-
import { S as StreamConnection } from '../../../connection-
|
|
1
|
+
import { a as ClientTransport, b as TransportClientId, c as TransportOptions } from '../../../index-0c0a69f6.js';
|
|
2
|
+
import { S as StreamConnection } from '../../../connection-bf7811aa.js';
|
|
3
3
|
import '../../../types-3e5768ec.js';
|
|
4
4
|
import '@sinclair/typebox';
|
|
5
5
|
import '../../../messageFraming-b200ef25.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ClientTransport, b as TransportClientId, c as TransportOptions } from '../../../index-
|
|
2
|
-
import { S as StreamConnection } from '../../../connection-
|
|
1
|
+
import { a as ClientTransport, b as TransportClientId, c as TransportOptions } from '../../../index-0c0a69f6.js';
|
|
2
|
+
import { S as StreamConnection } from '../../../connection-bf7811aa.js';
|
|
3
3
|
import '../../../types-3e5768ec.js';
|
|
4
4
|
import '@sinclair/typebox';
|
|
5
5
|
import '../../../messageFraming-b200ef25.js';
|