@actuallab/rpc 14.3.16 → 14.3.26

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.d.cts CHANGED
@@ -981,6 +981,9 @@ declare abstract class RpcPeer {
981
981
  * stale `$sys.Reconnect` that references an older connection generation
982
982
  * (C# `RpcSystemCalls.Reconnect`'s `ownHandshake.Index` check). */
983
983
  protected _ownHandshakeIndex: number;
984
+ /** Whether the current connection generation has already used its single
985
+ * `$sys.Reconnect`. Mirrors C# `RpcPeerConnectionState.TryClaimReconnect`. */
986
+ protected _isReconnectClaimed: boolean;
984
987
  protected _connection: RpcConnection | undefined;
985
988
  /** Mirror of `_connectionState === Connected`. True only after the
986
989
  * handshake round-trip completes; outbound `call()` checks this to
@@ -1013,6 +1016,8 @@ declare abstract class RpcPeer {
1013
1016
  get connectionState(): RpcConnectionState;
1014
1017
  get isConnected(): boolean;
1015
1018
  get ownHandshakeIndex(): number;
1019
+ tryClaimReconnect(): boolean;
1020
+ protected nextOwnHandshakeIndex(): number;
1016
1021
  protected _setConnectionState(value: RpcConnectionState): void;
1017
1022
  /** Resolves on the next transition into `Connected` — or immediately if
1018
1023
  * already in that state. */
package/dist/index.d.ts CHANGED
@@ -981,6 +981,9 @@ declare abstract class RpcPeer {
981
981
  * stale `$sys.Reconnect` that references an older connection generation
982
982
  * (C# `RpcSystemCalls.Reconnect`'s `ownHandshake.Index` check). */
983
983
  protected _ownHandshakeIndex: number;
984
+ /** Whether the current connection generation has already used its single
985
+ * `$sys.Reconnect`. Mirrors C# `RpcPeerConnectionState.TryClaimReconnect`. */
986
+ protected _isReconnectClaimed: boolean;
984
987
  protected _connection: RpcConnection | undefined;
985
988
  /** Mirror of `_connectionState === Connected`. True only after the
986
989
  * handshake round-trip completes; outbound `call()` checks this to
@@ -1013,6 +1016,8 @@ declare abstract class RpcPeer {
1013
1016
  get connectionState(): RpcConnectionState;
1014
1017
  get isConnected(): boolean;
1015
1018
  get ownHandshakeIndex(): number;
1019
+ tryClaimReconnect(): boolean;
1020
+ protected nextOwnHandshakeIndex(): number;
1016
1021
  protected _setConnectionState(value: RpcConnectionState): void;
1017
1022
  /** Resolves on the next transition into `Connected` — or immediately if
1018
1023
  * already in that state. */
package/dist/index.js CHANGED
@@ -1172,6 +1172,15 @@ var RpcSystemCallHandler = class {
1172
1172
  );
1173
1173
  return;
1174
1174
  }
1175
+ if (!peer.tryClaimReconnect()) {
1176
+ peer.hub.systemCallSender.error(
1177
+ peer.connection,
1178
+ peer.serializationFormat,
1179
+ relatedId,
1180
+ new Error("TooLateToReconnect: this connection was already reconnected")
1181
+ );
1182
+ return;
1183
+ }
1175
1184
  let unknownIds = [];
1176
1185
  try {
1177
1186
  const stagesRaw = args[1];
@@ -2636,6 +2645,9 @@ var RpcPeer = class {
2636
2645
  * stale `$sys.Reconnect` that references an older connection generation
2637
2646
  * (C# `RpcSystemCalls.Reconnect`'s `ownHandshake.Index` check). */
2638
2647
  _ownHandshakeIndex = 0;
2648
+ /** Whether the current connection generation has already used its single
2649
+ * `$sys.Reconnect`. Mirrors C# `RpcPeerConnectionState.TryClaimReconnect`. */
2650
+ _isReconnectClaimed = false;
2639
2651
  _connection;
2640
2652
  /** Mirror of `_connectionState === Connected`. True only after the
2641
2653
  * handshake round-trip completes; outbound `call()` checks this to
@@ -2706,6 +2718,19 @@ var RpcPeer = class {
2706
2718
  get ownHandshakeIndex() {
2707
2719
  return this._ownHandshakeIndex;
2708
2720
  }
2721
+ // A conforming peer sends `$sys.Reconnect` at most once per connection, so anything
2722
+ // beyond that is a replay - and the reconciliation it performs is proportional to the
2723
+ // call ids it carries, with nothing else capping how often it can arrive.
2724
+ tryClaimReconnect() {
2725
+ if (this._isReconnectClaimed)
2726
+ return false;
2727
+ this._isReconnectClaimed = true;
2728
+ return true;
2729
+ }
2730
+ nextOwnHandshakeIndex() {
2731
+ this._isReconnectClaimed = false;
2732
+ return ++this._ownHandshakeIndex;
2733
+ }
2709
2734
  _setConnectionState(value) {
2710
2735
  if (this._connectionState === value) return;
2711
2736
  const previousState = this._connectionState;
@@ -3241,7 +3266,7 @@ var RpcClientPeer = class extends RpcPeer {
3241
3266
  this.serializationFormat,
3242
3267
  this.id,
3243
3268
  this.hub.hubId,
3244
- ++this._ownHandshakeIndex
3269
+ this.nextOwnHandshakeIndex()
3245
3270
  );
3246
3271
  } catch (e) {
3247
3272
  warnLog7?.log(`'${this.ref}': Failed to send handshake`, e);
@@ -3506,7 +3531,7 @@ var RpcServerPeer = class extends RpcPeer {
3506
3531
  this.serializationFormat,
3507
3532
  this.id,
3508
3533
  this.hub.hubId,
3509
- ++this._ownHandshakeIndex
3534
+ this.nextOwnHandshakeIndex()
3510
3535
  );
3511
3536
  this._setConnectionState(3 /* Connected */);
3512
3537
  }