@replit/river 0.15.0 → 0.15.2
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 +41 -22
- package/dist/{builder-ca6c4259.d.ts → builder-ebd945c0.d.ts} +1 -1
- package/dist/{chunk-IVNV5HBI.js → chunk-B7VTDQR7.js} +160 -51
- package/dist/{chunk-BSAIT634.js → chunk-UJHTHOTT.js} +1 -1
- package/dist/{chunk-FFT7PSUV.js → chunk-ZRB6IKPV.js} +1 -1
- package/dist/{connection-0c5eeb14.d.ts → connection-10a24478.d.ts} +1 -1
- package/dist/{connection-14675d77.d.ts → connection-f4492948.d.ts} +1 -1
- package/dist/{index-f922ec84.d.ts → index-bbccacef.d.ts} +90 -16
- package/dist/router/index.d.cts +3 -3
- package/dist/router/index.d.ts +3 -3
- package/dist/transport/impls/uds/client.cjs +206 -92
- package/dist/transport/impls/uds/client.d.cts +3 -3
- package/dist/transport/impls/uds/client.d.ts +3 -3
- package/dist/transport/impls/uds/client.js +2 -2
- package/dist/transport/impls/uds/server.cjs +75 -73
- package/dist/transport/impls/uds/server.d.cts +3 -3
- package/dist/transport/impls/uds/server.d.ts +3 -3
- package/dist/transport/impls/uds/server.js +2 -2
- package/dist/transport/impls/ws/client.cjs +206 -94
- package/dist/transport/impls/ws/client.d.cts +3 -3
- package/dist/transport/impls/ws/client.d.ts +3 -3
- package/dist/transport/impls/ws/client.js +2 -2
- package/dist/transport/impls/ws/server.cjs +75 -73
- package/dist/transport/impls/ws/server.d.cts +3 -3
- package/dist/transport/impls/ws/server.d.ts +3 -3
- package/dist/transport/impls/ws/server.js +2 -2
- package/dist/transport/index.cjs +211 -105
- 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 +61 -64
- package/dist/util/testHelpers.d.cts +10 -4
- package/dist/util/testHelpers.d.ts +10 -4
- package/dist/util/testHelpers.js +13 -5
- package/package.json +1 -1
package/dist/router/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
2
|
-
export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-
|
|
3
|
-
import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-
|
|
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-ebd945c0.js';
|
|
2
|
+
export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-ebd945c0.js';
|
|
3
|
+
import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-bbccacef.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
|
-
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-
|
|
2
|
-
export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-
|
|
3
|
-
import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-
|
|
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-ebd945c0.js';
|
|
2
|
+
export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-ebd945c0.js';
|
|
3
|
+
import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-bbccacef.js';
|
|
4
4
|
import { Pushable } from 'it-pushable';
|
|
5
5
|
import { Static } from '@sinclair/typebox';
|
|
6
6
|
import '../types-3e5768ec.js';
|
|
@@ -100,58 +100,6 @@ function isAck(controlFlag) {
|
|
|
100
100
|
return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// codec/json.ts
|
|
104
|
-
var encoder = new TextEncoder();
|
|
105
|
-
var decoder = new TextDecoder();
|
|
106
|
-
function uint8ArrayToBase64(uint8Array) {
|
|
107
|
-
let binary = "";
|
|
108
|
-
uint8Array.forEach((byte) => {
|
|
109
|
-
binary += String.fromCharCode(byte);
|
|
110
|
-
});
|
|
111
|
-
return btoa(binary);
|
|
112
|
-
}
|
|
113
|
-
function base64ToUint8Array(base64) {
|
|
114
|
-
const binaryString = atob(base64);
|
|
115
|
-
const uint8Array = new Uint8Array(binaryString.length);
|
|
116
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
117
|
-
uint8Array[i] = binaryString.charCodeAt(i);
|
|
118
|
-
}
|
|
119
|
-
return uint8Array;
|
|
120
|
-
}
|
|
121
|
-
var NaiveJsonCodec = {
|
|
122
|
-
toBuffer: (obj) => {
|
|
123
|
-
return encoder.encode(
|
|
124
|
-
JSON.stringify(obj, function replacer(key) {
|
|
125
|
-
const val = this[key];
|
|
126
|
-
if (val instanceof Uint8Array) {
|
|
127
|
-
return { $t: uint8ArrayToBase64(val) };
|
|
128
|
-
} else {
|
|
129
|
-
return val;
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
);
|
|
133
|
-
},
|
|
134
|
-
fromBuffer: (buff) => {
|
|
135
|
-
try {
|
|
136
|
-
const parsed = JSON.parse(
|
|
137
|
-
decoder.decode(buff),
|
|
138
|
-
function reviver(_key, val) {
|
|
139
|
-
if (val?.$t) {
|
|
140
|
-
return base64ToUint8Array(val.$t);
|
|
141
|
-
} else {
|
|
142
|
-
return val;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
);
|
|
146
|
-
if (typeof parsed === "object")
|
|
147
|
-
return parsed;
|
|
148
|
-
return null;
|
|
149
|
-
} catch {
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
|
|
155
103
|
// transport/session.ts
|
|
156
104
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
157
105
|
var unsafeId = () => nanoid2();
|
|
@@ -161,15 +109,6 @@ var Connection = class {
|
|
|
161
109
|
this.debugId = `conn-${unsafeId()}`;
|
|
162
110
|
}
|
|
163
111
|
};
|
|
164
|
-
var HEARTBEAT_INTERVAL_MS = 1e3;
|
|
165
|
-
var HEARTBEATS_TILL_DEAD = 2;
|
|
166
|
-
var SESSION_DISCONNECT_GRACE_MS = 5e3;
|
|
167
|
-
var defaultSessionOptions = {
|
|
168
|
-
heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
|
|
169
|
-
heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
|
|
170
|
-
sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
|
|
171
|
-
codec: NaiveJsonCodec
|
|
172
|
-
};
|
|
173
112
|
var Session = class {
|
|
174
113
|
codec;
|
|
175
114
|
options;
|
|
@@ -450,6 +389,11 @@ var UdsConnection = class extends Connection {
|
|
|
450
389
|
var import_value = require("@sinclair/typebox/value");
|
|
451
390
|
|
|
452
391
|
// transport/events.ts
|
|
392
|
+
var ProtocolError = {
|
|
393
|
+
RetriesExceeded: "conn_retry_exceeded",
|
|
394
|
+
HandshakeFailed: "handshake_failed",
|
|
395
|
+
UseAfterDestroy: "use_after_destroy"
|
|
396
|
+
};
|
|
453
397
|
var EventDispatcher = class {
|
|
454
398
|
eventListeners = {};
|
|
455
399
|
numberOfListeners(eventType) {
|
|
@@ -488,14 +432,146 @@ function coerceErrorString(err) {
|
|
|
488
432
|
return `[coerced to error] ${String(err)}`;
|
|
489
433
|
}
|
|
490
434
|
|
|
435
|
+
// transport/rateLimit.ts
|
|
436
|
+
var LeakyBucketRateLimit = class {
|
|
437
|
+
budgetConsumed;
|
|
438
|
+
intervalHandles;
|
|
439
|
+
options;
|
|
440
|
+
constructor(options) {
|
|
441
|
+
this.options = options;
|
|
442
|
+
this.budgetConsumed = /* @__PURE__ */ new Map();
|
|
443
|
+
this.intervalHandles = /* @__PURE__ */ new Map();
|
|
444
|
+
}
|
|
445
|
+
getBackoffMs(user) {
|
|
446
|
+
if (!this.budgetConsumed.has(user))
|
|
447
|
+
return 0;
|
|
448
|
+
const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
|
|
449
|
+
const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
|
|
450
|
+
const backoffMs = Math.min(
|
|
451
|
+
this.options.baseIntervalMs * 2 ** exponent,
|
|
452
|
+
this.options.maxBackoffMs
|
|
453
|
+
);
|
|
454
|
+
return backoffMs + jitter;
|
|
455
|
+
}
|
|
456
|
+
get totalBudgetRestoreTime() {
|
|
457
|
+
return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
|
|
458
|
+
}
|
|
459
|
+
consumeBudget(user) {
|
|
460
|
+
this.stopLeak(user);
|
|
461
|
+
this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
|
|
462
|
+
}
|
|
463
|
+
getBudgetConsumed(user) {
|
|
464
|
+
return this.budgetConsumed.get(user) ?? 0;
|
|
465
|
+
}
|
|
466
|
+
hasBudget(user) {
|
|
467
|
+
return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
|
|
468
|
+
}
|
|
469
|
+
startRestoringBudget(user) {
|
|
470
|
+
if (this.intervalHandles.has(user)) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
const restoreBudgetForUser = () => {
|
|
474
|
+
const currentBudget = this.budgetConsumed.get(user);
|
|
475
|
+
if (!currentBudget) {
|
|
476
|
+
this.stopLeak(user);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const newBudget = currentBudget - 1;
|
|
480
|
+
if (newBudget === 0) {
|
|
481
|
+
this.budgetConsumed.delete(user);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
this.budgetConsumed.set(user, newBudget);
|
|
485
|
+
};
|
|
486
|
+
restoreBudgetForUser();
|
|
487
|
+
const intervalHandle = setInterval(
|
|
488
|
+
restoreBudgetForUser,
|
|
489
|
+
this.options.budgetRestoreIntervalMs
|
|
490
|
+
);
|
|
491
|
+
this.intervalHandles.set(user, intervalHandle);
|
|
492
|
+
}
|
|
493
|
+
stopLeak(user) {
|
|
494
|
+
if (!this.intervalHandles.has(user)) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
clearInterval(this.intervalHandles.get(user));
|
|
498
|
+
this.intervalHandles.delete(user);
|
|
499
|
+
}
|
|
500
|
+
close() {
|
|
501
|
+
for (const user of this.intervalHandles.keys()) {
|
|
502
|
+
this.stopLeak(user);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// codec/json.ts
|
|
508
|
+
var encoder = new TextEncoder();
|
|
509
|
+
var decoder = new TextDecoder();
|
|
510
|
+
function uint8ArrayToBase64(uint8Array) {
|
|
511
|
+
let binary = "";
|
|
512
|
+
uint8Array.forEach((byte) => {
|
|
513
|
+
binary += String.fromCharCode(byte);
|
|
514
|
+
});
|
|
515
|
+
return btoa(binary);
|
|
516
|
+
}
|
|
517
|
+
function base64ToUint8Array(base64) {
|
|
518
|
+
const binaryString = atob(base64);
|
|
519
|
+
const uint8Array = new Uint8Array(binaryString.length);
|
|
520
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
521
|
+
uint8Array[i] = binaryString.charCodeAt(i);
|
|
522
|
+
}
|
|
523
|
+
return uint8Array;
|
|
524
|
+
}
|
|
525
|
+
var NaiveJsonCodec = {
|
|
526
|
+
toBuffer: (obj) => {
|
|
527
|
+
return encoder.encode(
|
|
528
|
+
JSON.stringify(obj, function replacer(key) {
|
|
529
|
+
const val = this[key];
|
|
530
|
+
if (val instanceof Uint8Array) {
|
|
531
|
+
return { $t: uint8ArrayToBase64(val) };
|
|
532
|
+
} else {
|
|
533
|
+
return val;
|
|
534
|
+
}
|
|
535
|
+
})
|
|
536
|
+
);
|
|
537
|
+
},
|
|
538
|
+
fromBuffer: (buff) => {
|
|
539
|
+
try {
|
|
540
|
+
const parsed = JSON.parse(
|
|
541
|
+
decoder.decode(buff),
|
|
542
|
+
function reviver(_key, val) {
|
|
543
|
+
if (val?.$t) {
|
|
544
|
+
return base64ToUint8Array(val.$t);
|
|
545
|
+
} else {
|
|
546
|
+
return val;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
if (typeof parsed === "object")
|
|
551
|
+
return parsed;
|
|
552
|
+
return null;
|
|
553
|
+
} catch {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
|
|
491
559
|
// transport/transport.ts
|
|
492
|
-
var RECONNECT_JITTER_MAX_MS = 500;
|
|
493
|
-
var RECONNECT_INTERVAL_MS = 250;
|
|
494
560
|
var defaultTransportOptions = {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
561
|
+
heartbeatIntervalMs: 1e3,
|
|
562
|
+
heartbeatsUntilDead: 2,
|
|
563
|
+
sessionDisconnectGraceMs: 5e3,
|
|
564
|
+
codec: NaiveJsonCodec
|
|
565
|
+
};
|
|
566
|
+
var defaultClientTransportOptions = {
|
|
567
|
+
connectionRetryOptions: {
|
|
568
|
+
baseIntervalMs: 250,
|
|
569
|
+
maxJitterMs: 200,
|
|
570
|
+
maxBackoffMs: 32e3,
|
|
571
|
+
attemptBudgetCapacity: 15,
|
|
572
|
+
budgetRestoreIntervalMs: 200
|
|
573
|
+
},
|
|
574
|
+
...defaultTransportOptions
|
|
499
575
|
};
|
|
500
576
|
var Transport = class {
|
|
501
577
|
/**
|
|
@@ -710,7 +786,7 @@ var Transport = class {
|
|
|
710
786
|
if (this.state === "destroyed") {
|
|
711
787
|
const err = "transport is destroyed, cant send";
|
|
712
788
|
log?.error(`${this.clientId} -- ` + err + `: ${JSON.stringify(msg)}`);
|
|
713
|
-
this.protocolError(
|
|
789
|
+
this.protocolError(ProtocolError.UseAfterDestroy, err);
|
|
714
790
|
return void 0;
|
|
715
791
|
} else if (this.state === "closed") {
|
|
716
792
|
log?.info(
|
|
@@ -770,14 +846,26 @@ var Transport = class {
|
|
|
770
846
|
}
|
|
771
847
|
};
|
|
772
848
|
var ClientTransport = class extends Transport {
|
|
849
|
+
/**
|
|
850
|
+
* The options for this transport.
|
|
851
|
+
*/
|
|
852
|
+
options;
|
|
773
853
|
/**
|
|
774
854
|
* The map of reconnect promises for each client ID.
|
|
775
855
|
*/
|
|
776
856
|
inflightConnectionPromises;
|
|
857
|
+
retryBudget;
|
|
777
858
|
tryReconnecting = true;
|
|
778
859
|
constructor(clientId, providedOptions) {
|
|
779
860
|
super(clientId, providedOptions);
|
|
861
|
+
this.options = {
|
|
862
|
+
...defaultClientTransportOptions,
|
|
863
|
+
...providedOptions
|
|
864
|
+
};
|
|
780
865
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
866
|
+
this.retryBudget = new LeakyBucketRateLimit(
|
|
867
|
+
this.options.connectionRetryOptions
|
|
868
|
+
);
|
|
781
869
|
}
|
|
782
870
|
handleConnection(conn, to) {
|
|
783
871
|
if (this.state !== "open")
|
|
@@ -808,7 +896,10 @@ var ClientTransport = class extends Transport {
|
|
|
808
896
|
log?.info(
|
|
809
897
|
`${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
|
|
810
898
|
);
|
|
811
|
-
|
|
899
|
+
this.inflightConnectionPromises.delete(to);
|
|
900
|
+
if (this.tryReconnecting) {
|
|
901
|
+
void this.connect(to);
|
|
902
|
+
}
|
|
812
903
|
});
|
|
813
904
|
conn.addErrorListener((err) => {
|
|
814
905
|
log?.warn(
|
|
@@ -820,7 +911,7 @@ var ClientTransport = class extends Transport {
|
|
|
820
911
|
const parsed = this.parseMsg(data);
|
|
821
912
|
if (!parsed) {
|
|
822
913
|
this.protocolError(
|
|
823
|
-
|
|
914
|
+
ProtocolError.HandshakeFailed,
|
|
824
915
|
"received non-transport message"
|
|
825
916
|
);
|
|
826
917
|
return false;
|
|
@@ -832,7 +923,7 @@ var ClientTransport = class extends Transport {
|
|
|
832
923
|
)}`
|
|
833
924
|
);
|
|
834
925
|
this.protocolError(
|
|
835
|
-
|
|
926
|
+
ProtocolError.HandshakeFailed,
|
|
836
927
|
"invalid handshake resp"
|
|
837
928
|
);
|
|
838
929
|
return false;
|
|
@@ -844,7 +935,7 @@ var ClientTransport = class extends Transport {
|
|
|
844
935
|
)}`
|
|
845
936
|
);
|
|
846
937
|
this.protocolError(
|
|
847
|
-
|
|
938
|
+
ProtocolError.HandshakeFailed,
|
|
848
939
|
parsed.payload.status.reason
|
|
849
940
|
);
|
|
850
941
|
return false;
|
|
@@ -859,41 +950,64 @@ var ClientTransport = class extends Transport {
|
|
|
859
950
|
* Manually attempts to connect to a client.
|
|
860
951
|
* @param to The client ID of the node to connect to.
|
|
861
952
|
*/
|
|
862
|
-
async connect(to
|
|
863
|
-
|
|
953
|
+
async connect(to) {
|
|
954
|
+
const canProceedWithConnection = () => this.state === "open";
|
|
955
|
+
if (!canProceedWithConnection()) {
|
|
864
956
|
log?.info(
|
|
865
|
-
`${this.clientId} -- transport state is no longer open,
|
|
957
|
+
`${this.clientId} -- transport state is no longer open, cancelling attempt to connect to ${to}`
|
|
866
958
|
);
|
|
867
959
|
return;
|
|
868
960
|
}
|
|
869
961
|
let reconnectPromise = this.inflightConnectionPromises.get(to);
|
|
870
962
|
if (!reconnectPromise) {
|
|
871
|
-
|
|
963
|
+
log?.info(`${this.clientId} -- attempting connection to ${to}`);
|
|
964
|
+
const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
|
|
965
|
+
if (!this.retryBudget.hasBudget(to)) {
|
|
966
|
+
const errMsg = `not attempting to connect to ${to}, retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
967
|
+
log?.warn(`${this.clientId} -- ${errMsg}`);
|
|
968
|
+
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
let sleep = Promise.resolve();
|
|
972
|
+
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
973
|
+
if (backoffMs > 0) {
|
|
974
|
+
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
975
|
+
}
|
|
976
|
+
this.retryBudget.consumeBudget(to);
|
|
977
|
+
reconnectPromise = sleep.then(() => {
|
|
978
|
+
if (!canProceedWithConnection()) {
|
|
979
|
+
throw new Error("transport state is no longer open");
|
|
980
|
+
}
|
|
981
|
+
}).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
|
|
982
|
+
if (!canProceedWithConnection()) {
|
|
983
|
+
log?.info(
|
|
984
|
+
`${this.clientId} -- transport state is no longer open, closing pre-handshake connection (id: ${conn.debugId}) to ${to}`
|
|
985
|
+
);
|
|
986
|
+
conn.close();
|
|
987
|
+
throw new Error("transport state is no longer open");
|
|
988
|
+
}
|
|
989
|
+
this.retryBudget.startRestoringBudget(to);
|
|
872
990
|
this.sendHandshake(to, conn);
|
|
873
991
|
return conn;
|
|
874
992
|
});
|
|
875
993
|
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
994
|
+
} else {
|
|
995
|
+
log?.info(
|
|
996
|
+
`${this.clientId} -- attempting connection to ${to} (reusing previous attempt)`
|
|
997
|
+
);
|
|
876
998
|
}
|
|
877
999
|
try {
|
|
878
1000
|
await reconnectPromise;
|
|
879
1001
|
} catch (error) {
|
|
880
|
-
const errStr = coerceErrorString(error);
|
|
881
1002
|
this.inflightConnectionPromises.delete(to);
|
|
882
|
-
const
|
|
883
|
-
if (!
|
|
884
|
-
|
|
885
|
-
if (attempt >= this.options.retryAttemptsMax) {
|
|
886
|
-
const errMsg = `connection to ${to} failed after ${attempt} attempts (${errStr}), giving up`;
|
|
887
|
-
log?.error(`${this.clientId} -- ${errMsg}`);
|
|
888
|
-
this.protocolError("conn_retry_exceeded" /* RetriesExceeded */, errMsg);
|
|
889
|
-
return;
|
|
1003
|
+
const errStr = coerceErrorString(error);
|
|
1004
|
+
if (!this.tryReconnecting || !canProceedWithConnection()) {
|
|
1005
|
+
log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
|
|
890
1006
|
} else {
|
|
891
|
-
const jitter = Math.floor(Math.random() * this.options.retryJitterMs);
|
|
892
|
-
const backoffMs = this.options.retryIntervalMs * 2 ** attempt + jitter;
|
|
893
1007
|
log?.warn(
|
|
894
|
-
`${this.clientId} -- connection to ${to} failed (${errStr}),
|
|
1008
|
+
`${this.clientId} -- connection to ${to} failed (${errStr}), retrying`
|
|
895
1009
|
);
|
|
896
|
-
|
|
1010
|
+
return this.connect(to);
|
|
897
1011
|
}
|
|
898
1012
|
}
|
|
899
1013
|
}
|
|
@@ -906,9 +1020,9 @@ var ClientTransport = class extends Transport {
|
|
|
906
1020
|
log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
|
|
907
1021
|
conn.send(this.codec.toBuffer(requestMsg));
|
|
908
1022
|
}
|
|
909
|
-
|
|
910
|
-
this.
|
|
911
|
-
super.
|
|
1023
|
+
close() {
|
|
1024
|
+
this.retryBudget.close();
|
|
1025
|
+
super.close();
|
|
912
1026
|
}
|
|
913
1027
|
};
|
|
914
1028
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ClientTransport, c as
|
|
2
|
-
import { U as UdsConnection } from '../../../connection-
|
|
1
|
+
import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-bbccacef.js';
|
|
2
|
+
import { U as UdsConnection } from '../../../connection-10a24478.js';
|
|
3
3
|
import '../../../types-3e5768ec.js';
|
|
4
4
|
import '@sinclair/typebox';
|
|
5
5
|
import 'node:net';
|
|
@@ -7,7 +7,7 @@ import 'node:stream';
|
|
|
7
7
|
|
|
8
8
|
declare class UnixDomainSocketClientTransport extends ClientTransport<UdsConnection> {
|
|
9
9
|
path: string;
|
|
10
|
-
constructor(socketPath: string, clientId: string, providedOptions?:
|
|
10
|
+
constructor(socketPath: string, clientId: string, providedOptions?: ProvidedClientTransportOptions);
|
|
11
11
|
createNewOutgoingConnection(to: TransportClientId): Promise<UdsConnection>;
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ClientTransport, c as
|
|
2
|
-
import { U as UdsConnection } from '../../../connection-
|
|
1
|
+
import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-bbccacef.js';
|
|
2
|
+
import { U as UdsConnection } from '../../../connection-10a24478.js';
|
|
3
3
|
import '../../../types-3e5768ec.js';
|
|
4
4
|
import '@sinclair/typebox';
|
|
5
5
|
import 'node:net';
|
|
@@ -7,7 +7,7 @@ import 'node:stream';
|
|
|
7
7
|
|
|
8
8
|
declare class UnixDomainSocketClientTransport extends ClientTransport<UdsConnection> {
|
|
9
9
|
path: string;
|
|
10
|
-
constructor(socketPath: string, clientId: string, providedOptions?:
|
|
10
|
+
constructor(socketPath: string, clientId: string, providedOptions?: ProvidedClientTransportOptions);
|
|
11
11
|
createNewOutgoingConnection(to: TransportClientId): Promise<UdsConnection>;
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UdsConnection
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-UJHTHOTT.js";
|
|
4
4
|
import {
|
|
5
5
|
ClientTransport
|
|
6
|
-
} from "../../../chunk-
|
|
6
|
+
} from "../../../chunk-B7VTDQR7.js";
|
|
7
7
|
import "../../../chunk-GFRAOY75.js";
|
|
8
8
|
import {
|
|
9
9
|
log
|
|
@@ -108,6 +108,11 @@ function isAck(controlFlag) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// transport/events.ts
|
|
111
|
+
var ProtocolError = {
|
|
112
|
+
RetriesExceeded: "conn_retry_exceeded",
|
|
113
|
+
HandshakeFailed: "handshake_failed",
|
|
114
|
+
UseAfterDestroy: "use_after_destroy"
|
|
115
|
+
};
|
|
111
116
|
var EventDispatcher = class {
|
|
112
117
|
eventListeners = {};
|
|
113
118
|
numberOfListeners(eventType) {
|
|
@@ -137,60 +142,6 @@ var EventDispatcher = class {
|
|
|
137
142
|
|
|
138
143
|
// transport/session.ts
|
|
139
144
|
var import_nanoid2 = require("nanoid");
|
|
140
|
-
|
|
141
|
-
// codec/json.ts
|
|
142
|
-
var encoder = new TextEncoder();
|
|
143
|
-
var decoder = new TextDecoder();
|
|
144
|
-
function uint8ArrayToBase64(uint8Array) {
|
|
145
|
-
let binary = "";
|
|
146
|
-
uint8Array.forEach((byte) => {
|
|
147
|
-
binary += String.fromCharCode(byte);
|
|
148
|
-
});
|
|
149
|
-
return btoa(binary);
|
|
150
|
-
}
|
|
151
|
-
function base64ToUint8Array(base64) {
|
|
152
|
-
const binaryString = atob(base64);
|
|
153
|
-
const uint8Array = new Uint8Array(binaryString.length);
|
|
154
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
155
|
-
uint8Array[i] = binaryString.charCodeAt(i);
|
|
156
|
-
}
|
|
157
|
-
return uint8Array;
|
|
158
|
-
}
|
|
159
|
-
var NaiveJsonCodec = {
|
|
160
|
-
toBuffer: (obj) => {
|
|
161
|
-
return encoder.encode(
|
|
162
|
-
JSON.stringify(obj, function replacer(key) {
|
|
163
|
-
const val = this[key];
|
|
164
|
-
if (val instanceof Uint8Array) {
|
|
165
|
-
return { $t: uint8ArrayToBase64(val) };
|
|
166
|
-
} else {
|
|
167
|
-
return val;
|
|
168
|
-
}
|
|
169
|
-
})
|
|
170
|
-
);
|
|
171
|
-
},
|
|
172
|
-
fromBuffer: (buff) => {
|
|
173
|
-
try {
|
|
174
|
-
const parsed = JSON.parse(
|
|
175
|
-
decoder.decode(buff),
|
|
176
|
-
function reviver(_key, val) {
|
|
177
|
-
if (val?.$t) {
|
|
178
|
-
return base64ToUint8Array(val.$t);
|
|
179
|
-
} else {
|
|
180
|
-
return val;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
);
|
|
184
|
-
if (typeof parsed === "object")
|
|
185
|
-
return parsed;
|
|
186
|
-
return null;
|
|
187
|
-
} catch {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
// transport/session.ts
|
|
194
145
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
195
146
|
var unsafeId = () => nanoid2();
|
|
196
147
|
var Connection = class {
|
|
@@ -199,15 +150,6 @@ var Connection = class {
|
|
|
199
150
|
this.debugId = `conn-${unsafeId()}`;
|
|
200
151
|
}
|
|
201
152
|
};
|
|
202
|
-
var HEARTBEAT_INTERVAL_MS = 1e3;
|
|
203
|
-
var HEARTBEATS_TILL_DEAD = 2;
|
|
204
|
-
var SESSION_DISCONNECT_GRACE_MS = 5e3;
|
|
205
|
-
var defaultSessionOptions = {
|
|
206
|
-
heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
|
|
207
|
-
heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
|
|
208
|
-
sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
|
|
209
|
-
codec: NaiveJsonCodec
|
|
210
|
-
};
|
|
211
153
|
var Session = class {
|
|
212
154
|
codec;
|
|
213
155
|
options;
|
|
@@ -402,14 +344,74 @@ function coerceErrorString(err) {
|
|
|
402
344
|
return `[coerced to error] ${String(err)}`;
|
|
403
345
|
}
|
|
404
346
|
|
|
347
|
+
// codec/json.ts
|
|
348
|
+
var encoder = new TextEncoder();
|
|
349
|
+
var decoder = new TextDecoder();
|
|
350
|
+
function uint8ArrayToBase64(uint8Array) {
|
|
351
|
+
let binary = "";
|
|
352
|
+
uint8Array.forEach((byte) => {
|
|
353
|
+
binary += String.fromCharCode(byte);
|
|
354
|
+
});
|
|
355
|
+
return btoa(binary);
|
|
356
|
+
}
|
|
357
|
+
function base64ToUint8Array(base64) {
|
|
358
|
+
const binaryString = atob(base64);
|
|
359
|
+
const uint8Array = new Uint8Array(binaryString.length);
|
|
360
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
361
|
+
uint8Array[i] = binaryString.charCodeAt(i);
|
|
362
|
+
}
|
|
363
|
+
return uint8Array;
|
|
364
|
+
}
|
|
365
|
+
var NaiveJsonCodec = {
|
|
366
|
+
toBuffer: (obj) => {
|
|
367
|
+
return encoder.encode(
|
|
368
|
+
JSON.stringify(obj, function replacer(key) {
|
|
369
|
+
const val = this[key];
|
|
370
|
+
if (val instanceof Uint8Array) {
|
|
371
|
+
return { $t: uint8ArrayToBase64(val) };
|
|
372
|
+
} else {
|
|
373
|
+
return val;
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
);
|
|
377
|
+
},
|
|
378
|
+
fromBuffer: (buff) => {
|
|
379
|
+
try {
|
|
380
|
+
const parsed = JSON.parse(
|
|
381
|
+
decoder.decode(buff),
|
|
382
|
+
function reviver(_key, val) {
|
|
383
|
+
if (val?.$t) {
|
|
384
|
+
return base64ToUint8Array(val.$t);
|
|
385
|
+
} else {
|
|
386
|
+
return val;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
);
|
|
390
|
+
if (typeof parsed === "object")
|
|
391
|
+
return parsed;
|
|
392
|
+
return null;
|
|
393
|
+
} catch {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
405
399
|
// transport/transport.ts
|
|
406
|
-
var RECONNECT_JITTER_MAX_MS = 500;
|
|
407
|
-
var RECONNECT_INTERVAL_MS = 250;
|
|
408
400
|
var defaultTransportOptions = {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
401
|
+
heartbeatIntervalMs: 1e3,
|
|
402
|
+
heartbeatsUntilDead: 2,
|
|
403
|
+
sessionDisconnectGraceMs: 5e3,
|
|
404
|
+
codec: NaiveJsonCodec
|
|
405
|
+
};
|
|
406
|
+
var defaultClientTransportOptions = {
|
|
407
|
+
connectionRetryOptions: {
|
|
408
|
+
baseIntervalMs: 250,
|
|
409
|
+
maxJitterMs: 200,
|
|
410
|
+
maxBackoffMs: 32e3,
|
|
411
|
+
attemptBudgetCapacity: 15,
|
|
412
|
+
budgetRestoreIntervalMs: 200
|
|
413
|
+
},
|
|
414
|
+
...defaultTransportOptions
|
|
413
415
|
};
|
|
414
416
|
var Transport = class {
|
|
415
417
|
/**
|
|
@@ -624,7 +626,7 @@ var Transport = class {
|
|
|
624
626
|
if (this.state === "destroyed") {
|
|
625
627
|
const err = "transport is destroyed, cant send";
|
|
626
628
|
log?.error(`${this.clientId} -- ` + err + `: ${JSON.stringify(msg)}`);
|
|
627
|
-
this.protocolError(
|
|
629
|
+
this.protocolError(ProtocolError.UseAfterDestroy, err);
|
|
628
630
|
return void 0;
|
|
629
631
|
} else if (this.state === "closed") {
|
|
630
632
|
log?.info(
|
|
@@ -736,7 +738,7 @@ var ServerTransport = class extends Transport {
|
|
|
736
738
|
const parsed = this.parseMsg(data);
|
|
737
739
|
if (!parsed) {
|
|
738
740
|
this.protocolError(
|
|
739
|
-
|
|
741
|
+
ProtocolError.HandshakeFailed,
|
|
740
742
|
"received non-transport message"
|
|
741
743
|
);
|
|
742
744
|
return false;
|
|
@@ -755,7 +757,7 @@ var ServerTransport = class extends Transport {
|
|
|
755
757
|
)}`
|
|
756
758
|
);
|
|
757
759
|
this.protocolError(
|
|
758
|
-
|
|
760
|
+
ProtocolError.HandshakeFailed,
|
|
759
761
|
"invalid handshake request"
|
|
760
762
|
);
|
|
761
763
|
return false;
|
|
@@ -773,7 +775,7 @@ var ServerTransport = class extends Transport {
|
|
|
773
775
|
`${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
|
|
774
776
|
);
|
|
775
777
|
this.protocolError(
|
|
776
|
-
|
|
778
|
+
ProtocolError.HandshakeFailed,
|
|
777
779
|
`incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`
|
|
778
780
|
);
|
|
779
781
|
return false;
|