@actuallab/rpc 14.3.32 → 14.3.34
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 +54 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -4
- package/dist/index.d.ts +22 -4
- package/dist/index.js +53 -22
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -56,6 +56,7 @@ __export(index_exports, {
|
|
|
56
56
|
RpcOutboundCall: () => RpcOutboundCall,
|
|
57
57
|
RpcOutboundCallTracker: () => RpcOutboundCallTracker,
|
|
58
58
|
RpcPeer: () => RpcPeer,
|
|
59
|
+
RpcPeerChangeKind: () => RpcPeerChangeKind,
|
|
59
60
|
RpcPeerStateKind: () => RpcPeerStateKind,
|
|
60
61
|
RpcPeerStateMonitor: () => RpcPeerStateMonitor,
|
|
61
62
|
RpcRefBuilder: () => RpcRefBuilder,
|
|
@@ -864,6 +865,16 @@ var RpcOutboundCallTracker = class {
|
|
|
864
865
|
activeCallIds() {
|
|
865
866
|
return [...this._calls.keys()];
|
|
866
867
|
}
|
|
868
|
+
/** Calls handed to the transport at least once. Must be snapshotted BEFORE the
|
|
869
|
+
* peer enters `Connected` — that flushes every queued call, making queued and
|
|
870
|
+
* in-flight calls indistinguishable. Mirrors .NET's `GetSentCalls`. */
|
|
871
|
+
getSentCalls() {
|
|
872
|
+
const calls = [];
|
|
873
|
+
for (const call of this._calls.values())
|
|
874
|
+
if (call.sentAt !== 0)
|
|
875
|
+
calls.push(call);
|
|
876
|
+
return calls;
|
|
877
|
+
}
|
|
867
878
|
/** Reject all pending calls with the given error.
|
|
868
879
|
* Stage-3 compute calls (result resolved, awaiting invalidation) are kept in the tracker. */
|
|
869
880
|
rejectAll(error) {
|
|
@@ -3178,6 +3189,13 @@ var RpcConnectionState = /* @__PURE__ */ ((RpcConnectionState2) => {
|
|
|
3178
3189
|
RpcConnectionState2[RpcConnectionState2["Connected"] = 3] = "Connected";
|
|
3179
3190
|
return RpcConnectionState2;
|
|
3180
3191
|
})(RpcConnectionState || {});
|
|
3192
|
+
var RpcPeerChangeKind = /* @__PURE__ */ ((RpcPeerChangeKind2) => {
|
|
3193
|
+
RpcPeerChangeKind2[RpcPeerChangeKind2["Unchanged"] = 0] = "Unchanged";
|
|
3194
|
+
RpcPeerChangeKind2[RpcPeerChangeKind2["ChangedToVeryFirst"] = 1] = "ChangedToVeryFirst";
|
|
3195
|
+
RpcPeerChangeKind2[RpcPeerChangeKind2["Changed"] = 2] = "Changed";
|
|
3196
|
+
return RpcPeerChangeKind2;
|
|
3197
|
+
})(RpcPeerChangeKind || {});
|
|
3198
|
+
var peerChangeKindNames = ["Unchanged", "ChangedToVeryFirst", "Changed"];
|
|
3181
3199
|
var RpcClientPeer = class extends RpcPeer {
|
|
3182
3200
|
_disposed = false;
|
|
3183
3201
|
/** Aborted when the peer is stopped/disposed — threaded into the reconnect
|
|
@@ -3190,7 +3208,10 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3190
3208
|
* `connectionState.Handshake.Index` path in
|
|
3191
3209
|
* `RpcOutboundCallTracker.TryReconnect`. */
|
|
3192
3210
|
_remoteHandshakeIndex = 0;
|
|
3193
|
-
|
|
3211
|
+
/** Mirrors .NET's `lastHandshake` local in `RpcPeer.OnRun`: first-ness is keyed
|
|
3212
|
+
* off "was there a previous handshake", not off `RemotePeerId` — a legacy server
|
|
3213
|
+
* sends none, so every one of its handshakes would look like the first. */
|
|
3214
|
+
_lastHandshake;
|
|
3194
3215
|
_pendingHandshake;
|
|
3195
3216
|
_reconnectsAt = 0;
|
|
3196
3217
|
/** Server-issued reconnect secret, from the most recent handshake that
|
|
@@ -3271,10 +3292,11 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3271
3292
|
* self-invalidate and remote/shared objects are disposed). Pass `false`
|
|
3272
3293
|
* to simulate a same-peer reconnect in tests. */
|
|
3273
3294
|
connectWith(conn, isPeerChanged = true) {
|
|
3295
|
+
const sentCalls = this.outboundCalls.getSentCalls();
|
|
3274
3296
|
this.setupConnection(conn);
|
|
3275
3297
|
this._isConnected = true;
|
|
3276
3298
|
this.connectionStateChanged.trigger(3 /* Connected */);
|
|
3277
|
-
void this._reconnect(isPeerChanged);
|
|
3299
|
+
void this._reconnect(sentCalls, isPeerChanged);
|
|
3278
3300
|
}
|
|
3279
3301
|
/** Kick off the reconnect loop. Idempotent — subsequent calls are
|
|
3280
3302
|
* no-ops; await `peer.whenRunning` if you need the loop's completion
|
|
@@ -3405,11 +3427,19 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3405
3427
|
this._remoteHandshakeIndex = remoteHandshake.Index ?? 0;
|
|
3406
3428
|
if (remoteHandshake.Secret)
|
|
3407
3429
|
this._reconnectSecret = remoteHandshake.Secret;
|
|
3408
|
-
const
|
|
3409
|
-
infoLog?.log(
|
|
3430
|
+
const peerChangeKind = this._detectPeerChange(remoteHandshake);
|
|
3431
|
+
infoLog?.log(
|
|
3432
|
+
`'${this.ref}': Handshake succeeded, peerChangeKind=${peerChangeKindNames[peerChangeKind]}`
|
|
3433
|
+
);
|
|
3434
|
+
const sentCalls = this.outboundCalls.getSentCalls();
|
|
3410
3435
|
this._setConnectionState(3 /* Connected */);
|
|
3411
3436
|
connectedAt = Date.now();
|
|
3412
|
-
|
|
3437
|
+
if (peerChangeKind !== 1 /* ChangedToVeryFirst */)
|
|
3438
|
+
await this._reconnect(
|
|
3439
|
+
sentCalls,
|
|
3440
|
+
peerChangeKind === 2 /* Changed */,
|
|
3441
|
+
closedController.signal
|
|
3442
|
+
);
|
|
3413
3443
|
await whenClosed;
|
|
3414
3444
|
} catch (e) {
|
|
3415
3445
|
debugLog2?.log(`'${this.ref}': run() iteration failed:`, e);
|
|
@@ -3431,7 +3461,10 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3431
3461
|
}
|
|
3432
3462
|
}
|
|
3433
3463
|
/**
|
|
3434
|
-
* Reconcile
|
|
3464
|
+
* Reconcile the calls that were in flight on the connection that just died
|
|
3465
|
+
* (`sentCalls`), then resend the survivors. Calls still waiting for a
|
|
3466
|
+
* connection are deliberately NOT passed in — `AllowReconnect`/`AllowResend`
|
|
3467
|
+
* don't apply to them, and entering `Connected` already sends them.
|
|
3435
3468
|
*
|
|
3436
3469
|
* On peer change (different server hubId) or with binary wire format —
|
|
3437
3470
|
* we blind-resend every eligible call.
|
|
@@ -3449,7 +3482,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3449
3482
|
* are always self-invalidated — TS doesn't track compute-call stages
|
|
3450
3483
|
* across reconnect, so the safest behavior is to force a fresh compute.
|
|
3451
3484
|
*/
|
|
3452
|
-
async _reconnect(isPeerChanged, closedSignal) {
|
|
3485
|
+
async _reconnect(sentCalls, isPeerChanged, closedSignal) {
|
|
3453
3486
|
if (this._connection === void 0) return;
|
|
3454
3487
|
if (isPeerChanged) {
|
|
3455
3488
|
this.remoteObjects.disconnectAll();
|
|
@@ -3458,7 +3491,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3458
3491
|
this.remoteObjects.reconnectAll();
|
|
3459
3492
|
}
|
|
3460
3493
|
const eligible = [];
|
|
3461
|
-
for (const call of
|
|
3494
|
+
for (const call of sentCalls) {
|
|
3462
3495
|
const mode = call.remoteExecutionMode;
|
|
3463
3496
|
if (!(mode & 2)) {
|
|
3464
3497
|
if (!call.result.isCompleted)
|
|
@@ -3479,8 +3512,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3479
3512
|
continue;
|
|
3480
3513
|
}
|
|
3481
3514
|
eligible.push(call);
|
|
3482
|
-
|
|
3483
|
-
call.sentAt = Date.now();
|
|
3515
|
+
call.sentAt = Date.now();
|
|
3484
3516
|
}
|
|
3485
3517
|
let unknownIds = null;
|
|
3486
3518
|
if (!isPeerChanged && eligible.length > 0) {
|
|
@@ -3568,19 +3600,18 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
3568
3600
|
* `RpcHandshake.GetPeerChangeKind` keys off `RemotePeerId`, not
|
|
3569
3601
|
* `RemoteHubId` (an idle server peer can be replaced while keeping the
|
|
3570
3602
|
* same hub id). On a change it clears the inbound tracker and fires
|
|
3571
|
-
* `peerChanged`; the very first handshake is
|
|
3603
|
+
* `peerChanged`; the very first handshake is `ChangedToVeryFirst`. */
|
|
3572
3604
|
_detectPeerChange(handshake) {
|
|
3573
|
-
const
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
return isPeerChanged;
|
|
3605
|
+
const lastHandshake = this._lastHandshake;
|
|
3606
|
+
this._lastHandshake = handshake;
|
|
3607
|
+
if (lastHandshake === void 0)
|
|
3608
|
+
return 1 /* ChangedToVeryFirst */;
|
|
3609
|
+
if (handshake.RemotePeerId === lastHandshake.RemotePeerId)
|
|
3610
|
+
return 0 /* Unchanged */;
|
|
3611
|
+
this.inboundCalls.clear();
|
|
3612
|
+
infoLog?.log(`'${this.ref}': Peer changed`);
|
|
3613
|
+
this.peerChanged.trigger();
|
|
3614
|
+
return 2 /* Changed */;
|
|
3584
3615
|
}
|
|
3585
3616
|
_onHandshakeReceived(handshake) {
|
|
3586
3617
|
this._pendingHandshake?.resolve(handshake);
|
|
@@ -4880,6 +4911,7 @@ var RpcPeerStateMonitor = class {
|
|
|
4880
4911
|
RpcOutboundCall,
|
|
4881
4912
|
RpcOutboundCallTracker,
|
|
4882
4913
|
RpcPeer,
|
|
4914
|
+
RpcPeerChangeKind,
|
|
4883
4915
|
RpcPeerStateKind,
|
|
4884
4916
|
RpcPeerStateMonitor,
|
|
4885
4917
|
RpcRefBuilder,
|