@actuallab/rpc 12.4.6 → 12.4.7

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 CHANGED
@@ -1006,6 +1006,23 @@ var RpcStreamSender = class _RpcStreamSender {
1006
1006
  _lastAckedIndex = 0;
1007
1007
  _abortController = new AbortController();
1008
1008
  _iterator = null;
1009
+ // -- Recorder-controller metrics (Step 9.1) --
1010
+ /** Total items skipped via real-time `canSkipTo` compaction. */
1011
+ _skipCount = 0;
1012
+ /** Fires after a $sys.Ack has been processed (post-compaction). The
1013
+ * recorder's quality controller uses this to bump a "last ACK at"
1014
+ * watchdog so it can distinguish "stuck" (no ACK > N s) from
1015
+ * "throttled" (ACKs flowing). */
1016
+ onAckProcessed;
1017
+ get nextIndex() {
1018
+ return this._nextIndex;
1019
+ }
1020
+ get lastAckIndex() {
1021
+ return this._lastAckedIndex;
1022
+ }
1023
+ get skipCount() {
1024
+ return this._skipCount;
1025
+ }
1009
1026
  // -- ACK queue (analog of .NET's Channel<(long, bool)>) --
1010
1027
  _acks = [];
1011
1028
  _whenAckReady = null;
@@ -1240,8 +1257,16 @@ var RpcStreamSender = class _RpcStreamSender {
1240
1257
  if (bufferIndex >= buffer.count && !isFullyBuffered && buffer.hasRemainingCapacity && this._acks.length === 0) {
1241
1258
  await bufferNext(false, true);
1242
1259
  }
1243
- if (ack.nextIndex > 0)
1244
- bufferIndex = _compactBufferedUnsentSuffix(buffer, bufferIndex, this.canSkipTo);
1260
+ if (ack.nextIndex > 0) {
1261
+ const result = _compactBufferedUnsentSuffix(
1262
+ buffer,
1263
+ bufferIndex,
1264
+ this.canSkipTo
1265
+ );
1266
+ bufferIndex = result.newIndex;
1267
+ if (result.skipped > 0)
1268
+ this._skipCount += result.skipped;
1269
+ }
1245
1270
  if (this._acks.length > 0) break;
1246
1271
  }
1247
1272
  while (this._nextIndex < maxIndex && bufferIndex < buffer.count) {
@@ -1277,6 +1302,10 @@ var RpcStreamSender = class _RpcStreamSender {
1277
1302
  this._nextIndex = a.nextIndex;
1278
1303
  }
1279
1304
  }
1305
+ try {
1306
+ this.onAckProcessed?.();
1307
+ } catch {
1308
+ }
1280
1309
  return last;
1281
1310
  }
1282
1311
  /** Wait for the ACK queue to have at least one entry (or `_ended`). */
@@ -1336,14 +1365,16 @@ function _compactBufferedUnsentSuffix(buffer, firstUnsentIndex, canSkipTo) {
1336
1365
  skipToIndex = i;
1337
1366
  }
1338
1367
  if (skipToIndex <= firstUnsentIndex)
1339
- return firstUnsentIndex;
1368
+ return { newIndex: firstUnsentIndex, skipped: 0 };
1369
+ const cutFrom = firstUnsentIndex;
1370
+ const cutTo = skipToIndex;
1340
1371
  const items = buffer.toArray();
1341
1372
  buffer.clear();
1342
- for (let i = 0; i < firstUnsentIndex; i++)
1373
+ for (let i = 0; i < cutFrom; i++)
1343
1374
  buffer.pushTail(items[i]);
1344
- for (let i = skipToIndex; i < items.length; i++)
1375
+ for (let i = cutTo; i < items.length; i++)
1345
1376
  buffer.pushTail(items[i]);
1346
- return firstUnsentIndex;
1377
+ return { newIndex: firstUnsentIndex, skipped: skipToIndex - firstUnsentIndex };
1347
1378
  }
1348
1379
 
1349
1380
  // src/rpc-stream.ts
@@ -1449,6 +1480,11 @@ var RpcStream = class _RpcStream {
1449
1480
  throw new Error("toRef() must be called before awaiting whenSent.");
1450
1481
  return this._whenSent;
1451
1482
  }
1483
+ /** Local sender backing this stream after `toRef()` has been called.
1484
+ * `undefined` for remote streams or before `toRef()`. */
1485
+ get sender() {
1486
+ return this._sender;
1487
+ }
1452
1488
  /**
1453
1489
  * For local streams: bind to a peer, create and register an `RpcStreamSender`,
1454
1490
  * start pumping items from the local source in the background, and return the