@replit/river 0.12.5 → 0.13.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 +4 -1
- package/dist/{builder-c593de11.d.ts → builder-169fbf7f.d.ts} +16 -7
- package/dist/{chunk-AFLZ6INU.js → chunk-CBRQM65K.js} +29 -10
- package/dist/{chunk-IIBVKYDB.js → chunk-CDH7QSB4.js} +39 -1
- package/dist/{chunk-XFFS4UOD.js → chunk-MGGIUH5O.js} +7 -7
- package/dist/{chunk-6OAKPO5R.js → chunk-NPXAAD7M.js} +1 -1
- package/dist/{chunk-2PKONGC3.js → chunk-R2IMXRVU.js} +160 -135
- package/dist/{connection-4a839b9a.d.ts → connection-ab681c08.d.ts} +1 -1
- package/dist/{messageFraming-b200ef25.d.ts → connection-dd789651.d.ts} +17 -2
- package/dist/{index-1afc5580.d.ts → index-21c1b21d.d.ts} +32 -18
- package/dist/router/index.cjs +31 -13
- package/dist/router/index.d.cts +5 -5
- package/dist/router/index.d.ts +5 -5
- package/dist/router/index.js +2 -2
- package/dist/transport/impls/uds/client.cjs +153 -140
- package/dist/transport/impls/uds/client.d.cts +2 -3
- package/dist/transport/impls/uds/client.d.ts +2 -3
- package/dist/transport/impls/uds/client.js +5 -6
- package/dist/transport/impls/uds/server.cjs +161 -146
- package/dist/transport/impls/uds/server.d.cts +2 -3
- package/dist/transport/impls/uds/server.d.ts +2 -3
- package/dist/transport/impls/uds/server.js +4 -5
- package/dist/transport/impls/ws/client.cjs +157 -142
- package/dist/transport/impls/ws/client.d.cts +4 -4
- package/dist/transport/impls/ws/client.d.ts +4 -4
- package/dist/transport/impls/ws/client.js +7 -7
- package/dist/transport/impls/ws/server.cjs +161 -146
- 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 +4 -4
- package/dist/transport/index.cjs +212 -186
- package/dist/transport/index.d.cts +1 -1
- package/dist/transport/index.d.ts +1 -1
- package/dist/transport/index.js +3 -3
- package/dist/util/testHelpers.cjs +294 -16
- package/dist/util/testHelpers.d.cts +2 -2
- package/dist/util/testHelpers.d.ts +2 -2
- package/dist/util/testHelpers.js +30 -8
- package/package.json +1 -9
- package/dist/chunk-7J66WOIC.js +0 -44
- package/dist/chunk-H4QR2K3T.js +0 -47
- package/dist/connection-64b9e0ff.d.ts +0 -17
- package/dist/connection-a6cc48e8.d.ts +0 -18
- package/dist/transport/impls/stdio/client.cjs +0 -913
- package/dist/transport/impls/stdio/client.d.cts +0 -27
- package/dist/transport/impls/stdio/client.d.ts +0 -27
- package/dist/transport/impls/stdio/client.js +0 -42
- package/dist/transport/impls/stdio/server.cjs +0 -888
- package/dist/transport/impls/stdio/server.d.cts +0 -25
- package/dist/transport/impls/stdio/server.d.ts +0 -25
- package/dist/transport/impls/stdio/server.js +0 -33
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NaiveJsonCodec
|
|
3
|
-
} from "./chunk-GZ7HCLLM.js";
|
|
4
1
|
import {
|
|
5
2
|
ControlMessageHandshakeRequestSchema,
|
|
6
3
|
ControlMessageHandshakeResponseSchema,
|
|
7
4
|
OpaqueTransportMessageSchema,
|
|
8
5
|
PROTOCOL_VERSION,
|
|
9
|
-
bootRequestMessage,
|
|
10
|
-
bootResponseMessage,
|
|
11
6
|
coerceErrorString,
|
|
7
|
+
handshakeRequestMessage,
|
|
8
|
+
handshakeResponseMessage,
|
|
12
9
|
isAck
|
|
13
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-MGGIUH5O.js";
|
|
14
11
|
import {
|
|
15
12
|
log
|
|
16
13
|
} from "./chunk-H4BYJELI.js";
|
|
14
|
+
import {
|
|
15
|
+
NaiveJsonCodec
|
|
16
|
+
} from "./chunk-GZ7HCLLM.js";
|
|
17
17
|
|
|
18
18
|
// transport/events.ts
|
|
19
19
|
var EventDispatcher = class {
|
|
@@ -56,8 +56,15 @@ var Connection = class {
|
|
|
56
56
|
var HEARTBEAT_INTERVAL_MS = 1e3;
|
|
57
57
|
var HEARTBEATS_TILL_DEAD = 2;
|
|
58
58
|
var SESSION_DISCONNECT_GRACE_MS = 5e3;
|
|
59
|
+
var defaultSessionOptions = {
|
|
60
|
+
heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
|
|
61
|
+
heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
|
|
62
|
+
sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
|
|
63
|
+
codec: NaiveJsonCodec
|
|
64
|
+
};
|
|
59
65
|
var Session = class {
|
|
60
66
|
codec;
|
|
67
|
+
options;
|
|
61
68
|
/**
|
|
62
69
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
63
70
|
*/
|
|
@@ -93,16 +100,17 @@ var Session = class {
|
|
|
93
100
|
* The interval for sending heartbeats.
|
|
94
101
|
*/
|
|
95
102
|
heartbeat;
|
|
96
|
-
constructor(
|
|
103
|
+
constructor(from, connectedTo, conn, options) {
|
|
104
|
+
this.options = options;
|
|
97
105
|
this.debugId = `sess-${unsafeId()}`;
|
|
98
106
|
this.from = from;
|
|
99
107
|
this.to = connectedTo;
|
|
100
108
|
this.connection = conn;
|
|
101
|
-
this.codec = codec;
|
|
109
|
+
this.codec = options.codec;
|
|
102
110
|
this.heartbeatMisses = 0;
|
|
103
111
|
this.heartbeat = setInterval(
|
|
104
112
|
() => this.sendHeartbeat(),
|
|
105
|
-
|
|
113
|
+
options.heartbeatIntervalMs
|
|
106
114
|
);
|
|
107
115
|
}
|
|
108
116
|
/**
|
|
@@ -138,7 +146,7 @@ var Session = class {
|
|
|
138
146
|
return fullMsg.id;
|
|
139
147
|
}
|
|
140
148
|
sendHeartbeat() {
|
|
141
|
-
if (this.heartbeatMisses >=
|
|
149
|
+
if (this.heartbeatMisses >= this.options.heartbeatsUntilDead) {
|
|
142
150
|
if (this.connection) {
|
|
143
151
|
log?.info(
|
|
144
152
|
`${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
|
|
@@ -204,13 +212,11 @@ var Session = class {
|
|
|
204
212
|
this.cancelGrace();
|
|
205
213
|
this.connection = newConn;
|
|
206
214
|
}
|
|
207
|
-
graceCb;
|
|
208
215
|
beginGrace(cb) {
|
|
209
|
-
this.graceCb = cb;
|
|
210
216
|
this.disconnectionGrace = setTimeout(() => {
|
|
211
217
|
this.close();
|
|
212
218
|
cb();
|
|
213
|
-
},
|
|
219
|
+
}, this.options.sessionDisconnectGraceMs);
|
|
214
220
|
}
|
|
215
221
|
// called on reconnect of the underlying session
|
|
216
222
|
cancelGrace() {
|
|
@@ -222,8 +228,8 @@ var Session = class {
|
|
|
222
228
|
close() {
|
|
223
229
|
this.closeStaleConnection(this.connection);
|
|
224
230
|
this.cancelGrace();
|
|
225
|
-
clearInterval(this.heartbeat);
|
|
226
231
|
this.resetBufferedMessages();
|
|
232
|
+
clearInterval(this.heartbeat);
|
|
227
233
|
}
|
|
228
234
|
get connected() {
|
|
229
235
|
return this.connection !== void 0;
|
|
@@ -251,13 +257,13 @@ var Session = class {
|
|
|
251
257
|
// transport/transport.ts
|
|
252
258
|
import { Value } from "@sinclair/typebox/value";
|
|
253
259
|
import { nanoid as nanoid2 } from "nanoid";
|
|
254
|
-
var
|
|
255
|
-
var
|
|
260
|
+
var RECONNECT_JITTER_MAX_MS = 500;
|
|
261
|
+
var RECONNECT_INTERVAL_MS = 250;
|
|
256
262
|
var defaultTransportOptions = {
|
|
257
|
-
retryIntervalMs:
|
|
258
|
-
retryJitterMs:
|
|
263
|
+
retryIntervalMs: RECONNECT_INTERVAL_MS,
|
|
264
|
+
retryJitterMs: RECONNECT_JITTER_MAX_MS,
|
|
259
265
|
retryAttemptsMax: 5,
|
|
260
|
-
|
|
266
|
+
...defaultSessionOptions
|
|
261
267
|
};
|
|
262
268
|
var Transport = class {
|
|
263
269
|
/**
|
|
@@ -314,15 +320,6 @@ var Transport = class {
|
|
|
314
320
|
this.clientId = clientId;
|
|
315
321
|
this.state = "open";
|
|
316
322
|
}
|
|
317
|
-
sessionByClientId(clientId) {
|
|
318
|
-
const session = this.sessions.get(clientId);
|
|
319
|
-
if (!session) {
|
|
320
|
-
const err = `${this.clientId} -- (invariant violation) no existing session for ${clientId}`;
|
|
321
|
-
log?.error(err);
|
|
322
|
-
throw new Error(err);
|
|
323
|
-
}
|
|
324
|
-
return session;
|
|
325
|
-
}
|
|
326
323
|
/**
|
|
327
324
|
* Called when a new connection is established
|
|
328
325
|
* and we know the identity of the connected client.
|
|
@@ -337,7 +334,7 @@ var Transport = class {
|
|
|
337
334
|
const lastInstanceId = this.connectedInstanceIds.get(connectedTo);
|
|
338
335
|
if (oldSession && lastInstanceId !== void 0 && lastInstanceId !== instanceId) {
|
|
339
336
|
log?.warn(
|
|
340
|
-
`${this.clientId} --
|
|
337
|
+
`${this.clientId} -- connection from ${connectedTo} is a different instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
|
|
341
338
|
);
|
|
342
339
|
oldSession.close();
|
|
343
340
|
this.deleteSession(oldSession);
|
|
@@ -360,10 +357,10 @@ var Transport = class {
|
|
|
360
357
|
}
|
|
361
358
|
createSession(connectedTo, conn) {
|
|
362
359
|
const session = new Session(
|
|
363
|
-
this.codec,
|
|
364
360
|
this.clientId,
|
|
365
361
|
connectedTo,
|
|
366
|
-
conn
|
|
362
|
+
conn,
|
|
363
|
+
this.options
|
|
367
364
|
);
|
|
368
365
|
this.sessions.set(session.to, session);
|
|
369
366
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -392,13 +389,10 @@ var Transport = class {
|
|
|
392
389
|
status: "disconnect",
|
|
393
390
|
conn
|
|
394
391
|
});
|
|
395
|
-
|
|
392
|
+
const session = this.sessions.get(connectedTo);
|
|
393
|
+
if (!session)
|
|
396
394
|
return;
|
|
397
|
-
|
|
398
|
-
log?.info(
|
|
399
|
-
`${this.clientId} -- connection (id: ${conn.debugId}) disconnect from ${connectedTo}, ${SESSION_DISCONNECT_GRACE_MS}ms until session (id: ${session.debugId}) disconnect`
|
|
400
|
-
);
|
|
401
|
-
session.closeStaleConnection(conn);
|
|
395
|
+
session.connection = void 0;
|
|
402
396
|
session.beginGrace(() => this.deleteSession(session));
|
|
403
397
|
}
|
|
404
398
|
/**
|
|
@@ -409,7 +403,7 @@ var Transport = class {
|
|
|
409
403
|
parseMsg(msg) {
|
|
410
404
|
const parsedMsg = this.codec.fromBuffer(msg);
|
|
411
405
|
if (parsedMsg === null) {
|
|
412
|
-
const decodedBuffer = new TextDecoder().decode(msg);
|
|
406
|
+
const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));
|
|
413
407
|
log?.error(
|
|
414
408
|
`${this.clientId} -- received malformed msg, killing conn: ${decodedBuffer}`
|
|
415
409
|
);
|
|
@@ -423,11 +417,7 @@ var Transport = class {
|
|
|
423
417
|
);
|
|
424
418
|
return null;
|
|
425
419
|
}
|
|
426
|
-
return
|
|
427
|
-
...parsedMsg,
|
|
428
|
-
serviceName: parsedMsg.serviceName === null ? void 0 : parsedMsg.serviceName,
|
|
429
|
-
procedureName: parsedMsg.procedureName === null ? void 0 : parsedMsg.procedureName
|
|
430
|
-
};
|
|
420
|
+
return parsedMsg;
|
|
431
421
|
}
|
|
432
422
|
/**
|
|
433
423
|
* Called when a message is received by this transport.
|
|
@@ -437,15 +427,27 @@ var Transport = class {
|
|
|
437
427
|
handleMsg(msg) {
|
|
438
428
|
if (this.state !== "open")
|
|
439
429
|
return;
|
|
440
|
-
const session = this.
|
|
430
|
+
const session = this.sessions.get(msg.from);
|
|
431
|
+
if (!session) {
|
|
432
|
+
const err = `${this.clientId} -- (invariant violation) no existing session for ${msg.from}`;
|
|
433
|
+
log?.error(err);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
441
436
|
session.cancelGrace();
|
|
442
437
|
log?.debug(`${this.clientId} -- received msg: ${JSON.stringify(msg)}`);
|
|
443
438
|
if (msg.seq !== session.nextExpectedSeq) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
msg
|
|
447
|
-
|
|
448
|
-
|
|
439
|
+
if (msg.seq < session.nextExpectedSeq) {
|
|
440
|
+
log?.debug(
|
|
441
|
+
`${this.clientId} -- received duplicate msg (got: ${msg.seq}, wanted: ${session.nextExpectedSeq}), discarding: ${JSON.stringify(
|
|
442
|
+
msg
|
|
443
|
+
)}`
|
|
444
|
+
);
|
|
445
|
+
} else {
|
|
446
|
+
log?.error(
|
|
447
|
+
`${this.clientId} -- received out-of-order msg (got: ${msg.seq}, wanted: ${session.nextExpectedSeq}), marking connection as dead: ${JSON.stringify(msg)}`
|
|
448
|
+
);
|
|
449
|
+
session.closeStaleConnection(session.connection);
|
|
450
|
+
}
|
|
449
451
|
return;
|
|
450
452
|
}
|
|
451
453
|
if (!isAck(msg.controlFlags)) {
|
|
@@ -463,7 +465,7 @@ var Transport = class {
|
|
|
463
465
|
}
|
|
464
466
|
/**
|
|
465
467
|
* Removes a listener from this transport.
|
|
466
|
-
* @param the type of event to
|
|
468
|
+
* @param the type of event to un-listen on
|
|
467
469
|
* @param handler The message handler to remove.
|
|
468
470
|
*/
|
|
469
471
|
removeEventListener(type, handler) {
|
|
@@ -540,23 +542,31 @@ var ClientTransport = class extends Transport {
|
|
|
540
542
|
*/
|
|
541
543
|
inflightConnectionPromises;
|
|
542
544
|
tryReconnecting = true;
|
|
543
|
-
|
|
545
|
+
connectedTo;
|
|
546
|
+
constructor(clientId, connectedTo, providedOptions) {
|
|
544
547
|
super(clientId, providedOptions);
|
|
548
|
+
this.connectedTo = connectedTo;
|
|
545
549
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
546
550
|
}
|
|
547
551
|
handleConnection(conn, to) {
|
|
548
|
-
const
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
+
const handshakeHandler = (data) => {
|
|
553
|
+
const handshake = this.receiveHandshakeResponseMessage(data);
|
|
554
|
+
if (!handshake) {
|
|
555
|
+
conn.close();
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
this.onConnect(conn, handshake.from, handshake.instanceId);
|
|
559
|
+
conn.removeDataListener(handshakeHandler);
|
|
560
|
+
conn.addDataListener((data2) => {
|
|
561
|
+
const parsed = this.parseMsg(data2);
|
|
552
562
|
if (!parsed) {
|
|
553
563
|
conn.close();
|
|
554
564
|
return;
|
|
555
565
|
}
|
|
556
566
|
this.handleMsg(parsed);
|
|
557
567
|
});
|
|
558
|
-
}
|
|
559
|
-
conn.addDataListener(
|
|
568
|
+
};
|
|
569
|
+
conn.addDataListener(handshakeHandler);
|
|
560
570
|
conn.addCloseListener(() => {
|
|
561
571
|
this.onDisconnect(conn, to);
|
|
562
572
|
void this.connect(to);
|
|
@@ -567,6 +577,32 @@ var ClientTransport = class extends Transport {
|
|
|
567
577
|
);
|
|
568
578
|
});
|
|
569
579
|
}
|
|
580
|
+
receiveHandshakeResponseMessage(data) {
|
|
581
|
+
const parsed = this.parseMsg(data);
|
|
582
|
+
if (!parsed)
|
|
583
|
+
return false;
|
|
584
|
+
if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
585
|
+
log?.warn(
|
|
586
|
+
`${this.clientId} -- received invalid handshake resp: ${JSON.stringify(
|
|
587
|
+
parsed
|
|
588
|
+
)}`
|
|
589
|
+
);
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
if (!parsed.payload.status.ok) {
|
|
593
|
+
log?.warn(
|
|
594
|
+
`${this.clientId} -- received failed handshake resp: ${JSON.stringify(
|
|
595
|
+
parsed
|
|
596
|
+
)}`
|
|
597
|
+
);
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
const instanceId = parsed.payload.status.instanceId;
|
|
601
|
+
log?.debug(
|
|
602
|
+
`${this.clientId} -- handshake from ${parsed.from} ok (instance: ${instanceId})`
|
|
603
|
+
);
|
|
604
|
+
return { instanceId, from: parsed.from };
|
|
605
|
+
}
|
|
570
606
|
/**
|
|
571
607
|
* Manually attempts to connect to a client.
|
|
572
608
|
* @param to The client ID of the node to connect to.
|
|
@@ -585,10 +621,7 @@ var ClientTransport = class extends Transport {
|
|
|
585
621
|
}
|
|
586
622
|
try {
|
|
587
623
|
const conn = await reconnectPromise;
|
|
588
|
-
this.
|
|
589
|
-
const requestMsg = bootRequestMessage(this.clientId, to, this.instanceId);
|
|
590
|
-
log?.debug(`${this.clientId} -- sending boot handshake to ${to}`);
|
|
591
|
-
conn.send(this.codec.toBuffer(requestMsg));
|
|
624
|
+
this.sendHandshake(to, conn);
|
|
592
625
|
} catch (error) {
|
|
593
626
|
const errStr = coerceErrorString(error);
|
|
594
627
|
this.inflightConnectionPromises.delete(to);
|
|
@@ -606,34 +639,14 @@ var ClientTransport = class extends Transport {
|
|
|
606
639
|
}
|
|
607
640
|
}
|
|
608
641
|
}
|
|
609
|
-
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
log?.warn(
|
|
618
|
-
`${this.clientId} -- received invalid handshake resp: ${JSON.stringify(parsed)}`
|
|
619
|
-
);
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
if (!parsed.payload.status.ok) {
|
|
623
|
-
log?.warn(
|
|
624
|
-
`${this.clientId} -- received failed handshake resp: ${JSON.stringify(
|
|
625
|
-
parsed
|
|
626
|
-
)}`
|
|
627
|
-
);
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
const serverInstanceId = parsed.payload.status.instanceId;
|
|
631
|
-
log?.debug(
|
|
632
|
-
`${this.clientId} -- handshake from ${parsed.from} ok (server instance: ${serverInstanceId})`
|
|
633
|
-
);
|
|
634
|
-
sessionCb(this.onConnect(conn, parsed.from, serverInstanceId));
|
|
635
|
-
};
|
|
636
|
-
return bootHandler;
|
|
642
|
+
sendHandshake(to, conn) {
|
|
643
|
+
const requestMsg = handshakeRequestMessage(
|
|
644
|
+
this.clientId,
|
|
645
|
+
to,
|
|
646
|
+
this.instanceId
|
|
647
|
+
);
|
|
648
|
+
log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
|
|
649
|
+
conn.send(this.codec.toBuffer(requestMsg));
|
|
637
650
|
}
|
|
638
651
|
onDisconnect(conn, connectedTo) {
|
|
639
652
|
this.inflightConnectionPromises.delete(connectedTo);
|
|
@@ -650,22 +663,24 @@ var ServerTransport = class extends Transport {
|
|
|
650
663
|
handleConnection(conn) {
|
|
651
664
|
let session = void 0;
|
|
652
665
|
const client = () => session?.to ?? "unknown";
|
|
653
|
-
const
|
|
654
|
-
conn
|
|
655
|
-
(
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
conn.addDataListener((data) => {
|
|
659
|
-
const parsed = this.parseMsg(data);
|
|
660
|
-
if (!parsed) {
|
|
661
|
-
conn.close();
|
|
662
|
-
return;
|
|
663
|
-
}
|
|
664
|
-
this.handleMsg(parsed);
|
|
665
|
-
});
|
|
666
|
+
const handshakeHandler = (data) => {
|
|
667
|
+
const handshake = this.receiveHandshakeRequestMessage(data, conn);
|
|
668
|
+
if (!handshake) {
|
|
669
|
+
conn.close();
|
|
670
|
+
return;
|
|
666
671
|
}
|
|
667
|
-
|
|
668
|
-
|
|
672
|
+
session = this.onConnect(conn, handshake.from, handshake.instanceId);
|
|
673
|
+
conn.removeDataListener(handshakeHandler);
|
|
674
|
+
conn.addDataListener((data2) => {
|
|
675
|
+
const parsed = this.parseMsg(data2);
|
|
676
|
+
if (!parsed) {
|
|
677
|
+
conn.close();
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
this.handleMsg(parsed);
|
|
681
|
+
});
|
|
682
|
+
};
|
|
683
|
+
conn.addDataListener(handshakeHandler);
|
|
669
684
|
conn.addCloseListener(() => {
|
|
670
685
|
if (!session)
|
|
671
686
|
return;
|
|
@@ -682,47 +697,57 @@ var ServerTransport = class extends Transport {
|
|
|
682
697
|
);
|
|
683
698
|
});
|
|
684
699
|
}
|
|
685
|
-
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
this.instanceId,
|
|
696
|
-
parsed.from,
|
|
697
|
-
false
|
|
698
|
-
);
|
|
699
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
700
|
-
log?.warn(
|
|
701
|
-
`${this.clientId} -- received invalid handshake msg: ${JSON.stringify(
|
|
702
|
-
parsed
|
|
703
|
-
)}`
|
|
704
|
-
);
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
const instanceId = parsed.payload.instanceId;
|
|
708
|
-
log?.debug(
|
|
709
|
-
`${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
|
|
700
|
+
receiveHandshakeRequestMessage(data, conn) {
|
|
701
|
+
const parsed = this.parseMsg(data);
|
|
702
|
+
if (!parsed)
|
|
703
|
+
return false;
|
|
704
|
+
if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
|
|
705
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
706
|
+
this.clientId,
|
|
707
|
+
this.instanceId,
|
|
708
|
+
parsed.from,
|
|
709
|
+
false
|
|
710
710
|
);
|
|
711
|
-
|
|
711
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
712
|
+
log?.warn(
|
|
713
|
+
`${this.clientId} -- received invalid handshake msg: ${JSON.stringify(
|
|
714
|
+
parsed
|
|
715
|
+
)}`
|
|
716
|
+
);
|
|
717
|
+
return false;
|
|
718
|
+
}
|
|
719
|
+
const gotVersion = parsed.payload.protocolVersion;
|
|
720
|
+
if (gotVersion !== PROTOCOL_VERSION) {
|
|
721
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
712
722
|
this.clientId,
|
|
713
723
|
this.instanceId,
|
|
714
724
|
parsed.from,
|
|
715
|
-
|
|
725
|
+
false
|
|
716
726
|
);
|
|
717
|
-
conn.send(this.codec.toBuffer(
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
727
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
728
|
+
log?.warn(
|
|
729
|
+
`${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
|
|
730
|
+
);
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
const instanceId = parsed.payload.instanceId;
|
|
734
|
+
log?.debug(
|
|
735
|
+
`${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
|
|
736
|
+
);
|
|
737
|
+
const responseMsg = handshakeResponseMessage(
|
|
738
|
+
this.clientId,
|
|
739
|
+
this.instanceId,
|
|
740
|
+
parsed.from,
|
|
741
|
+
true
|
|
742
|
+
);
|
|
743
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
744
|
+
return { instanceId, from: parsed.from };
|
|
721
745
|
}
|
|
722
746
|
};
|
|
723
747
|
|
|
724
748
|
export {
|
|
725
749
|
Connection,
|
|
750
|
+
defaultSessionOptions,
|
|
726
751
|
Session,
|
|
727
752
|
Transport,
|
|
728
753
|
ClientTransport,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as Connection } from './index-21c1b21d.js';
|
|
2
|
+
import { Socket } from 'node:net';
|
|
3
|
+
import stream, { Transform, TransformCallback, TransformOptions } from 'node:stream';
|
|
2
4
|
|
|
3
5
|
interface LengthEncodedOptions extends TransformOptions {
|
|
4
6
|
/** Maximum in-memory buffer size before we throw */
|
|
@@ -17,4 +19,17 @@ declare class Uint32LengthPrefixFraming extends Transform {
|
|
|
17
19
|
_destroy(error: Error | null, callback: (error: Error | null) => void): void;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
declare class UdsConnection extends Connection {
|
|
23
|
+
sock: Socket;
|
|
24
|
+
input: stream.Readable;
|
|
25
|
+
framer: Uint32LengthPrefixFraming;
|
|
26
|
+
constructor(sock: Socket);
|
|
27
|
+
addDataListener(cb: (msg: Uint8Array) => void): void;
|
|
28
|
+
removeDataListener(cb: (msg: Uint8Array) => void): void;
|
|
29
|
+
addCloseListener(cb: () => void): void;
|
|
30
|
+
addErrorListener(cb: (err: Error) => void): void;
|
|
31
|
+
send(payload: Uint8Array): boolean;
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { UdsConnection as U };
|
|
@@ -14,8 +14,8 @@ declare const TransportMessageSchema: <T extends TSchema>(t: T) => _sinclair_typ
|
|
|
14
14
|
to: _sinclair_typebox.TString;
|
|
15
15
|
seq: _sinclair_typebox.TInteger;
|
|
16
16
|
ack: _sinclair_typebox.TInteger;
|
|
17
|
-
serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.
|
|
18
|
-
procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.
|
|
17
|
+
serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
18
|
+
procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
19
19
|
streamId: _sinclair_typebox.TString;
|
|
20
20
|
controlFlags: _sinclair_typebox.TInteger;
|
|
21
21
|
payload: T;
|
|
@@ -31,8 +31,8 @@ declare const OpaqueTransportMessageSchema: _sinclair_typebox.TObject<{
|
|
|
31
31
|
to: _sinclair_typebox.TString;
|
|
32
32
|
seq: _sinclair_typebox.TInteger;
|
|
33
33
|
ack: _sinclair_typebox.TInteger;
|
|
34
|
-
serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.
|
|
35
|
-
procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.
|
|
34
|
+
serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
35
|
+
procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
36
36
|
streamId: _sinclair_typebox.TString;
|
|
37
37
|
controlFlags: _sinclair_typebox.TInteger;
|
|
38
38
|
payload: _sinclair_typebox.TUnknown;
|
|
@@ -48,6 +48,8 @@ declare const OpaqueTransportMessageSchema: _sinclair_typebox.TObject<{
|
|
|
48
48
|
* * If `controlFlags & StreamOpenBit == StreamOpenBit`, `serviceName` and `procedureName` must be set.
|
|
49
49
|
* * If `controlFlags & StreamClosedBit == StreamClosedBit` and the kind is `stream` or `subscription`,
|
|
50
50
|
* `payload` should be discarded (usually contains a control message).
|
|
51
|
+
* * If `controlFlags & AckBit == AckBit`, the message is an explicit acknowledgement message and doesn't
|
|
52
|
+
* contain any payload that is relevant to the application so should not be delivered.
|
|
51
53
|
* @template Payload The type of the payload.
|
|
52
54
|
*/
|
|
53
55
|
interface TransportMessage<Payload = Record<string, unknown>> {
|
|
@@ -126,6 +128,12 @@ declare abstract class Connection {
|
|
|
126
128
|
*/
|
|
127
129
|
abstract close(): void;
|
|
128
130
|
}
|
|
131
|
+
interface SessionOptions {
|
|
132
|
+
heartbeatIntervalMs: number;
|
|
133
|
+
heartbeatsUntilDead: number;
|
|
134
|
+
sessionDisconnectGraceMs: number;
|
|
135
|
+
codec: Codec;
|
|
136
|
+
}
|
|
129
137
|
/**
|
|
130
138
|
* A session is a higher-level abstraction that operates over the span of potentially multiple transport-level connections
|
|
131
139
|
* - It’s responsible for tracking any metadata for a particular client that might need to be persisted across connections (i.e. the sendBuffer, ack, seq)
|
|
@@ -161,6 +169,7 @@ declare abstract class Connection {
|
|
|
161
169
|
*/
|
|
162
170
|
declare class Session<ConnType extends Connection> {
|
|
163
171
|
private codec;
|
|
172
|
+
private options;
|
|
164
173
|
/**
|
|
165
174
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
166
175
|
*/
|
|
@@ -196,7 +205,7 @@ declare class Session<ConnType extends Connection> {
|
|
|
196
205
|
* The interval for sending heartbeats.
|
|
197
206
|
*/
|
|
198
207
|
private heartbeat?;
|
|
199
|
-
constructor(
|
|
208
|
+
constructor(from: TransportClientId, connectedTo: TransportClientId, conn: ConnType | undefined, options: SessionOptions);
|
|
200
209
|
/**
|
|
201
210
|
* Sends a message over the session's connection.
|
|
202
211
|
* If the connection is not ready or the message fails to send, the message can be buffered for retry unless skipped.
|
|
@@ -214,7 +223,6 @@ declare class Session<ConnType extends Connection> {
|
|
|
214
223
|
addToSendBuff(msg: TransportMessage): void;
|
|
215
224
|
closeStaleConnection(conn?: ConnType): void;
|
|
216
225
|
replaceWithNewConnection(newConn: ConnType): void;
|
|
217
|
-
graceCb?: () => unknown;
|
|
218
226
|
beginGrace(cb: () => void): void;
|
|
219
227
|
cancelGrace(): void;
|
|
220
228
|
close(): void;
|
|
@@ -253,12 +261,11 @@ declare class EventDispatcher<T extends EventTypes> {
|
|
|
253
261
|
* @property {'destroyed'} destroyed - The transport is permanently destroyed and cannot be reopened.
|
|
254
262
|
*/
|
|
255
263
|
type TransportStatus = 'open' | 'closed' | 'destroyed';
|
|
256
|
-
|
|
264
|
+
type TransportOptions = {
|
|
257
265
|
retryIntervalMs: number;
|
|
258
266
|
retryJitterMs: number;
|
|
259
267
|
retryAttemptsMax: number;
|
|
260
|
-
|
|
261
|
-
}
|
|
268
|
+
} & SessionOptions;
|
|
262
269
|
/**
|
|
263
270
|
* Transports manage the lifecycle (creation/deletion) of sessions and connections. Its responsibilities include:
|
|
264
271
|
*
|
|
@@ -325,7 +332,7 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
325
332
|
/**
|
|
326
333
|
* The options for this transport.
|
|
327
334
|
*/
|
|
328
|
-
options: TransportOptions;
|
|
335
|
+
protected options: TransportOptions;
|
|
329
336
|
/**
|
|
330
337
|
* Creates a new Transport instance.
|
|
331
338
|
* This should also set up {@link onConnect}, and {@link onDisconnect} listeners.
|
|
@@ -333,7 +340,6 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
333
340
|
* @param clientId The client ID of this transport.
|
|
334
341
|
*/
|
|
335
342
|
constructor(clientId: TransportClientId, providedOptions?: Partial<TransportOptions>);
|
|
336
|
-
private sessionByClientId;
|
|
337
343
|
/**
|
|
338
344
|
* This is called immediately after a new connection is established and we
|
|
339
345
|
* may or may not know the identity of the connected client.
|
|
@@ -356,7 +362,7 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
356
362
|
* @param conn The connection object.
|
|
357
363
|
* @param connectedTo The peer we are connected to.
|
|
358
364
|
*/
|
|
359
|
-
onDisconnect(conn: ConnType, connectedTo: TransportClientId): void;
|
|
365
|
+
protected onDisconnect(conn: ConnType, connectedTo: TransportClientId): void;
|
|
360
366
|
/**
|
|
361
367
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
362
368
|
* @param msg The message to parse.
|
|
@@ -368,7 +374,7 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
368
374
|
* You generally shouldn't need to override this in downstream transport implementations.
|
|
369
375
|
* @param msg The received message.
|
|
370
376
|
*/
|
|
371
|
-
handleMsg(msg: OpaqueTransportMessage): void;
|
|
377
|
+
protected handleMsg(msg: OpaqueTransportMessage): void;
|
|
372
378
|
/**
|
|
373
379
|
* Adds a listener to this transport.
|
|
374
380
|
* @param the type of event to listen for
|
|
@@ -377,7 +383,7 @@ declare abstract class Transport<ConnType extends Connection> {
|
|
|
377
383
|
addEventListener<K extends EventTypes, T extends EventHandler<K>>(type: K, handler: T): void;
|
|
378
384
|
/**
|
|
379
385
|
* Removes a listener from this transport.
|
|
380
|
-
* @param the type of event to
|
|
386
|
+
* @param the type of event to un-listen on
|
|
381
387
|
* @param handler The message handler to remove.
|
|
382
388
|
*/
|
|
383
389
|
removeEventListener<K extends EventTypes, T extends EventHandler<K>>(type: K, handler: T): void;
|
|
@@ -408,8 +414,13 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
408
414
|
*/
|
|
409
415
|
inflightConnectionPromises: Map<TransportClientId, Promise<ConnType>>;
|
|
410
416
|
tryReconnecting: boolean;
|
|
411
|
-
|
|
417
|
+
connectedTo: TransportClientId;
|
|
418
|
+
constructor(clientId: TransportClientId, connectedTo: TransportClientId, providedOptions?: Partial<TransportOptions>);
|
|
412
419
|
protected handleConnection(conn: ConnType, to: TransportClientId): void;
|
|
420
|
+
receiveHandshakeResponseMessage(data: Uint8Array): false | {
|
|
421
|
+
instanceId: string;
|
|
422
|
+
from: string;
|
|
423
|
+
};
|
|
413
424
|
/**
|
|
414
425
|
* Abstract method that creates a new {@link Connection} object.
|
|
415
426
|
* This should call {@link handleConnection} when the connection is created.
|
|
@@ -424,13 +435,16 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
424
435
|
* @param to The client ID of the node to connect to.
|
|
425
436
|
*/
|
|
426
437
|
connect(to: TransportClientId, attempt?: number): Promise<void>;
|
|
427
|
-
|
|
428
|
-
onDisconnect(conn: ConnType, connectedTo: string): void;
|
|
438
|
+
protected sendHandshake(to: TransportClientId, conn: ConnType): void;
|
|
439
|
+
protected onDisconnect(conn: ConnType, connectedTo: string): void;
|
|
429
440
|
}
|
|
430
441
|
declare abstract class ServerTransport<ConnType extends Connection> extends Transport<ConnType> {
|
|
431
442
|
constructor(clientId: TransportClientId, providedOptions?: Partial<TransportOptions>);
|
|
432
443
|
protected handleConnection(conn: ConnType): void;
|
|
433
|
-
|
|
444
|
+
receiveHandshakeRequestMessage(data: Uint8Array, conn: ConnType): false | {
|
|
445
|
+
instanceId: string;
|
|
446
|
+
from: string;
|
|
447
|
+
};
|
|
434
448
|
}
|
|
435
449
|
|
|
436
450
|
export { Connection as C, EventMap as E, OpaqueTransportMessage as O, PartialTransportMessage as P, ServerTransport as S, Transport as T, ClientTransport as a, TransportClientId as b, TransportOptions as c, Session as d, TransportMessageSchema as e, OpaqueTransportMessageSchema as f, TransportMessage as g, isStreamClose as h, isStreamOpen as i, EventTypes as j, EventHandler as k };
|