@naylence/runtime 0.3.5-test.958 → 0.3.5-test.960

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.
@@ -98,12 +98,12 @@ installProcessEnvShim();
98
98
  // --- END ENV SHIM ---
99
99
 
100
100
  // This file is auto-generated during build - do not edit manually
101
- // Generated from package.json version: 0.3.5-test.958
101
+ // Generated from package.json version: 0.3.5-test.960
102
102
  /**
103
103
  * The package version, injected at build time.
104
104
  * @internal
105
105
  */
106
- const VERSION = '0.3.5-test.958';
106
+ const VERSION = '0.3.5-test.960';
107
107
 
108
108
  /**
109
109
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -1358,38 +1358,28 @@ class TaskSpawner {
1358
1358
  }
1359
1359
  }
1360
1360
 
1361
- // import { getLogger } from './logging.js';
1362
- // const logger = getLogger('naylence.fame.util.lock');
1363
1361
  class AsyncLock {
1364
1362
  constructor() {
1365
- this.queue = Promise.resolve();
1363
+ this.tail = Promise.resolve();
1366
1364
  }
1367
- async acquire(task) {
1368
- const currentQueue = this.queue;
1365
+ async runExclusive(operation) {
1369
1366
  let release;
1370
- const nextPromise = new Promise((resolve) => {
1367
+ const next = new Promise((resolve) => {
1371
1368
  release = resolve;
1372
1369
  });
1373
- // Chain the new promise to the queue
1374
- this.queue = this.queue.then(() => nextPromise, () => nextPromise);
1375
- // Wait for the previous task to complete
1376
- // logger.debug('waiting_for_lock');
1377
- await currentQueue;
1378
- // logger.debug('lock_acquired');
1370
+ const previous = this.tail;
1371
+ this.tail = previous.then(() => next, () => next);
1372
+ await previous;
1379
1373
  try {
1380
- return await task();
1374
+ return await operation();
1381
1375
  }
1382
1376
  finally {
1383
1377
  release();
1384
- // logger.debug('lock_released');
1385
1378
  }
1386
1379
  }
1387
- async runExclusive(task) {
1388
- return this.acquire(task);
1389
- }
1390
1380
  }
1391
1381
  async function withLock(lock, operation) {
1392
- return await lock.acquire(operation);
1382
+ return await lock.runExclusive(operation);
1393
1383
  }
1394
1384
 
1395
1385
  /**
@@ -9686,11 +9676,31 @@ class BaseAsyncConnector extends TaskSpawner {
9686
9676
  * Emit credit update if flow control needs refill
9687
9677
  */
