@naylence/runtime 0.3.5-test.954 → 0.3.5-test.955

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.
@@ -14,12 +14,12 @@ var fastify = require('fastify');
14
14
  var websocketPlugin = require('@fastify/websocket');
15
15
 
16
16
  // This file is auto-generated during build - do not edit manually
17
- // Generated from package.json version: 0.3.5-test.954
17
+ // Generated from package.json version: 0.3.5-test.955
18
18
  /**
19
19
  * The package version, injected at build time.
20
20
  * @internal
21
21
  */
22
- const VERSION = '0.3.5-test.954';
22
+ const VERSION = '0.3.5-test.955';
23
23
 
24
24
  /**
25
25
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -837,7 +837,7 @@ class TaskCancelledError extends Error {
837
837
  * Provides functionality similar to Python's asyncio TaskSpawner with proper
838
838
  * error handling, cancellation, and graceful shutdown capabilities.
839
839
  */
840
- const logger$1b = getLogger('naylence.fame.util.task_spawner');
840
+ const logger$1c = getLogger('naylence.fame.util.task_spawner');
841
841
  function firstDefined(source, keys) {
842
842
  for (const key of keys) {
843
843
  if (Object.prototype.hasOwnProperty.call(source, key)) {
@@ -998,7 +998,7 @@ class TaskSpawner {
998
998
  const taskId = `task-${++this._taskCounter}`;
999
999
  const taskName = normalizedOptions.name || `unnamed-${taskId}`;
1000
1000
  const timeout = normalizedOptions.timeout ?? this._config.defaultTimeout;
1001
- logger$1b.debug('starting_background_task', {
1001
+ logger$1c.debug('starting_background_task', {
1002
1002
  task_name: taskName,
1003
1003
  task_id: taskId,
1004
1004
  });
@@ -1015,7 +1015,7 @@ class TaskSpawner {
1015
1015
  task.promise
1016
1016
  .then(() => {
1017
1017
  if (!this._suppressCompletionLogging) {
1018
- logger$1b.debug('task_completed_successfully', {
1018
+ logger$1c.debug('task_completed_successfully', {
1019
1019
  task_name: taskName,
1020
1020
  task_id: taskId,
1021
1021
  duration_ms: Date.now() - task.startTime,
@@ -1069,7 +1069,7 @@ class TaskSpawner {
1069
1069
  error.name === 'AbortError' ||
1070
1070
  error.message === 'Task cancelled' ||
1071
1071
  error.message === 'Aborted') {
1072
- logger$1b.debug('task_cancelled', {
1072
+ logger$1c.debug('task_cancelled', {
1073
1073
  task_name: taskName,
1074
1074
  note: 'Task cancelled as requested',
1075
1075
  });
@@ -1077,7 +1077,7 @@ class TaskSpawner {
1077
1077
  }
1078
1078
  // Handle timeout
1079
1079
  if (error instanceof TaskTimeoutError) {
1080
- logger$1b.warning('task_timed_out', {
1080
+ logger$1c.warning('task_timed_out', {
1081
1081
  task_name: taskName,
1082
1082
  error: error.message,
1083
1083
  });
@@ -1089,7 +1089,7 @@ class TaskSpawner {
1089
1089
  // Handle known WebSocket shutdown race condition (similar to Python version)
1090
1090
  if (error.message.includes("await wasn't used with future") ||
1091
1091
  error.message.includes('WebSocket closed during receive')) {
1092
- logger$1b.debug('task_shutdown_race_condition_handled', {
1092
+ logger$1c.debug('task_shutdown_race_condition_handled', {
1093
1093
  task_name: taskName,
1094
1094
  note: 'Normal WebSocket close timing during shutdown - not an error',
1095
1095
  });
@@ -1099,7 +1099,7 @@ class TaskSpawner {
1099
1099
  if (error.name === 'FameTransportClose' ||
1100
1100
  error.message.includes('normal closure') ||
1101
1101
  error.message.includes('Connection closed')) {
1102
- logger$1b.debug('task_shutdown_completed_normally', {
1102
+ logger$1c.debug('task_shutdown_completed_normally', {
1103
1103
  task_name: taskName,
1104
1104
  note: 'Task closed normally during shutdown',
1105
1105
  });
@@ -1112,14 +1112,14 @@ class TaskSpawner {
1112
1112
  // Log retriable errors as warnings (they'll be retried by upstream logic)
1113
1113
  // Log non-retriable errors as errors (fatal failures)
1114
1114
  if (isRetriableError) {
1115
- logger$1b.warning('background_task_failed', {
1115
+ logger$1c.warning('background_task_failed', {
1116
1116
  task_name: taskName,
1117
1117
  error: error.message,
1118
1118
  retriable: true,
1119
1119
  });
1120
1120
  }
1121
1121
  else {
1122
- logger$1b.error('background_task_failed', {
1122
+ logger$1c.error('background_task_failed', {
1123
1123
  task_name: taskName,
1124
1124
  error: error.message,
1125
1125
  stack: error.stack,
@@ -1138,11 +1138,11 @@ class TaskSpawner {
1138
1138
  async shutdownTasks(options = {}) {
1139
1139
  const { gracePeriod, cancelHanging, joinTimeout } = normalizeShutdownOptions(options);
1140
1140
  if (this._tasks.size === 0) {
1141
- logger$1b.debug('shutdown_tasks_no_tasks_to_shutdown');
1141
+ logger$1c.debug('shutdown_tasks_no_tasks_to_shutdown');
1142
1142
  return;
1143
1143
  }
1144
1144
  this._suppressCompletionLogging = true;
1145
- logger$1b.debug('shutting_down_tasks', {
1145
+ logger$1c.debug('shutting_down_tasks', {
1146
1146
  task_count: this._tasks.size,
1147
1147
  task_names: Array.from(this._tasks.values()).map((t) => t.name),
1148
1148
  grace_period_ms: gracePeriod,
@@ -1157,7 +1157,7 @@ class TaskSpawner {
1157
1157
  if (cancelHanging) {
1158
1158
  const stillRunning = tasks.filter((task) => task.getState() === TaskState.RUNNING && !completed.has(task));
1159
1159
  if (stillRunning.length > 0) {
1160
- logger$1b.debug('tasks_did_not_complete_within_grace_period', {
1160
+ logger$1c.debug('tasks_did_not_complete_within_grace_period', {
1161
1161
  hanging_count: stillRunning.length,
1162
1162
  });
1163
1163
  // Wait for them to finish with individual timeouts
@@ -1167,7 +1167,7 @@ class TaskSpawner {
1167
1167
  }
1168
1168
  catch (error) {
1169
1169
  if (error instanceof TaskTimeoutError) {
1170
- logger$1b.warning('task_did_not_shutdown', {
1170
+ logger$1c.warning('task_did_not_shutdown', {
1171
1171
  task_name: task.name || task.id,
1172
1172
  join_timeout_ms: joinTimeout,
1173
1173
  });
@@ -1178,7 +1178,7 @@ class TaskSpawner {
1178
1178
  }
1179
1179
  else if (!(error instanceof TaskCancelledError)) {
1180
1180
  /* istanbul ignore next - unreachable defensive branch */
1181
- logger$1b.error('task_raised_during_cancellation', {
1181
+ logger$1c.error('task_raised_during_cancellation', {
1182
1182
  task_name: task.name || task.id,
1183
1183
  error: error instanceof Error ? error.message : String(error),
1184
1184
  });
@@ -2271,6 +2271,7 @@ function validateKeyCorrelationTtlSec(ttlSec) {
2271
2271
  * condition/promise and ensure at most one notifier coroutine exists for a
2272
2272
  * flow at any time.
2273
2273
  */
2274
+ const logger$1b = getLogger('naylence.fame.flow.flow_controller');
2274
2275
  /**
2275
2276
  * Simple condition variable implementation for TypeScript/Node.js
2276
2277
  * Similar to Python's asyncio.Condition
@@ -2396,8 +2397,17 @@ class FlowController {
2396
2397
  // clamp into [0, initialWindow]
2397
2398
  const newBalance = Math.max(0, Math.min(this.initialWindow, prev + delta));
2398
2399
  this.credits.set(flowId, newBalance);
2400
+ const crossedZero = prev <= 0 && newBalance > 0;
2401
+ logger$1b.debug('flow_controller_add_credits', {
2402
+ flow_id: flowId,
2403
+ delta,
2404
+ prev_balance: prev,
2405
+ new_balance: newBalance,
2406
+ initial_window: this.initialWindow,
2407
+ crossed_zero: crossedZero,
2408
+ });
2399
2409
  // wake waiters only if we crossed the zero boundary
2400
- if (prev <= 0 && newBalance > 0) {
2410
+ if (crossedZero) {
2401
2411
  this.wakeWaiters(flowId);
2402
2412
  }
2403
2413
  return newBalance;
@@ -2408,11 +2418,27 @@ class FlowController {
2408
2418
  async acquire(flowId) {
2409
2419
  this.ensureFlow(flowId);
2410
2420
  const condition = this.conditions.get(flowId);
2421
+ logger$1b.debug('flow_controller_acquire_attempt', {
2422
+ flow_id: flowId,
2423
+ current_balance: this.credits.get(flowId),
2424
+ });
2411
2425
  while (this.credits.get(flowId) <= 0) {
2426
+ logger$1b.debug('flow_controller_waiting_for_credit', {
2427
+ flow_id: flowId,
2428
+ });
2412
2429
  await condition.wait();
2430
+ logger$1b.debug('flow_controller_woke_with_credit', {
2431
+ flow_id: flowId,
2432
+ balance_after_wake: this.credits.get(flowId),
2433
+ });
2413
2434
  }
2414
2435
  const current = this.credits.get(flowId);
2415
2436
  this.credits.set(flowId, current - 1);
2437
+ logger$1b.debug('flow_controller_credit_consumed', {
2438
+ flow_id: flowId,
2439
+ prev_balance: current,
2440
+ remaining_balance: current - 1,
2441
+ });
2416
2442
  }
2417
2443
  /**
2418
2444
  * Consume *credits* immediately (non-blocking).
@@ -2432,6 +2458,12 @@ class FlowController {
2432
2458
  const current = this.credits.get(flowId);
2433
2459
  const remaining = Math.max(current - credits, 0);
2434
2460
  this.credits.set(flowId, remaining);
2461
+ logger$1b.debug('flow_controller_consume', {
2462
+ flow_id: flowId,
2463
+ requested: credits,
2464
+ prev_balance: current,
2465
+ remaining_balance: remaining,
2466
+ });
2435
2467
  return remaining;
2436
2468
  }
2437
2469
  /**
@@ -2452,6 +2484,10 @@ class FlowController {
2452
2484
  this.windowIds.delete(flowId);
2453
2485
  this.credits.set(flowId, this.initialWindow);
2454
2486
  this.wakeWaiters(flowId);
2487
+ logger$1b.debug('flow_controller_flow_reset', {
2488
+ flow_id: flowId,
2489
+ reset_balance: this.initialWindow,
2490
+ });
2455
2491
  }
2456
2492
  /**
2457
2493
  * Return `[windowId, flags]` for the next outbound envelope.
@@ -9797,6 +9833,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9797
9833
  ? Math.floor(config.inboxCapacity)
9798
9834
  : DEFAULT_INBOX_CAPACITY$7;
9799
9835
  this.inbox = new BoundedAsyncQueue(preferredCapacity);
9836
+ this.inboxCapacity = preferredCapacity;
9800
9837
  this.connectorId = BroadcastChannelConnector.generateConnectorId();
9801
9838
  this.channel = new BroadcastChannel(this.channelName);
9802
9839
  logger$_.debug('broadcast_channel_connector_created', {
@@ -9856,15 +9893,27 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9856
9893
  if (typeof this.inbox.tryEnqueue === 'function') {
9857
9894
  const accepted = this.inbox.tryEnqueue(payload);
9858
9895
  if (accepted) {
9896
+ this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
9897
+ source: 'listener',
9898
+ enqueue_strategy: 'try',
9899
+ payload_length: payload.byteLength,
9900
+ });
9859
9901
  return;
9860
9902
  }
9861
9903
  }
9862
9904
  this.inbox.enqueue(payload);
9905
+ this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
9906
+ source: 'listener',
9907
+ enqueue_strategy: 'enqueue',
9908
+ payload_length: payload.byteLength,
9909
+ });
9863
9910
  }
9864
9911
  catch (error) {
9865
9912
  if (error instanceof QueueFullError) {
9866
9913
  logger$_.warning('broadcast_channel_receive_queue_full', {
9867
9914
  channel: this.channelName,
9915
+ inbox_capacity: this.inboxCapacity,
9916
+ inbox_remaining_capacity: this.inbox.remainingCapacity,
9868
9917
  });
9869
9918
  }
9870
9919
  else {
@@ -9948,15 +9997,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9948
9997
  if (typeof this.inbox.tryEnqueue === 'function') {
9949
9998
  const accepted = this.inbox.tryEnqueue(item);
9950
9999
  if (accepted) {
10000
+ this.logInboxSnapshot('broadcast_channel_push_enqueued', {
10001
+ enqueue_strategy: 'try',
10002
+ item_type: this._describeInboxItem(item),
10003
+ });
9951
10004
  return;
9952
10005
  }
9953
10006
  }
9954
10007
  this.inbox.enqueue(item);
10008
+ this.logInboxSnapshot('broadcast_channel_push_enqueued', {
10009
+ enqueue_strategy: 'enqueue',
10010
+ item_type: this._describeInboxItem(item),
10011
+ });
9955
10012
  }
9956
10013
  catch (error) {
9957
10014
  if (error instanceof QueueFullError) {
9958
10015
  logger$_.warning('broadcast_channel_push_queue_full', {
9959
10016
  channel: this.channelName,
10017
+ inbox_capacity: this.inboxCapacity,
10018
+ inbox_remaining_capacity: this.inbox.remainingCapacity,
9960
10019
  });
9961
10020
  throw error;
9962
10021
  }
@@ -9979,7 +10038,11 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9979
10038
  });
9980
10039
  }
9981
10040
  async _transportReceive() {
9982
- return await this.inbox.dequeue();
10041
+ const item = await this.inbox.dequeue();
10042
+ this.logInboxSnapshot('broadcast_channel_inbox_dequeued', {
10043
+ item_type: this._describeInboxItem(item),
10044
+ });
10045
+ return item;
9983
10046
  }
9984
10047
  async _transportClose(code, reason) {
9985
10048
  logger$_.debug('broadcast_channel_transport_closing', {
@@ -10033,6 +10096,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10033
10096
  }
10034
10097
  return rawOrEnvelope;
10035
10098
  }
10099
+ _describeInboxItem(item) {
10100
+ if (item instanceof Uint8Array) {
10101
+ return 'bytes';
10102
+ }
10103
+ if (item.envelope) {
10104
+ return 'channel_message';
10105
+ }
10106
+ if (item.frame) {
10107
+ return 'envelope';
10108
+ }
10109
+ return 'unknown';
10110
+ }
10111
+ logInboxSnapshot(event, extra = {}) {
10112
+ logger$_.debug(event, {
10113
+ channel: this.channelName,
10114
+ connector_id: this.connectorId,
10115
+ connector_state: this.state,
10116
+ inbox_capacity: this.inboxCapacity,
10117
+ inbox_remaining_capacity: this.inbox.remainingCapacity,
10118
+ ...extra,
10119
+ });
10120
+ }
10036
10121
  _shouldSkipDuplicateAck(senderId, payload) {
10037
10122
  const dedupKey = this._extractAckDedupKey(payload);
10038
10123
  if (!dedupKey) {
@@ -13,12 +13,12 @@ import fastify from 'fastify';
13
13
  import websocketPlugin from '@fastify/websocket';
14
14
 
15
15
  // This file is auto-generated during build - do not edit manually
16
- // Generated from package.json version: 0.3.5-test.954
16
+ // Generated from package.json version: 0.3.5-test.955
17
17
  /**
18
18
  * The package version, injected at build time.
19
19
  * @internal
20
20
  */
21
- const VERSION = '0.3.5-test.954';
21
+ const VERSION = '0.3.5-test.955';
22
22
 
23
23
  /**
24
24
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -836,7 +836,7 @@ class TaskCancelledError extends Error {
836
836
  * Provides functionality similar to Python's asyncio TaskSpawner with proper
837
837
  * error handling, cancellation, and graceful shutdown capabilities.
838
838
  */
839
- const logger$1b = getLogger('naylence.fame.util.task_spawner');
839
+ const logger$1c = getLogger('naylence.fame.util.task_spawner');
840
840
  function firstDefined(source, keys) {
841
841
  for (const key of keys) {
842
842
  if (Object.prototype.hasOwnProperty.call(source, key)) {
@@ -997,7 +997,7 @@ class TaskSpawner {
997
997
  const taskId = `task-${++this._taskCounter}`;
998
998
  const taskName = normalizedOptions.name || `unnamed-${taskId}`;
999
999
  const timeout = normalizedOptions.timeout ?? this._config.defaultTimeout;
1000
- logger$1b.debug('starting_background_task', {
1000
+ logger$1c.debug('starting_background_task', {
1001
1001
  task_name: taskName,
1002
1002
  task_id: taskId,
1003
1003
  });
@@ -1014,7 +1014,7 @@ class TaskSpawner {
1014
1014
  task.promise
1015
1015
  .then(() => {
1016
1016
  if (!this._suppressCompletionLogging) {
1017
- logger$1b.debug('task_completed_successfully', {
1017
+ logger$1c.debug('task_completed_successfully', {
1018
1018
  task_name: taskName,
1019
1019
  task_id: taskId,
1020
1020
  duration_ms: Date.now() - task.startTime,
@@ -1068,7 +1068,7 @@ class TaskSpawner {
1068
1068
  error.name === 'AbortError' ||
1069
1069
  error.message === 'Task cancelled' ||
1070
1070
  error.message === 'Aborted') {
1071
- logger$1b.debug('task_cancelled', {
1071
+ logger$1c.debug('task_cancelled', {
1072
1072
  task_name: taskName,
1073
1073
  note: 'Task cancelled as requested',
1074
1074
  });
@@ -1076,7 +1076,7 @@ class TaskSpawner {
1076
1076
  }
1077
1077
  // Handle timeout
1078
1078
  if (error instanceof TaskTimeoutError) {
1079
- logger$1b.warning('task_timed_out', {
1079
+ logger$1c.warning('task_timed_out', {
1080
1080
  task_name: taskName,
1081
1081
  error: error.message,
1082
1082
  });
@@ -1088,7 +1088,7 @@ class TaskSpawner {
1088
1088
  // Handle known WebSocket shutdown race condition (similar to Python version)
1089
1089
  if (error.message.includes("await wasn't used with future") ||
1090
1090
  error.message.includes('WebSocket closed during receive')) {
1091
- logger$1b.debug('task_shutdown_race_condition_handled', {
1091
+ logger$1c.debug('task_shutdown_race_condition_handled', {
1092
1092
  task_name: taskName,
1093
1093
  note: 'Normal WebSocket close timing during shutdown - not an error',
1094
1094
  });
@@ -1098,7 +1098,7 @@ class TaskSpawner {
1098
1098
  if (error.name === 'FameTransportClose' ||
1099
1099
  error.message.includes('normal closure') ||
1100
1100
  error.message.includes('Connection closed')) {
1101
- logger$1b.debug('task_shutdown_completed_normally', {
1101
+ logger$1c.debug('task_shutdown_completed_normally', {
1102
1102
  task_name: taskName,
1103
1103
  note: 'Task closed normally during shutdown',
1104
1104
  });
@@ -1111,14 +1111,14 @@ class TaskSpawner {
1111
1111
  // Log retriable errors as warnings (they'll be retried by upstream logic)
1112
1112
  // Log non-retriable errors as errors (fatal failures)
1113
1113
  if (isRetriableError) {
1114
- logger$1b.warning('background_task_failed', {
1114
+ logger$1c.warning('background_task_failed', {
1115
1115
  task_name: taskName,
1116
1116
  error: error.message,
1117
1117
  retriable: true,
1118
1118
  });
1119
1119
  }
1120
1120
  else {
1121
- logger$1b.error('background_task_failed', {
1121
+ logger$1c.error('background_task_failed', {
1122
1122
  task_name: taskName,
1123
1123
  error: error.message,
1124
1124
  stack: error.stack,
@@ -1137,11 +1137,11 @@ class TaskSpawner {
1137
1137
  async shutdownTasks(options = {}) {
1138
1138
  const { gracePeriod, cancelHanging, joinTimeout } = normalizeShutdownOptions(options);
1139
1139
  if (this._tasks.size === 0) {
1140
- logger$1b.debug('shutdown_tasks_no_tasks_to_shutdown');
1140
+ logger$1c.debug('shutdown_tasks_no_tasks_to_shutdown');
1141
1141
  return;
1142
1142
  }
1143
1143
  this._suppressCompletionLogging = true;
1144
- logger$1b.debug('shutting_down_tasks', {
1144
+ logger$1c.debug('shutting_down_tasks', {
1145
1145
  task_count: this._tasks.size,
1146
1146
  task_names: Array.from(this._tasks.values()).map((t) => t.name),
1147
1147
  grace_period_ms: gracePeriod,
@@ -1156,7 +1156,7 @@ class TaskSpawner {
1156
1156
  if (cancelHanging) {
1157
1157
  const stillRunning = tasks.filter((task) => task.getState() === TaskState.RUNNING && !completed.has(task));
1158
1158
  if (stillRunning.length > 0) {
1159
- logger$1b.debug('tasks_did_not_complete_within_grace_period', {
1159
+ logger$1c.debug('tasks_did_not_complete_within_grace_period', {
1160
1160
  hanging_count: stillRunning.length,
1161
1161
  });
1162
1162
  // Wait for them to finish with individual timeouts
@@ -1166,7 +1166,7 @@ class TaskSpawner {
1166
1166
  }
1167
1167
  catch (error) {
1168
1168
  if (error instanceof TaskTimeoutError) {
1169
- logger$1b.warning('task_did_not_shutdown', {
1169
+ logger$1c.warning('task_did_not_shutdown', {
1170
1170
  task_name: task.name || task.id,
1171
1171
  join_timeout_ms: joinTimeout,
1172
1172
  });
@@ -1177,7 +1177,7 @@ class TaskSpawner {
1177
1177
  }
1178
1178
  else if (!(error instanceof TaskCancelledError)) {
1179
1179
  /* istanbul ignore next - unreachable defensive branch */
1180
- logger$1b.error('task_raised_during_cancellation', {
1180
+ logger$1c.error('task_raised_during_cancellation', {
1181
1181
  task_name: task.name || task.id,
1182
1182
  error: error instanceof Error ? error.message : String(error),
1183
1183
  });
@@ -2270,6 +2270,7 @@ function validateKeyCorrelationTtlSec(ttlSec) {
2270
2270
  * condition/promise and ensure at most one notifier coroutine exists for a
2271
2271
  * flow at any time.
2272
2272
  */
2273
+ const logger$1b = getLogger('naylence.fame.flow.flow_controller');
2273
2274
  /**
2274
2275
  * Simple condition variable implementation for TypeScript/Node.js
2275
2276
  * Similar to Python's asyncio.Condition
@@ -2395,8 +2396,17 @@ class FlowController {
2395
2396
  // clamp into [0, initialWindow]
2396
2397
  const newBalance = Math.max(0, Math.min(this.initialWindow, prev + delta));
2397
2398
  this.credits.set(flowId, newBalance);
2399
+ const crossedZero = prev <= 0 && newBalance > 0;
2400
+ logger$1b.debug('flow_controller_add_credits', {
2401
+ flow_id: flowId,
2402
+ delta,
2403
+ prev_balance: prev,
2404
+ new_balance: newBalance,
2405
+ initial_window: this.initialWindow,
2406
+ crossed_zero: crossedZero,
2407
+ });
2398
2408
  // wake waiters only if we crossed the zero boundary
2399
- if (prev <= 0 && newBalance > 0) {
2409
+ if (crossedZero) {
2400
2410
  this.wakeWaiters(flowId);
2401
2411
  }
2402
2412
  return newBalance;
@@ -2407,11 +2417,27 @@ class FlowController {
2407
2417
  async acquire(flowId) {
2408
2418
  this.ensureFlow(flowId);
2409
2419
  const condition = this.conditions.get(flowId);
2420
+ logger$1b.debug('flow_controller_acquire_attempt', {
2421
+ flow_id: flowId,
2422
+ current_balance: this.credits.get(flowId),
2423
+ });
2410
2424
  while (this.credits.get(flowId) <= 0) {
2425
+ logger$1b.debug('flow_controller_waiting_for_credit', {
2426
+ flow_id: flowId,
2427
+ });
2411
2428
  await condition.wait();
2429
+ logger$1b.debug('flow_controller_woke_with_credit', {
2430
+ flow_id: flowId,
2431
+ balance_after_wake: this.credits.get(flowId),
2432
+ });
2412
2433
  }
2413
2434
  const current = this.credits.get(flowId);
2414
2435
  this.credits.set(flowId, current - 1);
2436
+ logger$1b.debug('flow_controller_credit_consumed', {
2437
+ flow_id: flowId,
2438
+ prev_balance: current,
2439
+ remaining_balance: current - 1,
2440
+ });
2415
2441
  }
2416
2442
  /**
2417
2443
  * Consume *credits* immediately (non-blocking).
@@ -2431,6 +2457,12 @@ class FlowController {
2431
2457
  const current = this.credits.get(flowId);
2432
2458
  const remaining = Math.max(current - credits, 0);
2433
2459
  this.credits.set(flowId, remaining);
2460
+ logger$1b.debug('flow_controller_consume', {
2461
+ flow_id: flowId,
2462
+ requested: credits,
2463
+ prev_balance: current,
2464
+ remaining_balance: remaining,
2465
+ });
2434
2466
  return remaining;
2435
2467
  }
2436
2468
  /**
@@ -2451,6 +2483,10 @@ class FlowController {
2451
2483
  this.windowIds.delete(flowId);
2452
2484
  this.credits.set(flowId, this.initialWindow);
2453
2485
  this.wakeWaiters(flowId);
2486
+ logger$1b.debug('flow_controller_flow_reset', {
2487
+ flow_id: flowId,
2488
+ reset_balance: this.initialWindow,
2489
+ });
2454
2490
  }
2455
2491
  /**
2456
2492
  * Return `[windowId, flags]` for the next outbound envelope.
@@ -9796,6 +9832,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9796
9832
  ? Math.floor(config.inboxCapacity)
9797
9833
  : DEFAULT_INBOX_CAPACITY$7;
9798
9834
  this.inbox = new BoundedAsyncQueue(preferredCapacity);
9835
+ this.inboxCapacity = preferredCapacity;
9799
9836
  this.connectorId = BroadcastChannelConnector.generateConnectorId();
9800
9837
  this.channel = new BroadcastChannel(this.channelName);
9801
9838
  logger$_.debug('broadcast_channel_connector_created', {
@@ -9855,15 +9892,27 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9855
9892
  if (typeof this.inbox.tryEnqueue === 'function') {
9856
9893
  const accepted = this.inbox.tryEnqueue(payload);
9857
9894
  if (accepted) {
9895
+ this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
9896
+ source: 'listener',
9897
+ enqueue_strategy: 'try',
9898
+ payload_length: payload.byteLength,
9899
+ });
9858
9900
  return;
9859
9901
  }
9860
9902
  }
9861
9903
  this.inbox.enqueue(payload);
9904
+ this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
9905
+ source: 'listener',
9906
+ enqueue_strategy: 'enqueue',
9907
+ payload_length: payload.byteLength,
9908
+ });
9862
9909
  }
9863
9910
  catch (error) {
9864
9911
  if (error instanceof QueueFullError) {
9865
9912
  logger$_.warning('broadcast_channel_receive_queue_full', {
9866
9913
  channel: this.channelName,
9914
+ inbox_capacity: this.inboxCapacity,
9915
+ inbox_remaining_capacity: this.inbox.remainingCapacity,
9867
9916
  });
9868
9917
  }
9869
9918
  else {
@@ -9947,15 +9996,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9947
9996
  if (typeof this.inbox.tryEnqueue === 'function') {
9948
9997
  const accepted = this.inbox.tryEnqueue(item);
9949
9998
  if (accepted) {
9999
+ this.logInboxSnapshot('broadcast_channel_push_enqueued', {
10000
+ enqueue_strategy: 'try',
10001
+ item_type: this._describeInboxItem(item),
10002
+ });
9950
10003
  return;
9951
10004
  }
9952
10005
  }
9953
10006
  this.inbox.enqueue(item);
10007
+ this.logInboxSnapshot('broadcast_channel_push_enqueued', {
10008
+ enqueue_strategy: 'enqueue',
10009
+ item_type: this._describeInboxItem(item),
10010
+ });
9954
10011
  }
9955
10012
  catch (error) {
9956
10013
  if (error instanceof QueueFullError) {
9957
10014
  logger$_.warning('broadcast_channel_push_queue_full', {
9958
10015
  channel: this.channelName,
10016
+ inbox_capacity: this.inboxCapacity,
10017
+ inbox_remaining_capacity: this.inbox.remainingCapacity,
9959
10018
  });
9960
10019
  throw error;
9961
10020
  }
@@ -9978,7 +10037,11 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9978
10037
  });
9979
10038
  }
9980
10039
  async _transportReceive() {
9981
- return await this.inbox.dequeue();
10040
+ const item = await this.inbox.dequeue();
10041
+ this.logInboxSnapshot('broadcast_channel_inbox_dequeued', {
10042
+ item_type: this._describeInboxItem(item),
10043
+ });
10044
+ return item;
9982
10045
  }
9983
10046
  async _transportClose(code, reason) {
9984
10047
  logger$_.debug('broadcast_channel_transport_closing', {
@@ -10032,6 +10095,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10032
10095
  }
10033
10096
  return rawOrEnvelope;
10034
10097
  }
10098
+ _describeInboxItem(item) {
10099
+ if (item instanceof Uint8Array) {
10100
+ return 'bytes';
10101
+ }
10102
+ if (item.envelope) {
10103
+ return 'channel_message';
10104
+ }
10105
+ if (item.frame) {
10106
+ return 'envelope';
10107
+ }
10108
+ return 'unknown';
10109
+ }
10110
+ logInboxSnapshot(event, extra = {}) {
10111
+ logger$_.debug(event, {
10112
+ channel: this.channelName,
10113
+ connector_id: this.connectorId,
10114
+ connector_state: this.state,
10115
+ inbox_capacity: this.inboxCapacity,
10116
+ inbox_remaining_capacity: this.inbox.remainingCapacity,
10117
+ ...extra,
10118
+ });
10119
+ }
10035
10120
  _shouldSkipDuplicateAck(senderId, payload) {
10036
10121
  const dedupKey = this._extractAckDedupKey(payload);
10037
10122
  if (!dedupKey) {