@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.js
CHANGED
|
@@ -42,7 +42,8 @@ var RpcSystemCalls = {
|
|
|
42
42
|
ackEnd: "$sys.AckEnd:1",
|
|
43
43
|
item: "$sys.I:2",
|
|
44
44
|
batch: "$sys.B:2",
|
|
45
|
-
end: "$sys.End:2"
|
|
45
|
+
end: "$sys.End:2",
|
|
46
|
+
disconnect: "$sys.Disconnect:1"
|
|
46
47
|
};
|
|
47
48
|
var ENVELOPE_DELIMITER = "\n";
|
|
48
49
|
var ARG_DELIMITER = "";
|
|
@@ -870,7 +871,7 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
|
|
|
870
871
|
import { PromiseSource as PromiseSource3, RingBuffer } from "@actuallab/core";
|
|
871
872
|
var { warnLog: warnLog3 } = getLogs("RpcSharedStream");
|
|
872
873
|
var DEFAULT_ACK_PERIOD = 256;
|
|
873
|
-
var
|
|
874
|
+
var DEFAULT_ACK_ADVANCE = 128;
|
|
874
875
|
var RpcStreamSender = class _RpcStreamSender {
|
|
875
876
|
static _emptyGuid = "00000000-0000-0000-0000-000000000000";
|
|
876
877
|
id;
|
|
@@ -880,6 +881,18 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
880
881
|
canSkipTo;
|
|
881
882
|
peer;
|
|
882
883
|
ackPeriod;
|
|
884
|
+
/**
|
|
885
|
+
* Wire-level flow-control window: the maximum index the sender may
|
|
886
|
+
* advance past the most recently acknowledged index. Mirrors .NET
|
|
887
|
+
* `RpcStream.AckAdvance`.
|
|
888
|
+
*/
|
|
889
|
+
ackAdvance;
|
|
890
|
+
/**
|
|
891
|
+
* Effective local ring buffer capacity used by the pump. Set larger
|
|
892
|
+
* than `ackAdvance` to pre-buffer items beyond the in-flight window;
|
|
893
|
+
* values below `ackAdvance` are clamped up (with a warning) at
|
|
894
|
+
* construction time. Not transmitted on the wire.
|
|
895
|
+
*/
|
|
883
896
|
bufferSize;
|
|
884
897
|
/**
|
|
885
898
|
* If true, the source was produced by a factory `(abortSignal) => AsyncIterable<T>`
|
|
@@ -908,6 +921,13 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
908
921
|
* watchdog so it can distinguish "stuck" (no ACK > N s) from
|
|
909
922
|
* "throttled" (ACKs flowing). */
|
|
910
923
|
onAckProcessed;
|
|
924
|
+
/** Fires after each item is pushed onto the local ring buffer. The
|
|
925
|
+
* argument is the buffer count *after* the push. Together with
|
|
926
|
+
* `onAckProcessed` (which is the only place items leave the buffer),
|
|
927
|
+
* this gives controllers a complete picture of buffer utilization.
|
|
928
|
+
* When `bufferedCount === bufferSize`, the source pull is paused
|
|
929
|
+
* until the next ACK frees space. Listener errors are swallowed. */
|
|
930
|
+
onBuffered;
|
|
911
931
|
get nextIndex() {
|
|
912
932
|
return this._nextIndex;
|
|
913
933
|
}
|
|
@@ -920,7 +940,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
920
940
|
// -- ACK queue (analog of .NET's Channel<(long, bool)>) --
|
|
921
941
|
_acks = [];
|
|
922
942
|
_whenAckReady = null;
|
|
923
|
-
constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD,
|
|
943
|
+
constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true, isRealTime = false, canSkipTo = () => true, sourceUsesAbortSignal = false, bufferSize) {
|
|
924
944
|
const localId = peer.sharedObjects.nextId();
|
|
925
945
|
this.id = { hostId: peer.hub.hubId, localId };
|
|
926
946
|
this.allowReconnect = allowReconnect;
|
|
@@ -928,8 +948,13 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
928
948
|
this.canSkipTo = canSkipTo;
|
|
929
949
|
this.peer = peer;
|
|
930
950
|
this.ackPeriod = ackPeriod;
|
|
931
|
-
this.
|
|
951
|
+
this.ackAdvance = ackAdvance;
|
|
932
952
|
this.sourceUsesAbortSignal = sourceUsesAbortSignal;
|
|
953
|
+
if (bufferSize !== void 0 && bufferSize !== 0 && bufferSize < ackAdvance)
|
|
954
|
+
warnLog3?.log(
|
|
955
|
+
`RpcStream bufferSize (${bufferSize}) is below ackAdvance (${ackAdvance}); using ackAdvance as buffer size.`
|
|
956
|
+
);
|
|
957
|
+
this.bufferSize = bufferSize !== void 0 && bufferSize >= ackAdvance ? bufferSize : ackAdvance;
|
|
933
958
|
}
|
|
934
959
|
/** AbortSignal that is aborted when the sender is disconnected. */
|
|
935
960
|
get abortSignal() {
|
|
@@ -937,7 +962,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
937
962
|
}
|
|
938
963
|
/** Returns the stream reference string for the $sys.Ok response. */
|
|
939
964
|
toRef() {
|
|
940
|
-
return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.
|
|
965
|
+
return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"},${this.isRealTime ? "1" : "0"}`;
|
|
941
966
|
}
|
|
942
967
|
/**
|
|
943
968
|
* Called by system call handler when $sys.Ack is received from the client.
|
|
@@ -1033,8 +1058,10 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1033
1058
|
}
|
|
1034
1059
|
/**
|
|
1035
1060
|
* ACK-driven pump. Non-real-time streams apply normal backpressure at
|
|
1036
|
-
* `
|
|
1061
|
+
* `ackAdvance`; real-time streams may compact the already-buffered unsent
|
|
1037
1062
|
* suffix to the latest buffered `canSkipTo` item after the consumer ACKs.
|
|
1063
|
+
* With `bufferSize > ackAdvance` the local ring buffer holds more than the
|
|
1064
|
+
* in-flight window — real-time mode uses the extra space to pre-buffer.
|
|
1038
1065
|
*/
|
|
1039
1066
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition -- _ended changes across awaits */
|
|
1040
1067
|
async _run(iterator, state) {
|
|
@@ -1056,6 +1083,12 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1056
1083
|
Promise.resolve(pending)
|
|
1057
1084
|
]);
|
|
1058
1085
|
};
|
|
1086
|
+
const fireBuffered = () => {
|
|
1087
|
+
try {
|
|
1088
|
+
this.onBuffered?.(buffer.count);
|
|
1089
|
+
} catch {
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1059
1092
|
const bufferNext = async (onlyIfReady, prefetchNext) => {
|
|
1060
1093
|
let r;
|
|
1061
1094
|
try {
|
|
@@ -1073,6 +1106,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1073
1106
|
if (prefetchNext)
|
|
1074
1107
|
whenMovedNext = iterator.next();
|
|
1075
1108
|
}
|
|
1109
|
+
fireBuffered();
|
|
1076
1110
|
return true;
|
|
1077
1111
|
} catch (e) {
|
|
1078
1112
|
whenMovedNext = null;
|
|
@@ -1082,6 +1116,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1082
1116
|
kind: "error",
|
|
1083
1117
|
error: e instanceof Error ? e : new Error(String(e))
|
|
1084
1118
|
});
|
|
1119
|
+
fireBuffered();
|
|
1085
1120
|
return true;
|
|
1086
1121
|
}
|
|
1087
1122
|
};
|
|
@@ -1126,6 +1161,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1126
1161
|
};
|
|
1127
1162
|
}
|
|
1128
1163
|
buffer.pushTail(item);
|
|
1164
|
+
fireBuffered();
|
|
1129
1165
|
if (accepted || isFullyBuffered) break;
|
|
1130
1166
|
}
|
|
1131
1167
|
}
|
|
@@ -1140,7 +1176,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1140
1176
|
return;
|
|
1141
1177
|
}
|
|
1142
1178
|
let bufferIndex = this._nextIndex - bufferStart;
|
|
1143
|
-
const maxIndex = ack.nextIndex + this.
|
|
1179
|
+
const maxIndex = ack.nextIndex + this.ackAdvance;
|
|
1144
1180
|
while (this._nextIndex < maxIndex) {
|
|
1145
1181
|
if (this._ended) return;
|
|
1146
1182
|
if (isRealTime) {
|
|
@@ -1274,7 +1310,7 @@ function _compactBufferedUnsentSuffix(buffer, firstUnsentIndex, canSkipTo) {
|
|
|
1274
1310
|
// src/rpc-stream.ts
|
|
1275
1311
|
var { warnLog: warnLog4 } = getLogs("RpcStream");
|
|
1276
1312
|
var DEFAULT_ACK_PERIOD2 = 30;
|
|
1277
|
-
var
|
|
1313
|
+
var DEFAULT_ACK_ADVANCE2 = 61;
|
|
1278
1314
|
function parseStreamRef(value) {
|
|
1279
1315
|
if (typeof value === "string") {
|
|
1280
1316
|
const parts = value.split(",");
|
|
@@ -1282,12 +1318,12 @@ function parseStreamRef(value) {
|
|
|
1282
1318
|
const hostId = parts[0];
|
|
1283
1319
|
const localId = parseInt(parts[1], 10);
|
|
1284
1320
|
const ackPeriod = parseInt(parts[2], 10);
|
|
1285
|
-
const
|
|
1286
|
-
if (isNaN(localId) || isNaN(ackPeriod) || isNaN(
|
|
1321
|
+
const ackAdvance = parseInt(parts[3], 10);
|
|
1322
|
+
if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance))
|
|
1287
1323
|
return null;
|
|
1288
1324
|
const allowReconnect = parts.length < 5 || parts[4] !== "0";
|
|
1289
1325
|
const isRealTime = parts.length >= 6 && parts[5] === "1";
|
|
1290
|
-
return { hostId, localId, ackPeriod,
|
|
1326
|
+
return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
|
|
1291
1327
|
}
|
|
1292
1328
|
if (typeof value === "object" && value !== null) {
|
|
1293
1329
|
const obj = value;
|
|
@@ -1298,10 +1334,10 @@ function parseStreamRef(value) {
|
|
|
1298
1334
|
const hostId = String(rawHostId);
|
|
1299
1335
|
const localId = Number(serializedId[1]);
|
|
1300
1336
|
const ackPeriod = Number(obj.AckPeriod ?? 256);
|
|
1301
|
-
const
|
|
1337
|
+
const ackAdvance = Number(obj.AckAdvance ?? 128);
|
|
1302
1338
|
const allowReconnect = obj.AllowReconnect !== false;
|
|
1303
1339
|
const isRealTime = obj.IsRealTime === true;
|
|
1304
|
-
return { hostId, localId, ackPeriod,
|
|
1340
|
+
return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
|
|
1305
1341
|
}
|
|
1306
1342
|
return null;
|
|
1307
1343
|
}
|
|
@@ -1321,6 +1357,11 @@ var RpcStream = class _RpcStream {
|
|
|
1321
1357
|
isRealTime;
|
|
1322
1358
|
canSkipTo;
|
|
1323
1359
|
ackPeriod;
|
|
1360
|
+
ackAdvance;
|
|
1361
|
+
/**
|
|
1362
|
+
* Local-only ring buffer capacity hint for the sender. Undefined means
|
|
1363
|
+
* "use ackAdvance as the buffer size". Not part of the wire ref.
|
|
1364
|
+
*/
|
|
1324
1365
|
bufferSize;
|
|
1325
1366
|
// Local (origin) mode
|
|
1326
1367
|
localSource;
|
|
@@ -1351,7 +1392,8 @@ var RpcStream = class _RpcStream {
|
|
|
1351
1392
|
this.isRealTime = options.isRealTime ?? false;
|
|
1352
1393
|
this.canSkipTo = options.canSkipTo ?? (() => true);
|
|
1353
1394
|
this.ackPeriod = options.ackPeriod ?? DEFAULT_ACK_PERIOD2;
|
|
1354
|
-
this.
|
|
1395
|
+
this.ackAdvance = options.ackAdvance ?? DEFAULT_ACK_ADVANCE2;
|
|
1396
|
+
this.bufferSize = options.bufferSize;
|
|
1355
1397
|
} else {
|
|
1356
1398
|
const ref = sourceOrRef;
|
|
1357
1399
|
const peer = optionsOrPeer;
|
|
@@ -1362,7 +1404,7 @@ var RpcStream = class _RpcStream {
|
|
|
1362
1404
|
this.isRealTime = ref.isRealTime;
|
|
1363
1405
|
this.canSkipTo = () => true;
|
|
1364
1406
|
this.ackPeriod = ref.ackPeriod;
|
|
1365
|
-
this.
|
|
1407
|
+
this.ackAdvance = ref.ackAdvance;
|
|
1366
1408
|
}
|
|
1367
1409
|
}
|
|
1368
1410
|
/**
|
|
@@ -1385,7 +1427,7 @@ var RpcStream = class _RpcStream {
|
|
|
1385
1427
|
* stream reference.
|
|
1386
1428
|
*
|
|
1387
1429
|
* For binary peers the ref is a MessagePack-compatible object
|
|
1388
|
-
* (`{ SerializedId, AckPeriod,
|
|
1430
|
+
* (`{ SerializedId, AckPeriod, AckAdvance, AllowReconnect }`);
|
|
1389
1431
|
* for text peers it is a comma-separated string.
|
|
1390
1432
|
*
|
|
1391
1433
|
* Can only be called once per stream.
|
|
@@ -1402,11 +1444,12 @@ var RpcStream = class _RpcStream {
|
|
|
1402
1444
|
const sender = new RpcStreamSender(
|
|
1403
1445
|
peer,
|
|
1404
1446
|
this.ackPeriod,
|
|
1405
|
-
this.
|
|
1447
|
+
this.ackAdvance,
|
|
1406
1448
|
this.allowReconnect,
|
|
1407
1449
|
this.isRealTime,
|
|
1408
1450
|
this.canSkipTo,
|
|
1409
|
-
isFactory
|
|
1451
|
+
isFactory,
|
|
1452
|
+
this.bufferSize
|
|
1410
1453
|
);
|
|
1411
1454
|
peer.sharedObjects.register(sender);
|
|
1412
1455
|
this._sender = sender;
|
|
@@ -1415,7 +1458,7 @@ var RpcStream = class _RpcStream {
|
|
|
1415
1458
|
this._toRefValue = peer.serializationFormat.isBinary ? {
|
|
1416
1459
|
SerializedId: [sender.id.hostId, sender.id.localId],
|
|
1417
1460
|
AckPeriod: sender.ackPeriod,
|
|
1418
|
-
|
|
1461
|
+
AckAdvance: sender.ackAdvance,
|
|
1419
1462
|
AllowReconnect: sender.allowReconnect
|
|
1420
1463
|
} : sender.toRef();
|
|
1421
1464
|
return this._toRefValue;
|
|
@@ -1730,19 +1773,17 @@ var RpcSystemCallHandler = class {
|
|
|
1730
1773
|
sender?.onAckEnd(args[0]);
|
|
1731
1774
|
break;
|
|
1732
1775
|
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
sharedObj.disconnect();
|
|
1745
|
-
}
|
|
1776
|
+
case RpcSystemCalls.disconnect: {
|
|
1777
|
+
const ids = args[0];
|
|
1778
|
+
if (Array.isArray(ids)) {
|
|
1779
|
+
for (const id of ids) {
|
|
1780
|
+
const remoteObj = peer.remoteObjects.get(id);
|
|
1781
|
+
if (remoteObj && typeof remoteObj.disconnect === "function") {
|
|
1782
|
+
remoteObj.disconnect();
|
|
1783
|
+
}
|
|
1784
|
+
const sharedObj = peer.sharedObjects.get(id);
|
|
1785
|
+
if (sharedObj && typeof sharedObj.disconnect === "function") {
|
|
1786
|
+
sharedObj.disconnect();
|
|
1746
1787
|
}
|
|
1747
1788
|
}
|
|
1748
1789
|
}
|
|
@@ -2139,6 +2180,9 @@ var RpcSerializationFormatResolver = class _RpcSerializationFormatResolver {
|
|
|
2139
2180
|
};
|
|
2140
2181
|
|
|
2141
2182
|
// src/rpc-peer.ts
|
|
2183
|
+
function yieldToEventLoop() {
|
|
2184
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
2185
|
+
}
|
|
2142
2186
|
var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
|
|
2143
2187
|
var HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
2144
2188
|
var KEEP_ALIVE_PERIOD_MS = 15e3;
|
|
@@ -2191,16 +2235,14 @@ var RpcPeer = class {
|
|
|
2191
2235
|
* entered only after the handshake has succeeded. */
|
|
2192
2236
|
connectionStateChanged = new EventHandlerSet3();
|
|
2193
2237
|
_connection;
|
|
2194
|
-
/** Mirror of `_connectionState === Connected
|
|
2195
|
-
* handshake round-trip completes
|
|
2196
|
-
*
|
|
2197
|
-
*
|
|
2198
|
-
*
|
|
2199
|
-
*
|
|
2200
|
-
* hub removed it mid-handshake. */
|
|
2238
|
+
/** Mirror of `_connectionState === Connected`. True only after the
|
|
2239
|
+
* handshake round-trip completes; outbound `call()` checks this to
|
|
2240
|
+
* decide between sending now and deferring until the next `Connected`
|
|
2241
|
+
* transition. Kept as its own field so it can stay false through the
|
|
2242
|
+
* Handshaking phase without exposing the run loop's `_connection`
|
|
2243
|
+
* bookkeeping. */
|
|
2201
2244
|
_isConnected = false;
|
|
2202
2245
|
_connectionState = 0 /* Disconnected */;
|
|
2203
|
-
_pendingSends = [];
|
|
2204
2246
|
_keepAliveTimer;
|
|
2205
2247
|
_keepAliveWatchdog;
|
|
2206
2248
|
/** Wall-clock time of the last inbound `$sys.KeepAlive`, or 0 if none yet
|
|
@@ -2227,11 +2269,11 @@ var RpcPeer = class {
|
|
|
2227
2269
|
if (this._connectionState === value) return;
|
|
2228
2270
|
const previousState = this._connectionState;
|
|
2229
2271
|
this._connectionState = value;
|
|
2230
|
-
if (value ===
|
|
2272
|
+
if (value === 3 /* Connected */) {
|
|
2231
2273
|
this._isConnected = true;
|
|
2232
2274
|
this._armKeepAliveWatchdog();
|
|
2233
2275
|
} else if (value === 0 /* Disconnected */) {
|
|
2234
|
-
if (previousState ===
|
|
2276
|
+
if (previousState === 3 /* Connected */)
|
|
2235
2277
|
this._isConnected = false;
|
|
2236
2278
|
this._disarmKeepAliveWatchdog();
|
|
2237
2279
|
}
|
|
@@ -2240,11 +2282,11 @@ var RpcPeer = class {
|
|
|
2240
2282
|
/** Resolves on the next transition into `Connected` — or immediately if
|
|
2241
2283
|
* already in that state. */
|
|
2242
2284
|
whenConnected() {
|
|
2243
|
-
if (this._connectionState ===
|
|
2285
|
+
if (this._connectionState === 3 /* Connected */)
|
|
2244
2286
|
return Promise.resolve();
|
|
2245
2287
|
return new Promise((resolve) => {
|
|
2246
2288
|
const handler = (state) => {
|
|
2247
|
-
if (state !==
|
|
2289
|
+
if (state !== 3 /* Connected */) return;
|
|
2248
2290
|
this.connectionStateChanged.remove(handler);
|
|
2249
2291
|
resolve();
|
|
2250
2292
|
};
|
|
@@ -2294,11 +2336,18 @@ var RpcPeer = class {
|
|
|
2294
2336
|
this._connection?.encoder,
|
|
2295
2337
|
this.hub.registry
|
|
2296
2338
|
);
|
|
2339
|
+
this.outboundCalls.register(outboundCall);
|
|
2297
2340
|
if (this._isConnected) {
|
|
2298
|
-
this.outboundCalls.register(outboundCall);
|
|
2299
2341
|
this._sendWireData(outboundCall.serializedWireData);
|
|
2300
2342
|
} else {
|
|
2301
|
-
|
|
2343
|
+
const stateHandler = (state) => {
|
|
2344
|
+
if (state !== 3 /* Connected */) return;
|
|
2345
|
+
this.connectionStateChanged.remove(stateHandler);
|
|
2346
|
+
if (outboundCall.result.isCompleted) return;
|
|
2347
|
+
this._sendWireData(outboundCall.serializedWireData);
|
|
2348
|
+
};
|
|
2349
|
+
this.connectionStateChanged.add(stateHandler);
|
|
2350
|
+
outboundCall.result.promise.then(() => this.connectionStateChanged.remove(stateHandler)).catch(() => this.connectionStateChanged.remove(stateHandler));
|
|
2302
2351
|
}
|
|
2303
2352
|
const signal = options?.signal;
|
|
2304
2353
|
if (signal !== void 0) {
|
|
@@ -2308,17 +2357,6 @@ var RpcPeer = class {
|
|
|
2308
2357
|
outboundCall.onDisconnect();
|
|
2309
2358
|
if (this._connection !== void 0)
|
|
2310
2359
|
this.hub.systemCallSender.cancel(this._connection, this.serializationFormat, callId);
|
|
2311
|
-
} else {
|
|
2312
|
-
const idx = this._pendingSends.findIndex(
|
|
2313
|
-
(c) => c.callId === callId
|
|
2314
|
-
);
|
|
2315
|
-
if (idx !== -1) {
|
|
2316
|
-
this._pendingSends.splice(idx, 1);
|
|
2317
|
-
outboundCall.result.reject(
|
|
2318
|
-
new Error("Call cancelled.")
|
|
2319
|
-
);
|
|
2320
|
-
outboundCall.onDisconnect();
|
|
2321
|
-
}
|
|
2322
2360
|
}
|
|
2323
2361
|
};
|
|
2324
2362
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
@@ -2349,12 +2387,6 @@ var RpcPeer = class {
|
|
|
2349
2387
|
infoLog?.log(`'${this.ref}': Stopping`);
|
|
2350
2388
|
this.remoteObjects.disconnectAll();
|
|
2351
2389
|
this.sharedObjects.disconnectAll();
|
|
2352
|
-
for (const call of this._pendingSends) {
|
|
2353
|
-
if (!call.result.isCompleted)
|
|
2354
|
-
call.result.reject(new Error("Peer closed."));
|
|
2355
|
-
call.onDisconnect();
|
|
2356
|
-
}
|
|
2357
|
-
this._pendingSends.length = 0;
|
|
2358
2390
|
this.outboundCalls.rejectAll(new Error("Peer closed."));
|
|
2359
2391
|
this.outboundCalls.invalidateAll();
|
|
2360
2392
|
this._connection?.close();
|
|
@@ -2362,16 +2394,6 @@ var RpcPeer = class {
|
|
|
2362
2394
|
this._setConnectionState(0 /* Disconnected */);
|
|
2363
2395
|
infoLog?.log(`'${this.ref}': Stopped`);
|
|
2364
2396
|
}
|
|
2365
|
-
/** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
|
|
2366
|
-
_flushPendingSends() {
|
|
2367
|
-
if (this._pendingSends.length === 0 || this._connection === void 0)
|
|
2368
|
-
return;
|
|
2369
|
-
for (const call of this._pendingSends) {
|
|
2370
|
-
this.outboundCalls.register(call);
|
|
2371
|
-
this._sendWireData(call.serializedWireData);
|
|
2372
|
-
}
|
|
2373
|
-
this._pendingSends.length = 0;
|
|
2374
|
-
}
|
|
2375
2397
|
/** Send pre-serialized wire data through the current connection. */
|
|
2376
2398
|
_sendWireData(data) {
|
|
2377
2399
|
if (this._connection === void 0) return;
|
|
@@ -2524,7 +2546,8 @@ var RpcPeer = class {
|
|
|
2524
2546
|
var RpcConnectionState = /* @__PURE__ */ ((RpcConnectionState2) => {
|
|
2525
2547
|
RpcConnectionState2[RpcConnectionState2["Disconnected"] = 0] = "Disconnected";
|
|
2526
2548
|
RpcConnectionState2[RpcConnectionState2["Connecting"] = 1] = "Connecting";
|
|
2527
|
-
RpcConnectionState2[RpcConnectionState2["
|
|
2549
|
+
RpcConnectionState2[RpcConnectionState2["Handshaking"] = 2] = "Handshaking";
|
|
2550
|
+
RpcConnectionState2[RpcConnectionState2["Connected"] = 3] = "Connected";
|
|
2528
2551
|
return RpcConnectionState2;
|
|
2529
2552
|
})(RpcConnectionState || {});
|
|
2530
2553
|
var RpcClientPeer = class extends RpcPeer {
|
|
@@ -2598,6 +2621,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2598
2621
|
connectWith(conn, isPeerChanged = true) {
|
|
2599
2622
|
this.setupConnection(conn);
|
|
2600
2623
|
this._isConnected = true;
|
|
2624
|
+
this.connectionStateChanged.trigger(3 /* Connected */);
|
|
2601
2625
|
void this._reconnect(isPeerChanged);
|
|
2602
2626
|
}
|
|
2603
2627
|
/** Kick off the reconnect loop. Idempotent — subsequent calls are
|
|
@@ -2659,6 +2683,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2659
2683
|
this._pendingHandshake = new PromiseSource5();
|
|
2660
2684
|
this.setupConnection(conn);
|
|
2661
2685
|
await Promise.race([conn.whenConnected, closedRejection]);
|
|
2686
|
+
this._setConnectionState(2 /* Handshaking */);
|
|
2662
2687
|
try {
|
|
2663
2688
|
this.hub.systemCallSender.handshake(
|
|
2664
2689
|
conn,
|
|
@@ -2710,7 +2735,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2710
2735
|
this._lastRemoteHubId = remoteHubId;
|
|
2711
2736
|
}
|
|
2712
2737
|
infoLog?.log(`'${this.ref}': Handshake succeeded, peerChanged=${isPeerChanged}`);
|
|
2713
|
-
this._setConnectionState(
|
|
2738
|
+
this._setConnectionState(3 /* Connected */);
|
|
2714
2739
|
this._tryIndex = 0;
|
|
2715
2740
|
await this._reconnect(isPeerChanged, closedController.signal);
|
|
2716
2741
|
await whenClosed.promise;
|
|
@@ -2785,6 +2810,8 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2785
2810
|
if (!isPeerChanged && eligible.length > 0) {
|
|
2786
2811
|
unknownIds = await this._reconcileReconnect(eligible, closedSignal);
|
|
2787
2812
|
}
|
|
2813
|
+
const YIELD_BATCH = 20;
|
|
2814
|
+
let resentSinceYield = 0;
|
|
2788
2815
|
for (const call of eligible) {
|
|
2789
2816
|
if (!call.removeOnOk && call.result.isCompleted) {
|
|
2790
2817
|
call.onDisconnect();
|
|
@@ -2795,8 +2822,12 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2795
2822
|
continue;
|
|
2796
2823
|
}
|
|
2797
2824
|
this._sendWireData(call.serializedWireData);
|
|
2825
|
+
resentSinceYield++;
|
|
2826
|
+
if (resentSinceYield >= YIELD_BATCH) {
|
|
2827
|
+
resentSinceYield = 0;
|
|
2828
|
+
await yieldToEventLoop();
|
|
2829
|
+
}
|
|
2798
2830
|
}
|
|
2799
|
-
this._flushPendingSends();
|
|
2800
2831
|
}
|
|
2801
2832
|
/**
|
|
2802
2833
|
* Ask the server which call IDs in `eligible` it no longer recognizes
|
|
@@ -2873,6 +2904,7 @@ var RpcServerPeer = class extends RpcPeer {
|
|
|
2873
2904
|
accept(conn) {
|
|
2874
2905
|
this._setConnectionState(1 /* Connecting */);
|
|
2875
2906
|
this.setupConnection(conn);
|
|
2907
|
+
this._setConnectionState(2 /* Handshaking */);
|
|
2876
2908
|
conn.closed.add(() => {
|
|
2877
2909
|
if (this._connection !== conn && this._connection !== void 0) return;
|
|
2878
2910
|
this.sharedObjects.disconnectAll();
|
|
@@ -2887,7 +2919,7 @@ var RpcServerPeer = class extends RpcPeer {
|
|
|
2887
2919
|
this.hub.hubId,
|
|
2888
2920
|
0
|
|
2889
2921
|
);
|
|
2890
|
-
this._setConnectionState(
|
|
2922
|
+
this._setConnectionState(3 /* Connected */);
|
|
2891
2923
|
}
|
|
2892
2924
|
}
|
|
2893
2925
|
};
|
|
@@ -3842,7 +3874,7 @@ var RpcPeerStateMonitor = class {
|
|
|
3842
3874
|
_timer;
|
|
3843
3875
|
// Arrow functions to preserve `this` when used as event handlers
|
|
3844
3876
|
_onConnectionStateChanged = (state) => {
|
|
3845
|
-
if (state ===
|
|
3877
|
+
if (state === 3 /* Connected */) {
|
|
3846
3878
|
this._rawConnected = true;
|
|
3847
3879
|
this._connectedAt = Date.now();
|
|
3848
3880
|
this._lastError = void 0;
|