@actuallab/rpc 12.4.9 → 12.5.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/dist/index.cjs +110 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -25
- package/dist/index.d.ts +69 -25
- package/dist/index.js +110 -78
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -151,7 +151,8 @@ var RpcSystemCalls = {
|
|
|
151
151
|
ackEnd: "$sys.AckEnd:1",
|
|
152
152
|
item: "$sys.I:2",
|
|
153
153
|
batch: "$sys.B:2",
|
|
154
|
-
end: "$sys.End:2"
|
|
154
|
+
end: "$sys.End:2",
|
|
155
|
+
disconnect: "$sys.Disconnect:1"
|
|
155
156
|
};
|
|
156
157
|
var ENVELOPE_DELIMITER = "\n";
|
|
157
158
|
var ARG_DELIMITER = "";
|
|
@@ -976,7 +977,7 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
|
|
|
976
977
|
var import_core5 = require("@actuallab/core");
|
|
977
978
|
var { warnLog: warnLog3 } = getLogs("RpcSharedStream");
|
|
978
979
|
var DEFAULT_ACK_PERIOD = 256;
|
|
979
|
-
var
|
|
980
|
+
var DEFAULT_ACK_ADVANCE = 128;
|
|
980
981
|
var RpcStreamSender = class _RpcStreamSender {
|
|
981
982
|
static _emptyGuid = "00000000-0000-0000-0000-000000000000";
|
|
982
983
|
id;
|
|
@@ -986,6 +987,18 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
986
987
|
canSkipTo;
|
|
987
988
|
peer;
|
|
988
989
|
ackPeriod;
|
|
990
|
+
/**
|
|
991
|
+
* Wire-level flow-control window: the maximum index the sender may
|
|
992
|
+
* advance past the most recently acknowledged index. Mirrors .NET
|
|
993
|
+
* `RpcStream.AckAdvance`.
|
|
994
|
+
*/
|
|
995
|
+
ackAdvance;
|
|
996
|
+
/**
|
|
997
|
+
* Effective local ring buffer capacity used by the pump. Set larger
|
|
998
|
+
* than `ackAdvance` to pre-buffer items beyond the in-flight window;
|
|
999
|
+
* values below `ackAdvance` are clamped up (with a warning) at
|
|
1000
|
+
* construction time. Not transmitted on the wire.
|
|
1001
|
+
*/
|
|
989
1002
|
bufferSize;
|
|
990
1003
|
/**
|
|
991
1004
|
* If true, the source was produced by a factory `(abortSignal) => AsyncIterable<T>`
|
|
@@ -1014,6 +1027,13 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1014
1027
|
* watchdog so it can distinguish "stuck" (no ACK > N s) from
|
|
1015
1028
|
* "throttled" (ACKs flowing). */
|
|
1016
1029
|
onAckProcessed;
|
|
1030
|
+
/** Fires after each item is pushed onto the local ring buffer. The
|
|
1031
|
+
* argument is the buffer count *after* the push. Together with
|
|
1032
|
+
* `onAckProcessed` (which is the only place items leave the buffer),
|
|
1033
|
+
* this gives controllers a complete picture of buffer utilization.
|
|
1034
|
+
* When `bufferedCount === bufferSize`, the source pull is paused
|
|
1035
|
+
* until the next ACK frees space. Listener errors are swallowed. */
|
|
1036
|
+
onBuffered;
|
|
1017
1037
|
get nextIndex() {
|
|
1018
1038
|
return this._nextIndex;
|
|
1019
1039
|
}
|
|
@@ -1026,7 +1046,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1026
1046
|
// -- ACK queue (analog of .NET's Channel<(long, bool)>) --
|
|
1027
1047
|
_acks = [];
|
|
1028
1048
|
_whenAckReady = null;
|
|
1029
|
-
constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD,
|
|
1049
|
+
constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true, isRealTime = false, canSkipTo = () => true, sourceUsesAbortSignal = false, bufferSize) {
|
|
1030
1050
|
const localId = peer.sharedObjects.nextId();
|
|
1031
1051
|
this.id = { hostId: peer.hub.hubId, localId };
|
|
1032
1052
|
this.allowReconnect = allowReconnect;
|
|
@@ -1034,8 +1054,13 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1034
1054
|
this.canSkipTo = canSkipTo;
|
|
1035
1055
|
this.peer = peer;
|
|
1036
1056
|
this.ackPeriod = ackPeriod;
|
|
1037
|
-
this.
|
|
1057
|
+
this.ackAdvance = ackAdvance;
|
|
1038
1058
|
this.sourceUsesAbortSignal = sourceUsesAbortSignal;
|
|
1059
|
+
if (bufferSize !== void 0 && bufferSize !== 0 && bufferSize < ackAdvance)
|
|
1060
|
+
warnLog3?.log(
|
|
1061
|
+
`RpcStream bufferSize (${bufferSize}) is below ackAdvance (${ackAdvance}); using ackAdvance as buffer size.`
|
|
1062
|
+
);
|
|
1063
|
+
this.bufferSize = bufferSize !== void 0 && bufferSize >= ackAdvance ? bufferSize : ackAdvance;
|
|
1039
1064
|
}
|
|
1040
1065
|
/** AbortSignal that is aborted when the sender is disconnected. */
|
|
1041
1066
|
get abortSignal() {
|
|
@@ -1043,7 +1068,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1043
1068
|
}
|
|
1044
1069
|
/** Returns the stream reference string for the $sys.Ok response. */
|
|
1045
1070
|
toRef() {
|
|
1046
|
-
return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.
|
|
1071
|
+
return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"},${this.isRealTime ? "1" : "0"}`;
|
|
1047
1072
|
}
|
|
1048
1073
|
/**
|
|
1049
1074
|
* Called by system call handler when $sys.Ack is received from the client.
|
|
@@ -1139,8 +1164,10 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1139
1164
|
}
|
|
1140
1165
|
/**
|
|
1141
1166
|
* ACK-driven pump. Non-real-time streams apply normal backpressure at
|
|
1142
|
-
* `
|
|
1167
|
+
* `ackAdvance`; real-time streams may compact the already-buffered unsent
|
|
1143
1168
|
* suffix to the latest buffered `canSkipTo` item after the consumer ACKs.
|
|
1169
|
+
* With `bufferSize > ackAdvance` the local ring buffer holds more than the
|
|
1170
|
+
* in-flight window — real-time mode uses the extra space to pre-buffer.
|
|
1144
1171
|
*/
|
|
1145
1172
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition -- _ended changes across awaits */
|
|
1146
1173
|
async _run(iterator, state) {
|
|
@@ -1162,6 +1189,12 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1162
1189
|
Promise.resolve(pending)
|
|
1163
1190
|
]);
|
|
1164
1191
|
};
|
|
1192
|
+
const fireBuffered = () => {
|
|
1193
|
+
try {
|
|
1194
|
+
this.onBuffered?.(buffer.count);
|
|
1195
|
+
} catch {
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1165
1198
|
const bufferNext = async (onlyIfReady, prefetchNext) => {
|
|
1166
1199
|
let r;
|
|
1167
1200
|
try {
|
|
@@ -1179,6 +1212,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1179
1212
|
if (prefetchNext)
|
|
1180
1213
|
whenMovedNext = iterator.next();
|
|
1181
1214
|
}
|
|
1215
|
+
fireBuffered();
|
|
1182
1216
|
return true;
|
|
1183
1217
|
} catch (e) {
|
|
1184
1218
|
whenMovedNext = null;
|
|
@@ -1188,6 +1222,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1188
1222
|
kind: "error",
|
|
1189
1223
|
error: e instanceof Error ? e : new Error(String(e))
|
|
1190
1224
|
});
|
|
1225
|
+
fireBuffered();
|
|
1191
1226
|
return true;
|
|
1192
1227
|
}
|
|
1193
1228
|
};
|
|
@@ -1232,6 +1267,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1232
1267
|
};
|
|
1233
1268
|
}
|
|
1234
1269
|
buffer.pushTail(item);
|
|
1270
|
+
fireBuffered();
|
|
1235
1271
|
if (accepted || isFullyBuffered) break;
|
|
1236
1272
|
}
|
|
1237
1273
|
}
|
|
@@ -1246,7 +1282,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1246
1282
|
return;
|
|
1247
1283
|
}
|
|
1248
1284
|
let bufferIndex = this._nextIndex - bufferStart;
|
|
1249
|
-
const maxIndex = ack.nextIndex + this.
|
|
1285
|
+
const maxIndex = ack.nextIndex + this.ackAdvance;
|
|
1250
1286
|
while (this._nextIndex < maxIndex) {
|
|
1251
1287
|
if (this._ended) return;
|
|
1252
1288
|
if (isRealTime) {
|
|
@@ -1380,7 +1416,7 @@ function _compactBufferedUnsentSuffix(buffer, firstUnsentIndex, canSkipTo) {
|
|
|
1380
1416
|
// src/rpc-stream.ts
|
|
1381
1417
|
var { warnLog: warnLog4 } = getLogs("RpcStream");
|
|
1382
1418
|
var DEFAULT_ACK_PERIOD2 = 30;
|
|
1383
|
-
var
|
|
1419
|
+
var DEFAULT_ACK_ADVANCE2 = 61;
|
|
1384
1420
|
function parseStreamRef(value) {
|
|
1385
1421
|
if (typeof value === "string") {
|
|
1386
1422
|
const parts = value.split(",");
|
|
@@ -1388,12 +1424,12 @@ function parseStreamRef(value) {
|
|
|
1388
1424
|
const hostId = parts[0];
|
|
1389
1425
|
const localId = parseInt(parts[1], 10);
|
|
1390
1426
|
const ackPeriod = parseInt(parts[2], 10);
|
|
1391
|
-
const
|
|
1392
|
-
if (isNaN(localId) || isNaN(ackPeriod) || isNaN(
|
|
1427
|
+
const ackAdvance = parseInt(parts[3], 10);
|
|
1428
|
+
if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance))
|
|
1393
1429
|
return null;
|
|
1394
1430
|
const allowReconnect = parts.length < 5 || parts[4] !== "0";
|
|
1395
1431
|
const isRealTime = parts.length >= 6 && parts[5] === "1";
|
|
1396
|
-
return { hostId, localId, ackPeriod,
|
|
1432
|
+
return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
|
|
1397
1433
|
}
|
|
1398
1434
|
if (typeof value === "object" && value !== null) {
|
|
1399
1435
|
const obj = value;
|
|
@@ -1404,10 +1440,10 @@ function parseStreamRef(value) {
|
|
|
1404
1440
|
const hostId = String(rawHostId);
|
|
1405
1441
|
const localId = Number(serializedId[1]);
|
|
1406
1442
|
const ackPeriod = Number(obj.AckPeriod ?? 256);
|
|
1407
|
-
const
|
|
1443
|
+
const ackAdvance = Number(obj.AckAdvance ?? 128);
|
|
1408
1444
|
const allowReconnect = obj.AllowReconnect !== false;
|
|
1409
1445
|
const isRealTime = obj.IsRealTime === true;
|
|
1410
|
-
return { hostId, localId, ackPeriod,
|
|
1446
|
+
return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
|
|
1411
1447
|
}
|
|
1412
1448
|
return null;
|
|
1413
1449
|
}
|
|
@@ -1427,6 +1463,11 @@ var RpcStream = class _RpcStream {
|
|
|
1427
1463
|
isRealTime;
|
|
1428
1464
|
canSkipTo;
|
|
1429
1465
|
ackPeriod;
|
|
1466
|
+
ackAdvance;
|
|
1467
|
+
/**
|
|
1468
|
+
* Local-only ring buffer capacity hint for the sender. Undefined means
|
|
1469
|
+
* "use ackAdvance as the buffer size". Not part of the wire ref.
|
|
1470
|
+
*/
|
|
1430
1471
|
bufferSize;
|
|
1431
1472
|
// Local (origin) mode
|
|
1432
1473
|
localSource;
|
|
@@ -1457,7 +1498,8 @@ var RpcStream = class _RpcStream {
|
|
|
1457
1498
|
this.isRealTime = options.isRealTime ?? false;
|
|
1458
1499
|
this.canSkipTo = options.canSkipTo ?? (() => true);
|
|
1459
1500
|
this.ackPeriod = options.ackPeriod ?? DEFAULT_ACK_PERIOD2;
|
|
1460
|
-
this.
|
|
1501
|
+
this.ackAdvance = options.ackAdvance ?? DEFAULT_ACK_ADVANCE2;
|
|
1502
|
+
this.bufferSize = options.bufferSize;
|
|
1461
1503
|
} else {
|
|
1462
1504
|
const ref = sourceOrRef;
|
|
1463
1505
|
const peer = optionsOrPeer;
|
|
@@ -1468,7 +1510,7 @@ var RpcStream = class _RpcStream {
|
|
|
1468
1510
|
this.isRealTime = ref.isRealTime;
|
|
1469
1511
|
this.canSkipTo = () => true;
|
|
1470
1512
|
this.ackPeriod = ref.ackPeriod;
|
|
1471
|
-
this.
|
|
1513
|
+
this.ackAdvance = ref.ackAdvance;
|
|
1472
1514
|
}
|
|
1473
1515
|
}
|
|
1474
1516
|
/**
|
|
@@ -1491,7 +1533,7 @@ var RpcStream = class _RpcStream {
|
|
|
1491
1533
|
* stream reference.
|
|
1492
1534
|
*
|
|
1493
1535
|
* For binary peers the ref is a MessagePack-compatible object
|
|
1494
|
-
* (`{ SerializedId, AckPeriod,
|
|
1536
|
+
* (`{ SerializedId, AckPeriod, AckAdvance, AllowReconnect }`);
|
|
1495
1537
|
* for text peers it is a comma-separated string.
|
|
1496
1538
|
*
|
|
1497
1539
|
* Can only be called once per stream.
|
|
@@ -1508,11 +1550,12 @@ var RpcStream = class _RpcStream {
|
|
|
1508
1550
|
const sender = new RpcStreamSender(
|
|
1509
1551
|
peer,
|
|
1510
1552
|
this.ackPeriod,
|
|
1511
|
-
this.
|
|
1553
|
+
this.ackAdvance,
|
|
1512
1554
|
this.allowReconnect,
|
|
1513
1555
|
this.isRealTime,
|
|
1514
1556
|
this.canSkipTo,
|
|
1515
|
-
isFactory
|
|
1557
|
+
isFactory,
|
|
1558
|
+
this.bufferSize
|
|
1516
1559
|
);
|
|
1517
1560
|
peer.sharedObjects.register(sender);
|
|
1518
1561
|
this._sender = sender;
|
|
@@ -1521,7 +1564,7 @@ var RpcStream = class _RpcStream {
|
|
|
1521
1564
|
this._toRefValue = peer.serializationFormat.isBinary ? {
|
|
1522
1565
|
SerializedId: [sender.id.hostId, sender.id.localId],
|
|
1523
1566
|
AckPeriod: sender.ackPeriod,
|
|
1524
|
-
|
|
1567
|
+
AckAdvance: sender.ackAdvance,
|
|
1525
1568
|
AllowReconnect: sender.allowReconnect
|
|
1526
1569
|
} : sender.toRef();
|
|
1527
1570
|
return this._toRefValue;
|
|
@@ -1836,19 +1879,17 @@ var RpcSystemCallHandler = class {
|
|
|
1836
1879
|
sender?.onAckEnd(args[0]);
|
|
1837
1880
|
break;
|
|
1838
1881
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
sharedObj.disconnect();
|
|
1851
|
-
}
|
|
1882
|
+
case RpcSystemCalls.disconnect: {
|
|
1883
|
+
const ids = args[0];
|
|
1884
|
+
if (Array.isArray(ids)) {
|
|
1885
|
+
for (const id of ids) {
|
|
1886
|
+
const remoteObj = peer.remoteObjects.get(id);
|
|
1887
|
+
if (remoteObj && typeof remoteObj.disconnect === "function") {
|
|
1888
|
+
remoteObj.disconnect();
|
|
1889
|
+
}
|
|
1890
|
+
const sharedObj = peer.sharedObjects.get(id);
|
|
1891
|
+
if (sharedObj && typeof sharedObj.disconnect === "function") {
|
|
1892
|
+
sharedObj.disconnect();
|
|
1852
1893
|
}
|
|
1853
1894
|
}
|
|
1854
1895
|
}
|
|
@@ -2245,6 +2286,9 @@ var RpcSerializationFormatResolver = class _RpcSerializationFormatResolver {
|
|
|
2245
2286
|
};
|
|
2246
2287
|
|
|
2247
2288
|
// src/rpc-peer.ts
|
|
2289
|
+
function yieldToEventLoop() {
|
|
2290
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
2291
|
+
}
|
|
2248
2292
|
var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
|
|
2249
2293
|
var HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
2250
2294
|
var KEEP_ALIVE_PERIOD_MS = 15e3;
|
|
@@ -2297,16 +2341,14 @@ var RpcPeer = class {
|
|
|
2297
2341
|
* entered only after the handshake has succeeded. */
|
|
2298
2342
|
connectionStateChanged = new import_core7.EventHandlerSet();
|
|
2299
2343
|
_connection;
|
|
2300
|
-
/** Mirror of `_connectionState === Connected
|
|
2301
|
-
* handshake round-trip completes
|
|
2302
|
-
*
|
|
2303
|
-
*
|
|
2304
|
-
*
|
|
2305
|
-
*
|
|
2306
|
-
* hub removed it mid-handshake. */
|
|
2344
|
+
/** Mirror of `_connectionState === Connected`. True only after the
|
|
2345
|
+
* handshake round-trip completes; outbound `call()` checks this to
|
|
2346
|
+
* decide between sending now and deferring until the next `Connected`
|
|
2347
|
+
* transition. Kept as its own field so it can stay false through the
|
|
2348
|
+
* Handshaking phase without exposing the run loop's `_connection`
|
|
2349
|
+
* bookkeeping. */
|
|
2307
2350
|
_isConnected = false;
|
|
2308
2351
|
_connectionState = 0 /* Disconnected */;
|
|
2309
|
-
_pendingSends = [];
|
|
2310
2352
|
_keepAliveTimer;
|
|
2311
2353
|
_keepAliveWatchdog;
|
|
2312
2354
|
/** Wall-clock time of the last inbound `$sys.KeepAlive`, or 0 if none yet
|
|
@@ -2333,11 +2375,11 @@ var RpcPeer = class {
|
|
|
2333
2375
|
if (this._connectionState === value) return;
|
|
2334
2376
|
const previousState = this._connectionState;
|
|
2335
2377
|
this._connectionState = value;
|
|
2336
|
-
if (value ===
|
|
2378
|
+
if (value === 3 /* Connected */) {
|
|
2337
2379
|
this._isConnected = true;
|
|
2338
2380
|
this._armKeepAliveWatchdog();
|
|
2339
2381
|
} else if (value === 0 /* Disconnected */) {
|
|
2340
|
-
if (previousState ===
|
|
2382
|
+
if (previousState === 3 /* Connected */)
|
|
2341
2383
|
this._isConnected = false;
|
|
2342
2384
|
this._disarmKeepAliveWatchdog();
|
|
2343
2385
|
}
|
|
@@ -2346,11 +2388,11 @@ var RpcPeer = class {
|
|
|
2346
2388
|
/** Resolves on the next transition into `Connected` — or immediately if
|
|
2347
2389
|
* already in that state. */
|
|
2348
2390
|
whenConnected() {
|
|
2349
|
-
if (this._connectionState ===
|
|
2391
|
+
if (this._connectionState === 3 /* Connected */)
|
|
2350
2392
|
return Promise.resolve();
|
|
2351
2393
|
return new Promise((resolve) => {
|
|
2352
2394
|
const handler = (state) => {
|
|
2353
|
-
if (state !==
|
|
2395
|
+
if (state !== 3 /* Connected */) return;
|
|
2354
2396
|
this.connectionStateChanged.remove(handler);
|
|
2355
2397
|
resolve();
|
|
2356
2398
|
};
|
|
@@ -2400,11 +2442,18 @@ var RpcPeer = class {
|
|
|
2400
2442
|
this._connection?.encoder,
|
|
2401
2443
|
this.hub.registry
|
|
2402
2444
|
);
|
|
2445
|
+
this.outboundCalls.register(outboundCall);
|
|
2403
2446
|
if (this._isConnected) {
|
|
2404
|
-
this.outboundCalls.register(outboundCall);
|
|
2405
2447
|
this._sendWireData(outboundCall.serializedWireData);
|
|
2406
2448
|
} else {
|
|
2407
|
-
|
|
2449
|
+
const stateHandler = (state) => {
|
|
2450
|
+
if (state !== 3 /* Connected */) return;
|
|
2451
|
+
this.connectionStateChanged.remove(stateHandler);
|
|
2452
|
+
if (outboundCall.result.isCompleted) return;
|
|
2453
|
+
this._sendWireData(outboundCall.serializedWireData);
|
|
2454
|
+
};
|
|
2455
|
+
this.connectionStateChanged.add(stateHandler);
|
|
2456
|
+
outboundCall.result.promise.then(() => this.connectionStateChanged.remove(stateHandler)).catch(() => this.connectionStateChanged.remove(stateHandler));
|
|
2408
2457
|
}
|
|
2409
2458
|
const signal = options?.signal;
|
|
2410
2459
|
if (signal !== void 0) {
|
|
@@ -2414,17 +2463,6 @@ var RpcPeer = class {
|
|
|
2414
2463
|
outboundCall.onDisconnect();
|
|
2415
2464
|
if (this._connection !== void 0)
|
|
2416
2465
|
this.hub.systemCallSender.cancel(this._connection, this.serializationFormat, callId);
|
|
2417
|
-
} else {
|
|
2418
|
-
const idx = this._pendingSends.findIndex(
|
|
2419
|
-
(c) => c.callId === callId
|
|
2420
|
-
);
|
|
2421
|
-
if (idx !== -1) {
|
|
2422
|
-
this._pendingSends.splice(idx, 1);
|
|
2423
|
-
outboundCall.result.reject(
|
|
2424
|
-
new Error("Call cancelled.")
|
|
2425
|
-
);
|
|
2426
|
-
outboundCall.onDisconnect();
|
|
2427
|
-
}
|
|
2428
2466
|
}
|
|
2429
2467
|
};
|
|
2430
2468
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
@@ -2455,12 +2493,6 @@ var RpcPeer = class {
|
|
|
2455
2493
|
infoLog?.log(`'${this.ref}': Stopping`);
|
|
2456
2494
|
this.remoteObjects.disconnectAll();
|
|
2457
2495
|
this.sharedObjects.disconnectAll();
|
|
2458
|
-
for (const call of this._pendingSends) {
|
|
2459
|
-
if (!call.result.isCompleted)
|
|
2460
|
-
call.result.reject(new Error("Peer closed."));
|
|
2461
|
-
call.onDisconnect();
|
|
2462
|
-
}
|
|
2463
|
-
this._pendingSends.length = 0;
|
|
2464
2496
|
this.outboundCalls.rejectAll(new Error("Peer closed."));
|
|
2465
2497
|
this.outboundCalls.invalidateAll();
|
|
2466
2498
|
this._connection?.close();
|
|
@@ -2468,16 +2500,6 @@ var RpcPeer = class {
|
|
|
2468
2500
|
this._setConnectionState(0 /* Disconnected */);
|
|
2469
2501
|
infoLog?.log(`'${this.ref}': Stopped`);
|
|
2470
2502
|
}
|
|
2471
|
-
/** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
|
|
2472
|
-
_flushPendingSends() {
|
|
2473
|
-
if (this._pendingSends.length === 0 || this._connection === void 0)
|
|
2474
|
-
return;
|
|
2475
|
-
for (const call of this._pendingSends) {
|
|
2476
|
-
this.outboundCalls.register(call);
|
|
2477
|
-
this._sendWireData(call.serializedWireData);
|
|
2478
|
-
}
|
|
2479
|
-
this._pendingSends.length = 0;
|
|
2480
|
-
}
|
|
2481
2503
|
/** Send pre-serialized wire data through the current connection. */
|
|
2482
2504
|
_sendWireData(data) {
|
|
2483
2505
|
if (this._connection === void 0) return;
|
|
@@ -2630,7 +2652,8 @@ var RpcPeer = class {
|
|
|
2630
2652
|
var RpcConnectionState = /* @__PURE__ */ ((RpcConnectionState2) => {
|
|
2631
2653
|
RpcConnectionState2[RpcConnectionState2["Disconnected"] = 0] = "Disconnected";
|
|
2632
2654
|
RpcConnectionState2[RpcConnectionState2["Connecting"] = 1] = "Connecting";
|
|
2633
|
-
RpcConnectionState2[RpcConnectionState2["
|
|
2655
|
+
RpcConnectionState2[RpcConnectionState2["Handshaking"] = 2] = "Handshaking";
|
|
2656
|
+
RpcConnectionState2[RpcConnectionState2["Connected"] = 3] = "Connected";
|
|
2634
2657
|
return RpcConnectionState2;
|
|
2635
2658
|
})(RpcConnectionState || {});
|
|
2636
2659
|
var RpcClientPeer = class extends RpcPeer {
|
|
@@ -2704,6 +2727,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2704
2727
|
connectWith(conn, isPeerChanged = true) {
|
|
2705
2728
|
this.setupConnection(conn);
|
|
2706
2729
|
this._isConnected = true;
|
|
2730
|
+
this.connectionStateChanged.trigger(3 /* Connected */);
|
|
2707
2731
|
void this._reconnect(isPeerChanged);
|
|
2708
2732
|
}
|
|
2709
2733
|
/** Kick off the reconnect loop. Idempotent — subsequent calls are
|
|
@@ -2765,6 +2789,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2765
2789
|
this._pendingHandshake = new import_core7.PromiseSource();
|
|
2766
2790
|
this.setupConnection(conn);
|
|
2767
2791
|
await Promise.race([conn.whenConnected, closedRejection]);
|
|
2792
|
+
this._setConnectionState(2 /* Handshaking */);
|
|
2768
2793
|
try {
|
|
2769
2794
|
this.hub.systemCallSender.handshake(
|
|
2770
2795
|
conn,
|
|
@@ -2816,7 +2841,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2816
2841
|
this._lastRemoteHubId = remoteHubId;
|
|
2817
2842
|
}
|
|
2818
2843
|
infoLog?.log(`'${this.ref}': Handshake succeeded, peerChanged=${isPeerChanged}`);
|
|
2819
|
-
this._setConnectionState(
|
|
2844
|
+
this._setConnectionState(3 /* Connected */);
|
|
2820
2845
|
this._tryIndex = 0;
|
|
2821
2846
|
await this._reconnect(isPeerChanged, closedController.signal);
|
|
2822
2847
|
await whenClosed.promise;
|
|
@@ -2891,6 +2916,8 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2891
2916
|
if (!isPeerChanged && eligible.length > 0) {
|
|
2892
2917
|
unknownIds = await this._reconcileReconnect(eligible, closedSignal);
|
|
2893
2918
|
}
|
|
2919
|
+
const YIELD_BATCH = 20;
|
|
2920
|
+
let resentSinceYield = 0;
|
|
2894
2921
|
for (const call of eligible) {
|
|
2895
2922
|
if (!call.removeOnOk && call.result.isCompleted) {
|
|
2896
2923
|
call.onDisconnect();
|
|
@@ -2901,8 +2928,12 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2901
2928
|
continue;
|
|
2902
2929
|
}
|
|
2903
2930
|
this._sendWireData(call.serializedWireData);
|
|
2931
|
+
resentSinceYield++;
|
|
2932
|
+
if (resentSinceYield >= YIELD_BATCH) {
|
|
2933
|
+
resentSinceYield = 0;
|
|
2934
|
+
await yieldToEventLoop();
|
|
2935
|
+
}
|
|
2904
2936
|
}
|
|
2905
|
-
this._flushPendingSends();
|
|
2906
2937
|
}
|
|
2907
2938
|
/**
|
|
2908
2939
|
* Ask the server which call IDs in `eligible` it no longer recognizes
|
|
@@ -2979,6 +3010,7 @@ var RpcServerPeer = class extends RpcPeer {
|
|
|
2979
3010
|
accept(conn) {
|
|
2980
3011
|
this._setConnectionState(1 /* Connecting */);
|
|
2981
3012
|
this.setupConnection(conn);
|
|
3013
|
+
this._setConnectionState(2 /* Handshaking */);
|
|
2982
3014
|
conn.closed.add(() => {
|
|
2983
3015
|
if (this._connection !== conn && this._connection !== void 0) return;
|
|
2984
3016
|
this.sharedObjects.disconnectAll();
|
|
@@ -2993,7 +3025,7 @@ var RpcServerPeer = class extends RpcPeer {
|
|
|
2993
3025
|
this.hub.hubId,
|
|
2994
3026
|
0
|
|
2995
3027
|
);
|
|
2996
|
-
this._setConnectionState(
|
|
3028
|
+
this._setConnectionState(3 /* Connected */);
|
|
2997
3029
|
}
|
|
2998
3030
|
}
|
|
2999
3031
|
};
|
|
@@ -3948,7 +3980,7 @@ var RpcPeerStateMonitor = class {
|
|
|
3948
3980
|
_timer;
|
|
3949
3981
|
// Arrow functions to preserve `this` when used as event handlers
|
|
3950
3982
|
_onConnectionStateChanged = (state) => {
|
|
3951
|
-
if (state ===
|
|
3983
|
+
if (state === 3 /* Connected */) {
|
|
3952
3984
|
this._rawConnected = true;
|
|
3953
3985
|
this._connectedAt = Date.now();
|
|
3954
3986
|
this._lastError = void 0;
|