9688
9678
  async _maybeEmitCredit(flowId, traceId) {
9689
- if (!this._flowCtrl.needsRefill(flowId)) {
9679
+ const remainingCredits = this._flowCtrl.getCredits(flowId);
9680
+ const needsRefill = this._flowCtrl.needsRefill(flowId);
9681
+ logger$$.debug('maybe_emit_credit_check', {
9682
+ connector_id: this._connectorFlowId,
9683
+ flow_id: flowId,
9684
+ trace_id: traceId ?? null,
9685
+ remaining_credits: remainingCredits,
9686
+ low_watermark: this._flowCtrl instanceof FlowController
9687
+ ? this._flowCtrl.lowWatermark
9688
+ : null,
9689
+ initial_window: this._initialWindow,
9690
+ needs_refill: needsRefill,
9691
+ });
9692
+ if (!needsRefill) {
9690
9693
  return;
9691
9694
  }
9692
9695
  const delta = this._initialWindow;
9693
9696
  this._flowCtrl.addCredits(flowId, delta);
9697
+ logger$$.debug('maybe_emit_credit_emit', {
9698
+ connector_id: this._connectorFlowId,
9699
+ flow_id: flowId,
9700
+ trace_id: traceId ?? null,
9701
+ emitted_credits: delta,
9702
+ post_emit_balance: this._flowCtrl.getCredits(flowId),
9703
+ });
9694
9704
  const ackEnv = core.createFameEnvelope({
9695
9705
  ...(traceId && { traceId }),
9696
9706
  flowId,
@@ -9702,7 +9712,25 @@ class BaseAsyncConnector extends TaskSpawner {
9702
9712
  },
9703
9713
  flags: core.FlowFlags.ACK,
9704
9714
  });
9705
- await this.send(ackEnv);
9715
+ try {
9716
+ await this.send(ackEnv);
9717
+ logger$$.debug('maybe_emit_credit_sent', {
9718
+ connector_id: this._connectorFlowId,
9719
+ flow_id: flowId,
9720
+ trace_id: traceId ?? null,
9721
+ credits_acknowledged: delta,
9722
+ });
9723
+ }
9724
+ catch (error) {
9725
+ logger$$.error('maybe_emit_credit_send_failed', {
9726
+ connector_id: this._connectorFlowId,
9727
+ flow_id: flowId,
9728
+ trace_id: traceId ?? null,
9729
+ credits_attempted: delta,
9730
+ error: error instanceof Error ? error.message : String(error),
9731
+ });
9732
+ throw error;
9733
+ }
9706
9734
  }
9707
9735
  // ---------------------------------------------------------------------
9708
9736
  // Shutdown Management
@@ -10233,6 +10261,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10233
10261
  const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
10234
10262
  ? senderId
10235
10263
  : undefined;
10264
+ logger$_.debug('broadcast_channel_duplicate_ack_check', {
10265
+ channel: this.channelName,
10266
+ connector_id: this.connectorId,
10267
+ sender_id: normalizedSenderId ?? null,
10268
+ dedup_key: dedupKey,
10269
+ source: 'listener',
10270
+ cache_entries: this.seenAckKeys.size,
10271
+ });
10236
10272
  return this._checkDuplicateAck(dedupKey, normalizedSenderId);
10237
10273
  }
10238
10274
  _shouldSkipDuplicateAckFromInboxItem(item) {
@@ -10255,6 +10291,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10255
10291
  return false;
10256
10292
  }
10257
10293
  const senderId = this._extractSenderIdFromInboxItem(item);
10294
+ logger$_.debug('broadcast_channel_duplicate_ack_check', {
10295
+ channel: this.channelName,
10296
+ connector_id: this.connectorId,
10297
+ sender_id: senderId ?? null,
10298
+ dedup_key: dedupKey,
10299
+ source: 'inbox_item',
10300
+ cache_entries: this.seenAckKeys.size,
10301
+ });
10258
10302
  return this._checkDuplicateAck(dedupKey, senderId);
10259
10303
  }
10260
10304
  _checkDuplicateAck(dedupKey, senderId) {
@@ -10266,11 +10310,21 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10266
10310
  connector_id: this.connectorId,
10267
10311
  sender_id: senderId ?? null,
10268
10312
  dedup_key: dedupKey,
10313
+ age_ms: now - lastSeen,
10314
+ ttl_ms: this.ackDedupTtlMs,
10315
+ cache_entries: this.seenAckKeys.size,
10269
10316
  });
10270
10317
  return true;
10271
10318
  }
10272
10319
  this.seenAckKeys.set(dedupKey, now);
10273
10320
  this.seenAckOrder.push(dedupKey);
10321
+ logger$_.debug('broadcast_channel_duplicate_ack_recorded', {
10322
+ channel: this.channelName,
10323
+ connector_id: this.connectorId,
10324
+ sender_id: senderId ?? null,
10325
+ dedup_key: dedupKey,
10326
+ cache_entries: this.seenAckKeys.size,
10327
+ });
10274
10328
  this._trimSeenAcks(now);
10275
10329
  return false;
10276
10330
  }
@@ -19981,9 +20035,6 @@ class WebSocketConnector extends BaseAsyncConnector {
19981
20035
  // Browser WebSocket or Node.js ws client
19982
20036
  this._websocket.send(data);
19983
20037
  }
19984
- logger$H.debug('websocket_sent_bytes', {
19985
- byte_length: data.length,
19986
- });
19987
20038
  }
