@actuallab/rpc 14.2.23 → 14.3.16

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
@@ -1516,6 +1516,7 @@ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
1516
1516
  private _complete;
1517
1517
  private _failProtocol;
1518
1518
  private _isBeyondAckWindow;
1519
+ private _ackWindowSize;
1519
1520
  private _ackWindowError;
1520
1521
  private _gapError;
1521
1522
  private _notifyConsumer;
package/dist/index.d.ts CHANGED
@@ -1516,6 +1516,7 @@ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
1516
1516
  private _complete;
1517
1517
  private _failProtocol;
1518
1518
  private _isBeyondAckWindow;
1519
+ private _ackWindowSize;
1519
1520
  private _ackWindowError;
1520
1521
  private _gapError;
1521
1522
  private _notifyConsumer;
package/dist/index.js CHANGED
@@ -1912,6 +1912,7 @@ function _compactBufferedUnsentSuffix(buffer, firstUnsentIndex, canSkipTo) {
1912
1912
  var { warnLog: warnLog6 } = getLogs("RpcStream");
1913
1913
  var DEFAULT_ACK_PERIOD2 = 30;
1914
1914
  var DEFAULT_ACK_ADVANCE2 = 61;
1915
+ var MAX_BATCH_SIZE = 1024;
1915
1916
  function parseStreamRef(value) {
1916
1917
  if (typeof value === "string") {
1917
1918
  const parts = value.split(",");
@@ -2099,6 +2100,10 @@ var RpcStream = class _RpcStream {
2099
2100
  this._failProtocol(`invalid $sys.B index/length: ${String(index)}/${String(items.length)}`);
2100
2101
  return;
2101
2102
  }
2103
+ if (items.length > MAX_BATCH_SIZE) {
2104
+ this._failProtocol(`$sys.B batch is too large: ${items.length} > ${MAX_BATCH_SIZE}`);
2105
+ return;
2106
+ }
2102
2107
  if (index > this._nextExpectedIndex) {
2103
2108
  warnLog6?.log(`batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`);
2104
2109
  if (!this.allowReconnect) {
@@ -2233,11 +2238,23 @@ var RpcStream = class _RpcStream {
2233
2238
  // last acknowledged index. The sending side is the only place that window
2234
2239
  // was ever enforced, which left a flooding remote free to grow our buffer
2235
2240
  // without bound (I6) — so we enforce our half of the contract here.
2241
+ //
2242
+ // The window is credited by consumption, never by `_ackSentUpTo`: a reset ack
2243
+ // re-bases to what we've *received*, so crediting it would let a peer ratchet
2244
+ // its own limit up by alternating "fill the window" with a forced gap.
2245
+ // Twice ackAdvance is what a conforming sender can leave buffered (ackAdvance
2246
+ // in steady state, plus ackAdvance more after a reset re-bases it), and
2247
+ // ackPeriod covers the lag of acks behind consumption.
2236
2248
  _isBeyondAckWindow(nextExpectedIndex) {
2237
- return this.ackAdvance > 0 && nextExpectedIndex > this._ackSentUpTo + this.ackAdvance;
2249
+ if (this.ackAdvance <= 0)
2250
+ return false;
2251
+ return nextExpectedIndex > this._nextConsumedIndex + this._ackWindowSize();
2252
+ }
2253
+ _ackWindowSize() {
2254
+ return 2 * this.ackAdvance + this.ackPeriod;
2238
2255
  }
2239
2256
  _ackWindowError(nextExpectedIndex) {
2240
- return `Stream ran past its ack window: reached ${nextExpectedIndex}, acked ${this._ackSentUpTo}, ackAdvance ${this.ackAdvance}`;
2257
+ return `Stream ran past its ack window: reached ${nextExpectedIndex}, consumed ${this._nextConsumedIndex}, ackAdvance ${this.ackAdvance}`;
2241
2258
  }
2242
2259
  _gapError(index) {
2243
2260
  return new Error(