@actuallab/rpc 12.3.29 → 12.3.33
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 +152 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +122 -49
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -80,6 +80,7 @@ __export(index_exports, {
|
|
|
80
80
|
deserializeBinaryMessage: () => deserializeBinaryMessage,
|
|
81
81
|
deserializeCompactBinaryMessage: () => deserializeCompactBinaryMessage,
|
|
82
82
|
deserializeMessage: () => deserializeMessage,
|
|
83
|
+
getLogs: () => getLogs,
|
|
83
84
|
getMethodsMeta: () => getMethodsMeta,
|
|
84
85
|
getServiceMeta: () => getServiceMeta,
|
|
85
86
|
getStateDescription: () => getStateDescription,
|
|
@@ -103,6 +104,33 @@ __export(index_exports, {
|
|
|
103
104
|
});
|
|
104
105
|
module.exports = __toCommonJS(index_exports);
|
|
105
106
|
|
|
107
|
+
// src/logging.ts
|
|
108
|
+
var import_core = require("@actuallab/core");
|
|
109
|
+
var scopeDefaults = {
|
|
110
|
+
RpcCallTracker: import_core.LogLevel.Warn,
|
|
111
|
+
RpcClient: import_core.LogLevel.Warn,
|
|
112
|
+
RpcClientPeerReconnectDelayer: import_core.LogLevel.Warn,
|
|
113
|
+
RpcConnection: import_core.LogLevel.Warn,
|
|
114
|
+
RpcHub: import_core.LogLevel.Warn,
|
|
115
|
+
RpcInterceptor: import_core.LogLevel.Warn,
|
|
116
|
+
RpcMessageChannelConnection: import_core.LogLevel.Warn,
|
|
117
|
+
RpcMethodRegistry: import_core.LogLevel.Warn,
|
|
118
|
+
RpcOutboundCall: import_core.LogLevel.Warn,
|
|
119
|
+
RpcPeer: import_core.LogLevel.Info,
|
|
120
|
+
RpcPeerStateMonitor: import_core.LogLevel.Warn,
|
|
121
|
+
RpcRemoteObjectTracker: import_core.LogLevel.Warn,
|
|
122
|
+
RpcSerialization: import_core.LogLevel.Warn,
|
|
123
|
+
RpcServiceHost: import_core.LogLevel.Warn,
|
|
124
|
+
RpcSharedObjectTracker: import_core.LogLevel.Warn,
|
|
125
|
+
RpcSharedStream: import_core.LogLevel.Warn,
|
|
126
|
+
RpcStream: import_core.LogLevel.Warn,
|
|
127
|
+
RpcStreamSender: import_core.LogLevel.Warn,
|
|
128
|
+
RpcSystemCallHandler: import_core.LogLevel.Warn,
|
|
129
|
+
RpcSystemCallSender: import_core.LogLevel.Warn,
|
|
130
|
+
RpcWebSocketClient: import_core.LogLevel.Warn
|
|
131
|
+
};
|
|
132
|
+
var getLogs = (0, import_core.createLogProvider)("rpc.", scopeDefaults);
|
|
133
|
+
|
|
106
134
|
// src/rpc-message.ts
|
|
107
135
|
var RpcCallTypeId = /* @__PURE__ */ ((RpcCallTypeId2) => {
|
|
108
136
|
RpcCallTypeId2[RpcCallTypeId2["Regular"] = 0] = "Regular";
|
|
@@ -164,6 +192,7 @@ function patchMsgpackEncoderForMaps() {
|
|
|
164
192
|
patchMsgpackEncoderForMaps();
|
|
165
193
|
|
|
166
194
|
// src/rpc-serialization.ts
|
|
195
|
+
var { warnLog } = getLogs("RpcSerialization");
|
|
167
196
|
function serializeMessage(message, args) {
|
|
168
197
|
const envelope = JSON.stringify(message);
|
|
169
198
|
if (args === void 0 || args.length === 0) {
|
|
@@ -193,9 +222,7 @@ function deserializeMessage(raw) {
|
|
|
193
222
|
try {
|
|
194
223
|
return JSON.parse(s);
|
|
195
224
|
} catch {
|
|
196
|
-
|
|
197
|
-
`[RpcSerialization] failed to parse arg as JSON: ${s.substring(0, 100)}`
|
|
198
|
-
);
|
|
225
|
+
warnLog?.log(`failed to parse arg as JSON: ${s.substring(0, 100)}`);
|
|
199
226
|
return s;
|
|
200
227
|
}
|
|
201
228
|
});
|
|
@@ -450,7 +477,8 @@ function splitCompactBinaryFrame(frame, registry, decoder = defaultBinaryDecoder
|
|
|
450
477
|
|
|
451
478
|
// src/rpc-connection.ts
|
|
452
479
|
var import_msgpack3 = require("@msgpack/msgpack");
|
|
453
|
-
var
|
|
480
|
+
var import_core2 = require("@actuallab/core");
|
|
481
|
+
var { warnLog: warnLog2 } = getLogs("RpcConnection");
|
|
454
482
|
var WebSocketState = {
|
|
455
483
|
CONNECTING: 0,
|
|
456
484
|
OPEN: 1,
|
|
@@ -460,7 +488,7 @@ var WebSocketState = {
|
|
|
460
488
|
var RpcWebSocketConnection = class {
|
|
461
489
|
_ws;
|
|
462
490
|
_sendBuffer = [];
|
|
463
|
-
_connected = new
|
|
491
|
+
_connected = new import_core2.PromiseSource();
|
|
464
492
|
/** Per-connection msgpack encoder — reused across outbound messages to
|
|
465
493
|
* amortise construction cost and to keep the internal write buffer at
|
|
466
494
|
* its largest observed size (avoids repeated `resizeBuffer` growth on
|
|
@@ -481,9 +509,9 @@ var RpcWebSocketConnection = class {
|
|
|
481
509
|
_format;
|
|
482
510
|
_methodRegistry;
|
|
483
511
|
binaryMode;
|
|
484
|
-
messageReceived = new
|
|
485
|
-
closed = new
|
|
486
|
-
error = new
|
|
512
|
+
messageReceived = new import_core2.EventHandlerSet();
|
|
513
|
+
closed = new import_core2.EventHandlerSet();
|
|
514
|
+
error = new import_core2.EventHandlerSet();
|
|
487
515
|
constructor(ws, binaryMode = false, format, methodRegistry) {
|
|
488
516
|
this._ws = ws;
|
|
489
517
|
this.binaryMode = binaryMode;
|
|
@@ -512,6 +540,7 @@ var RpcWebSocketConnection = class {
|
|
|
512
540
|
});
|
|
513
541
|
}
|
|
514
542
|
} catch (e) {
|
|
543
|
+
warnLog2?.log("Failed to split binary frame:", e);
|
|
515
544
|
this.error.trigger(e);
|
|
516
545
|
}
|
|
517
546
|
} else if (typeof Blob !== "undefined" && ev.data instanceof Blob && this.binaryMode) {
|
|
@@ -527,6 +556,7 @@ var RpcWebSocketConnection = class {
|
|
|
527
556
|
});
|
|
528
557
|
}
|
|
529
558
|
} catch (e) {
|
|
559
|
+
warnLog2?.log("Failed to split binary blob frame:", e);
|
|
530
560
|
this.error.trigger(e);
|
|
531
561
|
}
|
|
532
562
|
});
|
|
@@ -602,13 +632,13 @@ var RpcWebSocketConnection = class {
|
|
|
602
632
|
};
|
|
603
633
|
|
|
604
634
|
// src/rpc-message-channel-connection.ts
|
|
605
|
-
var
|
|
635
|
+
var import_core3 = require("@actuallab/core");
|
|
606
636
|
var RpcMessageChannelConnection = class {
|
|
607
637
|
_port;
|
|
608
638
|
_open = true;
|
|
609
639
|
binaryMode = false;
|
|
610
|
-
messageReceived = new
|
|
611
|
-
closed = new
|
|
640
|
+
messageReceived = new import_core3.EventHandlerSet();
|
|
641
|
+
closed = new import_core3.EventHandlerSet();
|
|
612
642
|
whenConnected = Promise.resolve();
|
|
613
643
|
// immediately connected
|
|
614
644
|
constructor(port) {
|
|
@@ -697,7 +727,7 @@ function defineRpcService(name, methods) {
|
|
|
697
727
|
}
|
|
698
728
|
|
|
699
729
|
// src/rpc-call-tracker.ts
|
|
700
|
-
var
|
|
730
|
+
var import_core4 = require("@actuallab/core");
|
|
701
731
|
|
|
702
732
|
// src/rpc-call-stage.ts
|
|
703
733
|
var RpcCallStage = {
|
|
@@ -716,7 +746,7 @@ var RpcCallStage = {
|
|
|
716
746
|
var RpcOutboundCall = class {
|
|
717
747
|
callId;
|
|
718
748
|
method;
|
|
719
|
-
result = new
|
|
749
|
+
result = new import_core4.PromiseSource();
|
|
720
750
|
/** Bitfield of RpcRemoteExecutionMode flags controlling reconnect/resend behavior. */
|
|
721
751
|
remoteExecutionMode;
|
|
722
752
|
/** Whether to remove this call from the tracker on $sys.Ok. Default: true.
|
|
@@ -933,13 +963,14 @@ function _readVarUint(data, offset) {
|
|
|
933
963
|
|
|
934
964
|
// src/rpc-stream.ts
|
|
935
965
|
var import_denque = __toESM(require("denque"), 1);
|
|
936
|
-
var
|
|
966
|
+
var import_core6 = require("@actuallab/core");
|
|
937
967
|
|
|
938
968
|
// src/rpc-object.ts
|
|
939
969
|
var RpcObjectKind = { Local: 0, Remote: 1 };
|
|
940
970
|
|
|
941
971
|
// src/rpc-stream-sender.ts
|
|
942
|
-
var
|
|
972
|
+
var import_core5 = require("@actuallab/core");
|
|
973
|
+
var { warnLog: warnLog3 } = getLogs("RpcSharedStream");
|
|
943
974
|
var DEFAULT_ACK_PERIOD = 256;
|
|
944
975
|
var DEFAULT_ACK_ADVANCE = 128;
|
|
945
976
|
var RpcStreamSender = class _RpcStreamSender {
|
|
@@ -966,7 +997,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
966
997
|
/** Next stream index that will be sent (matches .NET's `index`). */
|
|
967
998
|
_nextIndex = 0;
|
|
968
999
|
_ended = false;
|
|
969
|
-
_started = new
|
|
1000
|
+
_started = new import_core5.PromiseSource();
|
|
970
1001
|
/** Highest `nextIndex` observed in an ACK so far (matches .NET's `lastAckNextIndex` idiom). */
|
|
971
1002
|
_lastAckedIndex = 0;
|
|
972
1003
|
_abortController = new AbortController();
|
|
@@ -1098,7 +1129,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1098
1129
|
*/
|
|
1099
1130
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition -- _ended changes across awaits */
|
|
1100
1131
|
async _runNonRealTime(iterator, state) {
|
|
1101
|
-
const buffer = new
|
|
1132
|
+
const buffer = new import_core5.RingBuffer(this.ackAdvance + 1);
|
|
1102
1133
|
let bufferStart = 0;
|
|
1103
1134
|
let isFullyBuffered = false;
|
|
1104
1135
|
while (true) {
|
|
@@ -1108,6 +1139,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1108
1139
|
if (this._ended) return;
|
|
1109
1140
|
ack = this._tryProcessAcks();
|
|
1110
1141
|
if (!ack) {
|
|
1142
|
+
warnLog3?.log("Something is off: couldn't read an acknowledgement");
|
|
1111
1143
|
return;
|
|
1112
1144
|
}
|
|
1113
1145
|
}
|
|
@@ -1171,7 +1203,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1171
1203
|
* src/ActualLab.Rpc/Infrastructure/RpcSharedStream.cs:219-420.
|
|
1172
1204
|
*/
|
|
1173
1205
|
async _runRealTime(iterator, state) {
|
|
1174
|
-
const buffer = new
|
|
1206
|
+
const buffer = new import_core5.RingBuffer(this.ackAdvance + 1);
|
|
1175
1207
|
let bufferStart = 0;
|
|
1176
1208
|
let isFullyBuffered = false;
|
|
1177
1209
|
while (true) {
|
|
@@ -1180,7 +1212,10 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1180
1212
|
await this._waitAckReady();
|
|
1181
1213
|
if (this._ended) return;
|
|
1182
1214
|
ack = this._tryProcessAcks();
|
|
1183
|
-
if (!ack)
|
|
1215
|
+
if (!ack) {
|
|
1216
|
+
warnLog3?.log("Something is off: couldn't read an acknowledgement");
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1184
1219
|
}
|
|
1185
1220
|
this._lastAckedIndex = ack.nextIndex;
|
|
1186
1221
|
if (ack.mustReset && !isFullyBuffered) {
|
|
@@ -1328,7 +1363,7 @@ var RpcStreamSender = class _RpcStreamSender {
|
|
|
1328
1363
|
/** Wait for the ACK queue to have at least one entry (or `_ended`). */
|
|
1329
1364
|
async _waitAckReady() {
|
|
1330
1365
|
if (this._acks.length > 0 || this._ended) return;
|
|
1331
|
-
this._whenAckReady = new
|
|
1366
|
+
this._whenAckReady = new import_core5.PromiseSource();
|
|
1332
1367
|
await this._whenAckReady.promise;
|
|
1333
1368
|
this._whenAckReady = null;
|
|
1334
1369
|
}
|
|
@@ -1376,6 +1411,7 @@ function _clamp(value, min, max) {
|
|
|
1376
1411
|
}
|
|
1377
1412
|
|
|
1378
1413
|
// src/rpc-stream.ts
|
|
1414
|
+
var { warnLog: warnLog4 } = getLogs("RpcStream");
|
|
1379
1415
|
var DEFAULT_ACK_PERIOD2 = 30;
|
|
1380
1416
|
var DEFAULT_ACK_ADVANCE2 = 61;
|
|
1381
1417
|
function parseStreamRef(value) {
|
|
@@ -1521,9 +1557,7 @@ var RpcStream = class _RpcStream {
|
|
|
1521
1557
|
onItem(index, item) {
|
|
1522
1558
|
if (this._disposed || this._completed) return;
|
|
1523
1559
|
if (index > this._nextExpectedIndex) {
|
|
1524
|
-
|
|
1525
|
-
`[RpcStream] item index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
|
|
1526
|
-
);
|
|
1560
|
+
warnLog4?.log(`item index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`);
|
|
1527
1561
|
if (!this.allowReconnect) {
|
|
1528
1562
|
this._completed = true;
|
|
1529
1563
|
this._completionError = new Error(
|
|
@@ -1548,9 +1582,7 @@ var RpcStream = class _RpcStream {
|
|
|
1548
1582
|
onBatch(index, items) {
|
|
1549
1583
|
if (this._disposed || this._completed) return;
|
|
1550
1584
|
if (index > this._nextExpectedIndex) {
|
|
1551
|
-
|
|
1552
|
-
`[RpcStream] batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
|
|
1553
|
-
);
|
|
1585
|
+
warnLog4?.log(`batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`);
|
|
1554
1586
|
if (!this.allowReconnect) {
|
|
1555
1587
|
this._completed = true;
|
|
1556
1588
|
this._completionError = new Error(
|
|
@@ -1621,7 +1653,7 @@ var RpcStream = class _RpcStream {
|
|
|
1621
1653
|
if (this._completionError) throw this._completionError;
|
|
1622
1654
|
return { value: void 0, done: true };
|
|
1623
1655
|
}
|
|
1624
|
-
this._consumerWaiting = new
|
|
1656
|
+
this._consumerWaiting = new import_core6.PromiseSource();
|
|
1625
1657
|
await this._consumerWaiting.promise;
|
|
1626
1658
|
}
|
|
1627
1659
|
},
|
|
@@ -1737,10 +1769,12 @@ function base64Decode(encoded) {
|
|
|
1737
1769
|
}
|
|
1738
1770
|
|
|
1739
1771
|
// src/rpc-system-call-handler.ts
|
|
1772
|
+
var { debugLog, warnLog: warnLog5 } = getLogs("RpcSystemCallHandler");
|
|
1740
1773
|
var RpcSystemCallHandler = class {
|
|
1741
1774
|
handle(message, args, peer) {
|
|
1742
1775
|
const method = message.Method;
|
|
1743
1776
|
const relatedId = message.RelatedId ?? 0;
|
|
1777
|
+
debugLog?.log(`'${peer.ref}': handle ${method}#${relatedId}`);
|
|
1744
1778
|
switch (method) {
|
|
1745
1779
|
case RpcSystemCalls.ok: {
|
|
1746
1780
|
const call = peer.outbound.get(relatedId);
|
|
@@ -1762,6 +1796,12 @@ var RpcSystemCallHandler = class {
|
|
|
1762
1796
|
if (call !== void 0) {
|
|
1763
1797
|
const errorInfo = args[0];
|
|
1764
1798
|
const msg = errorInfo?.Message ?? errorInfo?.message ?? "RPC error";
|
|
1799
|
+
const errorType = errorInfo?.TypeRef ?? errorInfo?.typeRef;
|
|
1800
|
+
if (errorType !== null && typeof errorType === "object") {
|
|
1801
|
+
const t = errorType;
|
|
1802
|
+
if (t.TypeName === "RpcRerouteException" || t.typeName === "RpcRerouteException")
|
|
1803
|
+
warnLog5?.log("Got RpcRerouteException from remote peer:", msg);
|
|
1804
|
+
}
|
|
1765
1805
|
call.result.reject(new Error(msg));
|
|
1766
1806
|
}
|
|
1767
1807
|
break;
|
|
@@ -1775,25 +1815,20 @@ var RpcSystemCallHandler = class {
|
|
|
1775
1815
|
}
|
|
1776
1816
|
case RpcSystemCalls.item: {
|
|
1777
1817
|
const stream = peer.remoteObjects.get(relatedId);
|
|
1778
|
-
if (!stream)
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
);
|
|
1782
|
-
} else {
|
|
1818
|
+
if (!stream)
|
|
1819
|
+
debugLog?.log(`$sys.I: no stream for relatedId=${relatedId}`);
|
|
1820
|
+
else
|
|
1783
1821
|
stream.onItem(
|
|
1784
1822
|
args[0],
|
|
1785
1823
|
resolveStreamRefs(args[1], peer)
|
|
1786
1824
|
);
|
|
1787
|
-
}
|
|
1788
1825
|
break;
|
|
1789
1826
|
}
|
|
1790
1827
|
case RpcSystemCalls.batch: {
|
|
1791
1828
|
const stream = peer.remoteObjects.get(relatedId);
|
|
1792
|
-
if (!stream)
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
);
|
|
1796
|
-
} else if (Array.isArray(args[1])) {
|
|
1829
|
+
if (!stream)
|
|
1830
|
+
debugLog?.log(`$sys.B: no stream for relatedId=${relatedId}`);
|
|
1831
|
+
else if (Array.isArray(args[1])) {
|
|
1797
1832
|
const items = args[1];
|
|
1798
1833
|
for (let i = 0; i < items.length; i++)
|
|
1799
1834
|
items[i] = resolveStreamRefs(items[i], peer);
|
|
@@ -1804,9 +1839,7 @@ var RpcSystemCallHandler = class {
|
|
|
1804
1839
|
case RpcSystemCalls.end: {
|
|
1805
1840
|
const stream = peer.remoteObjects.get(relatedId);
|
|
1806
1841
|
if (!stream) {
|
|
1807
|
-
|
|
1808
|
-
`[RpcSysHandler] $sys.End: no stream for relatedId=${relatedId}`
|
|
1809
|
-
);
|
|
1842
|
+
debugLog?.log(`$sys.End: no stream for relatedId=${relatedId}`);
|
|
1810
1843
|
} else {
|
|
1811
1844
|
const errorInfo = args[1];
|
|
1812
1845
|
const msg = errorInfo?.Message ?? errorInfo?.message;
|
|
@@ -1895,6 +1928,7 @@ function _toBytes(value) {
|
|
|
1895
1928
|
}
|
|
1896
1929
|
|
|
1897
1930
|
// src/rpc-system-call-sender.ts
|
|
1931
|
+
var { errorLog } = getLogs("RpcSystemCallSender");
|
|
1898
1932
|
var RpcSystemCallSender = class _RpcSystemCallSender {
|
|
1899
1933
|
// Reusable envelopes — one per hot-path method.
|
|
1900
1934
|
_itemEnv = {
|
|
@@ -1951,12 +1985,17 @@ var RpcSystemCallSender = class _RpcSystemCallSender {
|
|
|
1951
1985
|
]);
|
|
1952
1986
|
}
|
|
1953
1987
|
ok(conn, format, relatedId, result) {
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1988
|
+
try {
|
|
1989
|
+
this._send(
|
|
1990
|
+
conn,
|
|
1991
|
+
format,
|
|
1992
|
+
{ Method: RpcSystemCalls.ok, RelatedId: relatedId },
|
|
1993
|
+
[result]
|
|
1994
|
+
);
|
|
1995
|
+
} catch (e) {
|
|
1996
|
+
errorLog?.log(`Failed to send Ok response for call #${relatedId}`, e);
|
|
1997
|
+
this.error(conn, format, relatedId, e);
|
|
1998
|
+
}
|
|
1960
1999
|
}
|
|
1961
2000
|
error(conn, format, relatedId, error) {
|
|
1962
2001
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -2068,14 +2107,14 @@ var RpcSharedObjectTracker = class {
|
|
|
2068
2107
|
};
|
|
2069
2108
|
|
|
2070
2109
|
// src/rpc-peer.ts
|
|
2071
|
-
var
|
|
2110
|
+
var import_core8 = require("@actuallab/core");
|
|
2072
2111
|
|
|
2073
2112
|
// src/rpc-client-peer-reconnect-delayer.ts
|
|
2074
|
-
var
|
|
2075
|
-
var RpcClientPeerReconnectDelayer = class extends
|
|
2113
|
+
var import_core7 = require("@actuallab/core");
|
|
2114
|
+
var RpcClientPeerReconnectDelayer = class extends import_core7.RetryDelayer {
|
|
2076
2115
|
constructor() {
|
|
2077
2116
|
super();
|
|
2078
|
-
this.delays =
|
|
2117
|
+
this.delays = import_core7.RetryDelaySeq.exp(1e3, 6e4);
|
|
2079
2118
|
}
|
|
2080
2119
|
};
|
|
2081
2120
|
|
|
@@ -2238,6 +2277,7 @@ var RpcSerializationFormatResolver = class _RpcSerializationFormatResolver {
|
|
|
2238
2277
|
|
|
2239
2278
|
// src/rpc-peer.ts
|
|
2240
2279
|
var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
|
|
2280
|
+
var { debugLog: debugLog2, infoLog, warnLog: warnLog6, errorLog: errorLog2 } = getLogs("RpcPeer");
|
|
2241
2281
|
var defaultConnectionUrlResolver = (peer) => {
|
|
2242
2282
|
const sep = peer.ref.includes("?") ? "&" : "?";
|
|
2243
2283
|
return peer.ref + sep + `clientId=${peer.clientId}&f=${peer.serializationFormat}`;
|
|
@@ -2253,8 +2293,8 @@ var RpcPeer = class {
|
|
|
2253
2293
|
inbound = new RpcInboundCallTracker();
|
|
2254
2294
|
remoteObjects = new RpcRemoteObjectTracker();
|
|
2255
2295
|
sharedObjects = new RpcSharedObjectTracker();
|
|
2256
|
-
connected = new
|
|
2257
|
-
disconnected = new
|
|
2296
|
+
connected = new import_core8.EventHandlerSet();
|
|
2297
|
+
disconnected = new import_core8.EventHandlerSet();
|
|
2258
2298
|
_pendingSends = [];
|
|
2259
2299
|
_keepAliveTimer;
|
|
2260
2300
|
constructor(ref, hub) {
|
|
@@ -2276,9 +2316,14 @@ var RpcPeer = class {
|
|
|
2276
2316
|
conn.closed.add((ev) => {
|
|
2277
2317
|
this._connection = void 0;
|
|
2278
2318
|
this._stopKeepAlive();
|
|
2319
|
+
if (ev.reason)
|
|
2320
|
+
infoLog?.log(`'${this.ref}': Disconnected: ${ev.reason} (code=${ev.code})`);
|
|
2321
|
+
else
|
|
2322
|
+
infoLog?.log(`'${this.ref}': Disconnected`);
|
|
2279
2323
|
this.disconnected.trigger(ev);
|
|
2280
2324
|
});
|
|
2281
2325
|
void conn.whenConnected.then(() => {
|
|
2326
|
+
infoLog?.log(`'${this.ref}': Connected`);
|
|
2282
2327
|
this.connected.trigger();
|
|
2283
2328
|
this._startKeepAlive();
|
|
2284
2329
|
});
|
|
@@ -2353,6 +2398,7 @@ var RpcPeer = class {
|
|
|
2353
2398
|
this._sendWireData(wireData);
|
|
2354
2399
|
}
|
|
2355
2400
|
close() {
|
|
2401
|
+
infoLog?.log(`'${this.ref}': Stopping`);
|
|
2356
2402
|
this._stopKeepAlive();
|
|
2357
2403
|
this.remoteObjects.disconnectAll();
|
|
2358
2404
|
this.sharedObjects.disconnectAll();
|
|
@@ -2366,6 +2412,7 @@ var RpcPeer = class {
|
|
|
2366
2412
|
this.outbound.invalidateAll();
|
|
2367
2413
|
this._connection?.close();
|
|
2368
2414
|
this._hub.peers.delete(this.ref);
|
|
2415
|
+
infoLog?.log(`'${this.ref}': Stopped`);
|
|
2369
2416
|
}
|
|
2370
2417
|
/** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
|
|
2371
2418
|
_flushPendingSends() {
|
|
@@ -2392,15 +2439,21 @@ var RpcPeer = class {
|
|
|
2392
2439
|
_handleMessage(received) {
|
|
2393
2440
|
let message;
|
|
2394
2441
|
let args;
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2442
|
+
try {
|
|
2443
|
+
if (received.kind === "binary") {
|
|
2444
|
+
message = received.message;
|
|
2445
|
+
args = received.args;
|
|
2446
|
+
} else {
|
|
2447
|
+
const parsed = deserializeMessage(received.raw);
|
|
2448
|
+
message = parsed.message;
|
|
2449
|
+
args = parsed.args;
|
|
2450
|
+
}
|
|
2451
|
+
} catch (e) {
|
|
2452
|
+
errorLog2?.log(`'${this.ref}': Failed to process inbound message:`, received, e);
|
|
2453
|
+
return;
|
|
2402
2454
|
}
|
|
2403
2455
|
const method = message.Method ?? "";
|
|
2456
|
+
debugLog2?.log(`'${this.ref}': <- ${method}#${message.RelatedId ?? 0}`);
|
|
2404
2457
|
if (method === RpcSystemCalls.handshake) {
|
|
2405
2458
|
const raw = args[0];
|
|
2406
2459
|
if (raw !== void 0) {
|
|
@@ -2467,6 +2520,7 @@ var RpcPeer = class {
|
|
|
2467
2520
|
e
|
|
2468
2521
|
);
|
|
2469
2522
|
}
|
|
2523
|
+
debugLog2?.log(`'${this.ref}': Inbound call failed: ${method}#${relatedId}`, e);
|
|
2470
2524
|
} finally {
|
|
2471
2525
|
if (!isNoWait) {
|
|
2472
2526
|
this.inbound.remove(relatedId);
|
|
@@ -2520,11 +2574,11 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2520
2574
|
serializationFormat;
|
|
2521
2575
|
/** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
|
|
2522
2576
|
connectionUrlResolver = defaultConnectionUrlResolver;
|
|
2523
|
-
peerChanged = new
|
|
2577
|
+
peerChanged = new import_core8.EventHandlerSet();
|
|
2524
2578
|
/** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
|
|
2525
|
-
unsupportedFormat = new
|
|
2579
|
+
unsupportedFormat = new import_core8.EventHandlerSet();
|
|
2526
2580
|
reconnectDelayer = new RpcClientPeerReconnectDelayer();
|
|
2527
|
-
reconnectsAtChanged = new
|
|
2581
|
+
reconnectsAtChanged = new import_core8.EventHandlerSet();
|
|
2528
2582
|
get reconnectsAt() {
|
|
2529
2583
|
return this._reconnectsAt;
|
|
2530
2584
|
}
|
|
@@ -2555,10 +2609,12 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2555
2609
|
/** Start the reconnection loop — runs until disposed. */
|
|
2556
2610
|
async run(wsFactory) {
|
|
2557
2611
|
const connUrl = this.connectionUrlResolver(this);
|
|
2612
|
+
infoLog?.log(`'${this.ref}': Started (Client)`);
|
|
2558
2613
|
while (!this._disposed) {
|
|
2559
2614
|
let lastCloseCode = 0;
|
|
2560
2615
|
let lastCloseReason = "";
|
|
2561
2616
|
try {
|
|
2617
|
+
infoLog?.log(`'${this.ref}': Connecting to ${connUrl}`);
|
|
2562
2618
|
const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
|
|
2563
2619
|
const conn = new RpcWebSocketConnection(
|
|
2564
2620
|
ws,
|
|
@@ -2571,7 +2627,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2571
2627
|
lastCloseCode = ev.code;
|
|
2572
2628
|
lastCloseReason = ev.reason;
|
|
2573
2629
|
});
|
|
2574
|
-
this._pendingHandshake = new
|
|
2630
|
+
this._pendingHandshake = new import_core8.PromiseSource();
|
|
2575
2631
|
this.setupConnection(conn);
|
|
2576
2632
|
this._connection = void 0;
|
|
2577
2633
|
const closedRejection = new Promise(
|
|
@@ -2582,13 +2638,18 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2582
2638
|
closedRejection.catch(() => {
|
|
2583
2639
|
});
|
|
2584
2640
|
await Promise.race([conn.whenConnected, closedRejection]);
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2641
|
+
try {
|
|
2642
|
+
this._hub.systemCallSender.handshake(
|
|
2643
|
+
conn,
|
|
2644
|
+
this.format,
|
|
2645
|
+
this.id,
|
|
2646
|
+
this._hub.hubId,
|
|
2647
|
+
++this._handshakeIndex
|
|
2648
|
+
);
|
|
2649
|
+
} catch (e) {
|
|
2650
|
+
warnLog6?.log(`'${this.ref}': Failed to send handshake`, e);
|
|
2651
|
+
throw e;
|
|
2652
|
+
}
|
|
2592
2653
|
const remoteHandshake = await Promise.race([
|
|
2593
2654
|
this._pendingHandshake.promise,
|
|
2594
2655
|
closedRejection
|
|
@@ -2601,20 +2662,24 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2601
2662
|
isPeerChanged = this._lastRemoteHubId !== void 0 && this._lastRemoteHubId !== remoteHubId;
|
|
2602
2663
|
if (isPeerChanged) {
|
|
2603
2664
|
this.inbound.clear();
|
|
2665
|
+
infoLog?.log(`'${this.ref}': Peer changed`);
|
|
2604
2666
|
this.peerChanged.trigger();
|
|
2605
2667
|
}
|
|
2606
2668
|
this._lastRemoteHubId = remoteHubId;
|
|
2607
2669
|
}
|
|
2670
|
+
infoLog?.log(`'${this.ref}': Handshake succeeded, peerChanged=${isPeerChanged}`);
|
|
2608
2671
|
this._connection = conn;
|
|
2609
2672
|
this._connectionKind = 2 /* Connected */;
|
|
2610
2673
|
this._tryIndex = 0;
|
|
2611
2674
|
await this._reconnect(isPeerChanged);
|
|
2612
2675
|
await new Promise((r) => conn.closed.add(() => r()));
|
|
2613
|
-
} catch {
|
|
2676
|
+
} catch (e) {
|
|
2677
|
+
debugLog2?.log(`'${this.ref}': run() iteration failed:`, e);
|
|
2614
2678
|
}
|
|
2615
2679
|
this._connectionKind = 0 /* Disconnected */;
|
|
2616
2680
|
if (this._disposed) break;
|
|
2617
2681
|
if (lastCloseCode === RPC_CLOSE_CODE_UNSUPPORTED_FORMAT) {
|
|
2682
|
+
warnLog6?.log(`'${this.ref}': Unsupported serialization format - shutting down`);
|
|
2618
2683
|
this.unsupportedFormat.trigger({ reason: lastCloseReason });
|
|
2619
2684
|
this._disposed = true;
|
|
2620
2685
|
break;
|
|
@@ -2622,6 +2687,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
2622
2687
|
this._tryIndex++;
|
|
2623
2688
|
const delay = this.reconnectDelayer.getDelay(this._tryIndex);
|
|
2624
2689
|
if (delay.isLimitExceeded) {
|
|
2690
|
+
warnLog6?.log(`'${this.ref}': Reconnect limit exceeded - shutting down`);
|
|
2625
2691
|
this._disposed = true;
|
|
2626
2692
|
break;
|
|
2627
2693
|
}
|
|
@@ -2816,6 +2882,7 @@ function _toBytes2(value) {
|
|
|
2816
2882
|
}
|
|
2817
2883
|
|
|
2818
2884
|
// src/rpc-service-host.ts
|
|
2885
|
+
var { warnLog: warnLog7 } = getLogs("RpcServiceHost");
|
|
2819
2886
|
var RpcServiceHost = class {
|
|
2820
2887
|
_methods = /* @__PURE__ */ new Map();
|
|
2821
2888
|
register(def, impl) {
|
|
@@ -2830,8 +2897,10 @@ var RpcServiceHost = class {
|
|
|
2830
2897
|
}
|
|
2831
2898
|
async dispatch(wireMethod, args, context) {
|
|
2832
2899
|
const entry = this._methods.get(wireMethod);
|
|
2833
|
-
if (entry === void 0)
|
|
2900
|
+
if (entry === void 0) {
|
|
2901
|
+
warnLog7?.log(`Method not found: ${wireMethod}`);
|
|
2834
2902
|
throw new Error(`Method not found: ${wireMethod}`);
|
|
2903
|
+
}
|
|
2835
2904
|
if (context !== void 0 && entry.def.callTypeId !== 0) {
|
|
2836
2905
|
return await entry.fn(...args, context);
|
|
2837
2906
|
}
|
|
@@ -3361,6 +3430,7 @@ function computeMethodHash(methodName) {
|
|
|
3361
3430
|
}
|
|
3362
3431
|
|
|
3363
3432
|
// src/rpc-method-registry.ts
|
|
3433
|
+
var { warnLog: warnLog8 } = getLogs("RpcMethodRegistry");
|
|
3364
3434
|
var RpcMethodRegistry = class {
|
|
3365
3435
|
_nameToHash = /* @__PURE__ */ new Map();
|
|
3366
3436
|
_hashToName = /* @__PURE__ */ new Map();
|
|
@@ -3370,9 +3440,7 @@ var RpcMethodRegistry = class {
|
|
|
3370
3440
|
const hash = computeMethodHash(methodName);
|
|
3371
3441
|
const existing = this._hashToName.get(hash);
|
|
3372
3442
|
if (existing !== void 0 && existing !== methodName) {
|
|
3373
|
-
|
|
3374
|
-
`[RpcMethodRegistry] hash collision: "${methodName}" and "${existing}" both hash to ${hash}`
|
|
3375
|
-
);
|
|
3443
|
+
warnLog8?.log(`hash collision: "${methodName}" and "${existing}" both hash to ${hash}`);
|
|
3376
3444
|
return;
|
|
3377
3445
|
}
|
|
3378
3446
|
this._nameToHash.set(methodName, hash);
|
|
@@ -3405,6 +3473,7 @@ var RpcMethodRegistry = class {
|
|
|
3405
3473
|
};
|
|
3406
3474
|
|
|
3407
3475
|
// src/rpc-hub.ts
|
|
3476
|
+
var { warnLog: warnLog9 } = getLogs("RpcHub");
|
|
3408
3477
|
var RpcHub = class {
|
|
3409
3478
|
hubId;
|
|
3410
3479
|
peers = /* @__PURE__ */ new Map();
|
|
@@ -3430,6 +3499,7 @@ var RpcHub = class {
|
|
|
3430
3499
|
if (peer !== void 0) {
|
|
3431
3500
|
peer.close();
|
|
3432
3501
|
this.peers.delete(ref);
|
|
3502
|
+
warnLog9?.log(`'${ref}': peer is removed from RpcHub`);
|
|
3433
3503
|
}
|
|
3434
3504
|
}
|
|
3435
3505
|
/** Get or create a peer by ref. Server peers have "server://" prefix, everything else is a client peer. */
|
|
@@ -3661,13 +3731,14 @@ function getStateDescription(state, useLastError = false) {
|
|
|
3661
3731
|
}
|
|
3662
3732
|
|
|
3663
3733
|
// src/rpc-peer-state-monitor.ts
|
|
3664
|
-
var
|
|
3734
|
+
var import_core9 = require("@actuallab/core");
|
|
3735
|
+
var { infoLog: infoLog2 } = getLogs("RpcPeerStateMonitor");
|
|
3665
3736
|
var JustConnectedPeriodMs = 1500;
|
|
3666
3737
|
var JustDisconnectedPeriodMs = 3e3;
|
|
3667
3738
|
var MinReconnectsInMs = 1e3;
|
|
3668
3739
|
var RpcPeerStateMonitor = class {
|
|
3669
3740
|
peer;
|
|
3670
|
-
stateChanged = new
|
|
3741
|
+
stateChanged = new import_core9.EventHandlerSet();
|
|
3671
3742
|
_rawConnected;
|
|
3672
3743
|
_connectedAt = 0;
|
|
3673
3744
|
_disconnectedAt = 0;
|
|
@@ -3723,6 +3794,7 @@ var RpcPeerStateMonitor = class {
|
|
|
3723
3794
|
this._scheduleRecompute(
|
|
3724
3795
|
this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs
|
|
3725
3796
|
);
|
|
3797
|
+
infoLog2?.log(`'${peer.ref}': monitor started`);
|
|
3726
3798
|
}
|
|
3727
3799
|
get state() {
|
|
3728
3800
|
return this._state;
|
|
@@ -3738,6 +3810,7 @@ var RpcPeerStateMonitor = class {
|
|
|
3738
3810
|
this.peer.reconnectDelayer.cancelDelaysChanged.remove(
|
|
3739
3811
|
this._onCancelDelaysChanged
|
|
3740
3812
|
);
|
|
3813
|
+
infoLog2?.log(`'${this.peer.ref}': monitor stopped`);
|
|
3741
3814
|
}
|
|
3742
3815
|
_recompute() {
|
|
3743
3816
|
if (this._timer !== void 0) {
|
|
@@ -3864,6 +3937,7 @@ var RpcPeerStateMonitor = class {
|
|
|
3864
3937
|
deserializeBinaryMessage,
|
|
3865
3938
|
deserializeCompactBinaryMessage,
|
|
3866
3939
|
deserializeMessage,
|
|
3940
|
+
getLogs,
|
|
3867
3941
|
getMethodsMeta,
|
|
3868
3942
|
getServiceMeta,
|
|
3869
3943
|
getStateDescription,
|