19988
20039
  catch (error) {
19989
20040
  // Handle WebSocket disconnection errors
@@ -96,12 +96,12 @@ installProcessEnvShim();
96
96
  // --- END ENV SHIM ---
97
97
 
98
98
  // This file is auto-generated during build - do not edit manually
99
- // Generated from package.json version: 0.3.5-test.958
99
+ // Generated from package.json version: 0.3.5-test.960
100
100
  /**
101
101
  * The package version, injected at build time.
102
102
  * @internal
103
103
  */
104
- const VERSION = '0.3.5-test.958';
104
+ const VERSION = '0.3.5-test.960';
105
105
 
106
106
  /**
107
107
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -1356,38 +1356,28 @@ class TaskSpawner {
1356
1356
  }
1357
1357
  }
1358
1358
 
1359
- // import { getLogger } from './logging.js';
1360
- // const logger = getLogger('naylence.fame.util.lock');
1361
1359
  class AsyncLock {
1362
1360
  constructor() {
1363
- this.queue = Promise.resolve();
1361
+ this.tail = Promise.resolve();
1364
1362
  }
1365
- async acquire(task) {
1366
- const currentQueue = this.queue;
1363
+ async runExclusive(operation) {
1367
1364
  let release;
1368
- const nextPromise = new Promise((resolve) => {
1365
+ const next = new Promise((resolve) => {
1369
1366
  release = resolve;
1370
1367
  });
1371
- // Chain the new promise to the queue
1372
- this.queue = this.queue.then(() => nextPromise, () => nextPromise);
1373
- // Wait for the previous task to complete
1374
- // logger.debug('waiting_for_lock');
1375
- await currentQueue;
1376
- // logger.debug('lock_acquired');
1368
+ const previous = this.tail;
1369
+ this.tail = previous.then(() => next, () => next);
1370
+ await previous;
1377
1371
  try {
1378
- return await task();
1372
+ return await operation();
1379
1373
  }
1380
1374
  finally {
1381
1375
  release();
1382
- // logger.debug('lock_released');
1383
1376
  }
1384
1377
  }
1385
- async runExclusive(task) {
1386
- return this.acquire(task);
1387
- }
1388
1378
  }
1389
1379
  async function withLock(lock, operation) {
1390
- return await lock.acquire(operation);
1380
+ return await lock.runExclusive(operation);
1391
1381
  }
1392
1382
 
1393
1383
  /**
@@ -9684,11 +9674,31 @@ class BaseAsyncConnector extends TaskSpawner {
9684
9674
  * Emit credit update if flow control needs refill
9685
9675
  */
9686
9676
  async _maybeEmitCredit(flowId, traceId) {
9687
- if (!this._flowCtrl.needsRefill(flowId)) {
9677
+ const remainingCredits = this._flowCtrl.getCredits(flowId);
9678
+ const needsRefill = this._flowCtrl.needsRefill(flowId);
9679
+ logger$$.debug('maybe_emit_credit_check', {
9680
+ connector_id: this._connectorFlowId,
9681
+ flow_id: flowId,
9682
+ trace_id: traceId ?? null,
9683
+ remaining_credits: remainingCredits,
9684
+ low_watermark: this._flowCtrl instanceof FlowController
9685
+ ? this._flowCtrl.lowWatermark
9686
+ : null,
9687
+ initial_window: this._initialWindow,
9688
+ needs_refill: needsRefill,
9689
+ });
9690
+ if (!needsRefill) {
9688
9691
  return;
9689
9692
  }
9690
9693
  const delta = this._initialWindow;
9691
9694
  this._flowCtrl.addCredits(flowId, delta);
9695
+ logger$$.debug('maybe_emit_credit_emit', {
9696
+ connector_id: this._connectorFlowId,
9697
+ flow_id: flowId,
9698
+ trace_id: traceId ?? null,
9699
+ emitted_credits: delta,
9700
+ post_emit_balance: this._flowCtrl.getCredits(flowId),
9701
+ });
9692
9702
  const ackEnv = createFameEnvelope({
9693
9703
  ...(traceId && { traceId }),
9694
9704
  flowId,
@@ -9700,7 +9710,25 @@ class BaseAsyncConnector extends TaskSpawner {
9700
9710
  },
9701
9711
  flags: FlowFlags.ACK,
9702
9712
  });
9703
- await this.send(ackEnv);
9713
+ try {
9714
+ await this.send(ackEnv);
9715
+ logger$$.debug('maybe_emit_credit_sent', {
9716
+ connector_id: this._connectorFlowId,
9717
+ flow_id: flowId,
9718
+ trace_id: traceId ?? null,
9719
+ credits_acknowledged: delta,
9720
+ });
9721
+ }
9722
+ catch (error) {
9723
+ logger$$.error('maybe_emit_credit_send_failed', {
9724
+ connector_id: this._connectorFlowId,
9725
+ flow_id: flowId,
9726
+ trace_id: traceId ?? null,
9727
+ credits_attempted: delta,
9728
+ error: error instanceof Error ? error.message : String(error),
9729
+ });
9730
+ throw error;
9731
+ }
9704
9732
  }
9705
9733
  // ---------------------------------------------------------------------
9706
9734
  // Shutdown Management
@@ -10231,6 +10259,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10231
10259
  const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
10232
10260
  ? senderId
10233
10261
  : undefined;
10262
+ logger$_.debug('broadcast_channel_duplicate_ack_check', {
10263
+ channel: this.channelName,
10264
+ connector_id: this.connectorId,
10265
+ sender_id: normalizedSenderId ?? null,
10266
+ dedup_key: dedupKey,
10267
+ source: 'listener',
10268
+ cache_entries: this.seenAckKeys.size,
10269
+ });
10234
10270
  return this._checkDuplicateAck(dedupKey, normalizedSenderId);
10235
10271
  }
10236
10272
  _shouldSkipDuplicateAckFromInboxItem(item) {
@@ -10253,6 +10289,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10253
10289
  return false;
10254
10290
  }
10255
10291
  const senderId = this._extractSenderIdFromInboxItem(item);
10292
+ logger$_.debug('broadcast_channel_duplicate_ack_check', {
10293
+ channel: this.channelName,
10294
+ connector_id: this.connectorId,
10295
+ sender_id: senderId ?? null,
10296
+ dedup_key: dedupKey,
10297
+ source: 'inbox_item',
10298
+ cache_entries: this.seenAckKeys.size,
10299
+ });
10256
10300
  return this._checkDuplicateAck(dedupKey, senderId);
10257
10301
  }
10258
10302
  _checkDuplicateAck(dedupKey, senderId) {
@@ -10264,11 +10308,21 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10264
10308
  connector_id: this.connectorId,
10265
10309
  sender_id: senderId ?? null,
10266
10310
  dedup_key: dedupKey,
10311
+ age_ms: now - lastSeen,
10312
+ ttl_ms: this.ackDedupTtlMs,
10313
+ cache_entries: this.seenAckKeys.size,
10267
10314
  });
10268
10315
  return true;
10269
10316
  }
10270
10317
  this.seenAckKeys.set(dedupKey, now);
10271
10318
  this.seenAckOrder.push(dedupKey);
10319
+ logger$_.debug('broadcast_channel_duplicate_ack_recorded', {
10320
+ channel: this.channelName,
10321
+ connector_id: this.connectorId,
10322
+ sender_id: senderId ?? null,
10323
+ dedup_key: dedupKey,
10324
+ cache_entries: this.seenAckKeys.size,
10325
+ });
10272
10326
  this._trimSeenAcks(now);
10273
10327
  return false;
10274
10328
  }
@@ -19979,9 +20033,6 @@ class WebSocketConnector extends BaseAsyncConnector {
19979
20033
  // Browser WebSocket or Node.js ws client
19980
20034
  this._websocket.send(data);
19981
20035
  }
19982
- logger$H.debug('websocket_sent_bytes', {
19983
- byte_length: data.length,
19984
- });
19985
20036
  }
19986
20037
  catch (error) {
19987
20038
  // Handle WebSocket disconnection errors
@@ -509,11 +509,31 @@ class BaseAsyncConnector extends task_spawner_js_1.TaskSpawner {
509
509
  * Emit credit update if flow control needs refill
510
510
  */
511
511
  async _maybeEmitCredit(flowId, traceId) {
512
- if (!this._flowCtrl.needsRefill(flowId)) {
512
+ const remainingCredits = this._flowCtrl.getCredits(flowId);
513
+ const needsRefill = this._flowCtrl.needsRefill(flowId);
514
+ logger.debug('maybe_emit_credit_check', {
515
+ connector_id: this._connectorFlowId,
516
+ flow_id: flowId,
517
+ trace_id: traceId ?? null,
518
+ remaining_credits: remainingCredits,
519
+ low_watermark: this._flowCtrl instanceof flow_controller_js_1.FlowController
520
+ ? this._flowCtrl.lowWatermark
521
+ : null,
522
+ initial_window: this._initialWindow,
523
+ needs_refill: needsRefill,
524
+ });
525
+ if (!needsRefill) {
513
526
  return;
514
527
  }
515
528
  const delta = this._initialWindow;
516
529
  this._flowCtrl.addCredits(flowId, delta);
530
+ logger.debug('maybe_emit_credit_emit', {
531
+ connector_id: this._connectorFlowId,
532
+ flow_id: flowId,
533
+ trace_id: traceId ?? null,
534
+ emitted_credits: delta,
535
+ post_emit_balance: this._flowCtrl.getCredits(flowId),
536
+ });
517
537
  const ackEnv = (0, core_1.createFameEnvelope)({
518
538
  ...(traceId && { traceId }),
519
539
  flowId,
@@ -525,7 +545,25 @@ class BaseAsyncConnector extends task_spawner_js_1.TaskSpawner {
525
545
  },
526
546
  flags: core_1.FlowFlags.ACK,
527
547
  });
528
- await this.send(ackEnv);
548
+ try {
549
+ await this.send(ackEnv);
550
+ logger.debug('maybe_emit_credit_sent', {
551
+ connector_id: this._connectorFlowId,
552
+ flow_id: flowId,
553
+ trace_id: traceId ?? null,
554
+ credits_acknowledged: delta,
555
+ });
556
+ }
557
+ catch (error) {
558
+ logger.error('maybe_emit_credit_send_failed', {
559
+ connector_id: this._connectorFlowId,
560
+ flow_id: flowId,
561
+ trace_id: traceId ?? null,
562
+ credits_attempted: delta,
563
+ error: error instanceof Error ? error.message : String(error),
564
+ });
565
+ throw error;
566
+ }
529
567
  }
530
568
  // ---------------------------------------------------------------------
531
569
  // Shutdown Management
@@ -364,6 +364,14 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
364
364
  const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
365
365
  ? senderId
366
366
  : undefined;
367
+ logger.debug('broadcast_channel_duplicate_ack_check', {
368
+ channel: this.channelName,
369
+ connector_id: this.connectorId,
370
+ sender_id: normalizedSenderId ?? null,
371
+ dedup_key: dedupKey,
372
+ source: 'listener',
373
+ cache_entries: this.seenAckKeys.size,
374
+ });
367
375
  return this._checkDuplicateAck(dedupKey, normalizedSenderId);
368
376
  }
369
377
  _shouldSkipDuplicateAckFromInboxItem(item) {
@@ -386,6 +394,14 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
386
394
  return false;
387
395
  }
388
396
  const senderId = this._extractSenderIdFromInboxItem(item);
397
+ logger.debug('broadcast_channel_duplicate_ack_check', {
398
+ channel: this.channelName,
399
+ connector_id: this.connectorId,
400
+ sender_id: senderId ?? null,
401
+ dedup_key: dedupKey,
402
+ source: 'inbox_item',
403
+ cache_entries: this.seenAckKeys.size,
404
+ });
389
405
  return this._checkDuplicateAck(dedupKey, senderId);
390
406
  }
391
407
  _checkDuplicateAck(dedupKey, senderId) {
@@ -397,11 +413,21 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
397
413
  connector_id: this.connectorId,
398
414
  sender_id: senderId ?? null,
399
415
  dedup_key: dedupKey,
416
+ age_ms: now - lastSeen,
417
+ ttl_ms: this.ackDedupTtlMs,
418
+ cache_entries: this.seenAckKeys.size,
400
419
  });
401
420
  return true;
402
421
  }
403
422
  this.seenAckKeys.set(dedupKey, now);
404
423
  this.seenAckOrder.push(dedupKey);
424
+ logger.debug('broadcast_channel_duplicate_ack_recorded', {
425
+ channel: this.channelName,
426
+ connector_id: this.connectorId,
427
+ sender_id: senderId ?? null,
428
+ dedup_key: dedupKey,
429
+ cache_entries: this.seenAckKeys.size,
430
+ });
405
431
  this._trimSeenAcks(now);
406
432
  return false;
407
433
  }
@@ -143,9 +143,6 @@ class WebSocketConnector extends base_async_connector_js_1.BaseAsyncConnector {
143
143
  // Browser WebSocket or Node.js ws client
144
144
  this._websocket.send(data);
145
145
  }
146
- logger.debug('websocket_sent_bytes', {
147
- byte_length: data.length,
148
- });
149
146
  }
150
147
  catch (error) {
151
148
  // Handle WebSocket disconnection errors
@@ -1,38 +1,28 @@
1
1
  "use strict";
2
- // import { getLogger } from './logging.js';
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.AsyncLock = void 0;
5
4
  exports.withLock = withLock;
6
- // const logger = getLogger('naylence.fame.util.lock');
7
5
  class AsyncLock {
8
6
  constructor() {
9
- this.queue = Promise.resolve();
7
+ this.tail = Promise.resolve();
10
8
  }
11
- async acquire(task) {
12
- const currentQueue = this.queue;
9
+ async runExclusive(operation) {
13
10
  let release;
14
- const nextPromise = new Promise((resolve) => {
11
+ const next = new Promise((resolve) => {
15
12
  release = resolve;
16
13
  });
17
- // Chain the new promise to the queue
18
- this.queue = this.queue.then(() => nextPromise, () => nextPromise);
19
- // Wait for the previous task to complete
20
- // logger.debug('waiting_for_lock');
21
- await currentQueue;
22
- // logger.debug('lock_acquired');
14
+ const previous = this.tail;
15
+ this.tail = previous.then(() => next, () => next);
16
+ await previous;
23
17
  try {
24
- return await task();
18
+ return await operation();
25
19
  }
26
20
  finally {
27
21
  release();
28
- // logger.debug('lock_released');
29
22
  }
30
23
  }
31
- async runExclusive(task) {
32
- return this.acquire(task);
33
- }
34
24
  }
35
25
  exports.AsyncLock = AsyncLock;
36
26
  async function withLock(lock, operation) {
37
- return await lock.acquire(operation);
27
+ return await lock.runExclusive(operation);
38
28
  }
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  // This file is auto-generated during build - do not edit manually
3
- // Generated from package.json version: 0.3.5-test.958
3
+ // Generated from package.json version: 0.3.5-test.960
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.VERSION = void 0;
6
6
  /**
7
7
  * The package version, injected at build time.
8
8
  * @internal
9
9
  */
10
- exports.VERSION = '0.3.5-test.958';
10
+ exports.VERSION = '0.3.5-test.960';
@@ -505,11 +505,31 @@ export class BaseAsyncConnector extends TaskSpawner {
505
505
  * Emit credit update if flow control needs refill
506
506
  */
507
507
  async _maybeEmitCredit(flowId, traceId) {
508
- if (!this._flowCtrl.needsRefill(flowId)) {
508
+ const remainingCredits = this._flowCtrl.getCredits(flowId);
509
+ const needsRefill = this._flowCtrl.needsRefill(flowId);
510
+ logger.debug('maybe_emit_credit_check', {
511
+ connector_id: this._connectorFlowId,
512
+ flow_id: flowId,
513
+ trace_id: traceId ?? null,
514
+ remaining_credits: remainingCredits,
515
+ low_watermark: this._flowCtrl instanceof FlowController
516
+ ? this._flowCtrl.lowWatermark
517
+ : null,
518
+ initial_window: this._initialWindow,
519
+ needs_refill: needsRefill,
520
+ });
521
+ if (!needsRefill) {
509
522
  return;
510
523
  }
511
524
  const delta = this._initialWindow;
512
525
  this._flowCtrl.addCredits(flowId, delta);
526
+ logger.debug('maybe_emit_credit_emit', {
527
+ connector_id: this._connectorFlowId,
528
+ flow_id: flowId,
529
+ trace_id: traceId ?? null,
530
+ emitted_credits: delta,
531
+ post_emit_balance: this._flowCtrl.getCredits(flowId),
532
+ });
513
533
  const ackEnv = createFameEnvelope({
514
534
  ...(traceId && { traceId }),
515
535
  flowId,
@@ -521,7 +541,25 @@ export class BaseAsyncConnector extends TaskSpawner {
521
541
  },
522
542
  flags: FlowFlags.ACK,
523
543
  });
524
- await this.send(ackEnv);
544
+ try {
545
+ await this.send(ackEnv);
546
+ logger.debug('maybe_emit_credit_sent', {
547
+ connector_id: this._connectorFlowId,
548
+ flow_id: flowId,
549
+ trace_id: traceId ?? null,
550
+ credits_acknowledged: delta,
551
+ });
552
+ }
553
+ catch (error) {
554
+ logger.error('maybe_emit_credit_send_failed', {
555
+ connector_id: this._connectorFlowId,
556
+ flow_id: flowId,
557
+ trace_id: traceId ?? null,
558
+ credits_attempted: delta,
559
+ error: error instanceof Error ? error.message : String(error),
560
+ });
561
+ throw error;
562
+ }
525
563
  }
526
564
  // ---------------------------------------------------------------------
527
565
  // Shutdown Management
@@ -361,6 +361,14 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
361
361
  const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
362
362
  ? senderId
363
363
  : undefined;
364
+ logger.debug('broadcast_channel_duplicate_ack_check', {
365
+ channel: this.channelName,
366
+ connector_id: this.connectorId,
367
+ sender_id: normalizedSenderId ?? null,
368
+ dedup_key: dedupKey,
369
+ source: 'listener',
370
+ cache_entries: this.seenAckKeys.size,
371
+ });
364
372
  return this._checkDuplicateAck(dedupKey, normalizedSenderId);
365
373
  }
366
374
  _shouldSkipDuplicateAckFromInboxItem(item) {
@@ -383,6 +391,14 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
383
391
  return false;
384
392
  }
385
393
  const senderId = this._extractSenderIdFromInboxItem(item);
394
+ logger.debug('broadcast_channel_duplicate_ack_check', {
395
+ channel: this.channelName,
396
+ connector_id: this.connectorId,
397
+ sender_id: senderId ?? null,
398
+ dedup_key: dedupKey,
399
+ source: 'inbox_item',
400
+ cache_entries: this.seenAckKeys.size,
401
+ });
386
402
  return this._checkDuplicateAck(dedupKey, senderId);
387
403
  }
388
404
  _checkDuplicateAck(dedupKey, senderId) {
@@ -394,11 +410,21 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
394
410
  connector_id: this.connectorId,
395
411
  sender_id: senderId ?? null,
396
412
  dedup_key: dedupKey,
413
+ age_ms: now - lastSeen,
414
+ ttl_ms: this.ackDedupTtlMs,
415
+ cache_entries: this.seenAckKeys.size,
397
416
  });
398
417
  return true;
399
418
  }
400
419
  this.seenAckKeys.set(dedupKey, now);
401
420
  this.seenAckOrder.push(dedupKey);
421
+ logger.debug('broadcast_channel_duplicate_ack_recorded', {
422
+ channel: this.channelName,
423
+ connector_id: this.connectorId,
424
+ sender_id: senderId ?? null,
425
+ dedup_key: dedupKey,
426
+ cache_entries: this.seenAckKeys.size,
427
+ });
402
428
  this._trimSeenAcks(now);
403
429
  return false;
404
430
  }
@@ -140,9 +140,6 @@ export class WebSocketConnector extends BaseAsyncConnector {
140
140
  // Browser WebSocket or Node.js ws client
141
141
  this._websocket.send(data);
142
142
  }
143
- logger.debug('websocket_sent_bytes', {
144
- byte_length: data.length,
145
- });
146
143
  }
147
144
  catch (error) {
148
145
  // Handle WebSocket disconnection errors