@naylence/agent-sdk 0.3.4-test.730 → 0.3.5
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/browser/index.js +867 -195
- package/dist/browser/index.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +2 -2
- package/dist/esm/version.js.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/browser/index.js
CHANGED
|
@@ -15674,12 +15674,12 @@
|
|
|
15674
15674
|
// --- END ENV SHIM ---
|
|
15675
15675
|
|
|
15676
15676
|
// This file is auto-generated during build - do not edit manually
|
|
15677
|
-
// Generated from package.json version: 0.3.
|
|
15677
|
+
// Generated from package.json version: 0.3.6
|
|
15678
15678
|
/**
|
|
15679
15679
|
* The package version, injected at build time.
|
|
15680
15680
|
* @internal
|
|
15681
15681
|
*/
|
|
15682
|
-
const VERSION$1 = '0.3.
|
|
15682
|
+
const VERSION$1 = '0.3.6';
|
|
15683
15683
|
|
|
15684
15684
|
/**
|
|
15685
15685
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -16383,7 +16383,7 @@
|
|
|
16383
16383
|
* Provides functionality similar to Python's asyncio TaskSpawner with proper
|
|
16384
16384
|
* error handling, cancellation, and graceful shutdown capabilities.
|
|
16385
16385
|
*/
|
|
16386
|
-
const logger$
|
|
16386
|
+
const logger$1c = getLogger('naylence.fame.util.task_spawner');
|
|
16387
16387
|
function firstDefined(source, keys) {
|
|
16388
16388
|
for (const key of keys) {
|
|
16389
16389
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
@@ -16544,7 +16544,7 @@
|
|
|
16544
16544
|
const taskId = `task-${++this._taskCounter}`;
|
|
16545
16545
|
const taskName = normalizedOptions.name || `unnamed-${taskId}`;
|
|
16546
16546
|
const timeout = normalizedOptions.timeout ?? this._config.defaultTimeout;
|
|
16547
|
-
logger$
|
|
16547
|
+
logger$1c.debug('starting_background_task', {
|
|
16548
16548
|
task_name: taskName,
|
|
16549
16549
|
task_id: taskId,
|
|
16550
16550
|
});
|
|
@@ -16561,7 +16561,7 @@
|
|
|
16561
16561
|
task.promise
|
|
16562
16562
|
.then(() => {
|
|
16563
16563
|
if (!this._suppressCompletionLogging) {
|
|
16564
|
-
logger$
|
|
16564
|
+
logger$1c.debug('task_completed_successfully', {
|
|
16565
16565
|
task_name: taskName,
|
|
16566
16566
|
task_id: taskId,
|
|
16567
16567
|
duration_ms: Date.now() - task.startTime,
|
|
@@ -16615,7 +16615,7 @@
|
|
|
16615
16615
|
error.name === 'AbortError' ||
|
|
16616
16616
|
error.message === 'Task cancelled' ||
|
|
16617
16617
|
error.message === 'Aborted') {
|
|
16618
|
-
logger$
|
|
16618
|
+
logger$1c.debug('task_cancelled', {
|
|
16619
16619
|
task_name: taskName,
|
|
16620
16620
|
note: 'Task cancelled as requested',
|
|
16621
16621
|
});
|
|
@@ -16623,7 +16623,7 @@
|
|
|
16623
16623
|
}
|
|
16624
16624
|
// Handle timeout
|
|
16625
16625
|
if (error instanceof TaskTimeoutError) {
|
|
16626
|
-
logger$
|
|
16626
|
+
logger$1c.warning('task_timed_out', {
|
|
16627
16627
|
task_name: taskName,
|
|
16628
16628
|
error: error.message,
|
|
16629
16629
|
});
|
|
@@ -16635,7 +16635,7 @@
|
|
|
16635
16635
|
// Handle known WebSocket shutdown race condition (similar to Python version)
|
|
16636
16636
|
if (error.message.includes("await wasn't used with future") ||
|
|
16637
16637
|
error.message.includes('WebSocket closed during receive')) {
|
|
16638
|
-
logger$
|
|
16638
|
+
logger$1c.debug('task_shutdown_race_condition_handled', {
|
|
16639
16639
|
task_name: taskName,
|
|
16640
16640
|
note: 'Normal WebSocket close timing during shutdown - not an error',
|
|
16641
16641
|
});
|
|
@@ -16645,7 +16645,7 @@
|
|
|
16645
16645
|
if (error.name === 'FameTransportClose' ||
|
|
16646
16646
|
error.message.includes('normal closure') ||
|
|
16647
16647
|
error.message.includes('Connection closed')) {
|
|
16648
|
-
logger$
|
|
16648
|
+
logger$1c.debug('task_shutdown_completed_normally', {
|
|
16649
16649
|
task_name: taskName,
|
|
16650
16650
|
note: 'Task closed normally during shutdown',
|
|
16651
16651
|
});
|
|
@@ -16658,14 +16658,14 @@
|
|
|
16658
16658
|
// Log retriable errors as warnings (they'll be retried by upstream logic)
|
|
16659
16659
|
// Log non-retriable errors as errors (fatal failures)
|
|
16660
16660
|
if (isRetriableError) {
|
|
16661
|
-
logger$
|
|
16661
|
+
logger$1c.warning('background_task_failed', {
|
|
16662
16662
|
task_name: taskName,
|
|
16663
16663
|
error: error.message,
|
|
16664
16664
|
retriable: true,
|
|
16665
16665
|
});
|
|
16666
16666
|
}
|
|
16667
16667
|
else {
|
|
16668
|
-
logger$
|
|
16668
|
+
logger$1c.error('background_task_failed', {
|
|
16669
16669
|
task_name: taskName,
|
|
16670
16670
|
error: error.message,
|
|
16671
16671
|
stack: error.stack,
|
|
@@ -16684,11 +16684,11 @@
|
|
|
16684
16684
|
async shutdownTasks(options = {}) {
|
|
16685
16685
|
const { gracePeriod, cancelHanging, joinTimeout } = normalizeShutdownOptions(options);
|
|
16686
16686
|
if (this._tasks.size === 0) {
|
|
16687
|
-
logger$
|
|
16687
|
+
logger$1c.debug('shutdown_tasks_no_tasks_to_shutdown');
|
|
16688
16688
|
return;
|
|
16689
16689
|
}
|
|
16690
16690
|
this._suppressCompletionLogging = true;
|
|
16691
|
-
logger$
|
|
16691
|
+
logger$1c.debug('shutting_down_tasks', {
|
|
16692
16692
|
task_count: this._tasks.size,
|
|
16693
16693
|
task_names: Array.from(this._tasks.values()).map((t) => t.name),
|
|
16694
16694
|
grace_period_ms: gracePeriod,
|
|
@@ -16703,7 +16703,7 @@
|
|
|
16703
16703
|
if (cancelHanging) {
|
|
16704
16704
|
const stillRunning = tasks.filter((task) => task.getState() === TaskState.RUNNING && !completed.has(task));
|
|
16705
16705
|
if (stillRunning.length > 0) {
|
|
16706
|
-
logger$
|
|
16706
|
+
logger$1c.debug('tasks_did_not_complete_within_grace_period', {
|
|
16707
16707
|
hanging_count: stillRunning.length,
|
|
16708
16708
|
});
|
|
16709
16709
|
// Wait for them to finish with individual timeouts
|
|
@@ -16713,7 +16713,7 @@
|
|
|
16713
16713
|
}
|
|
16714
16714
|
catch (error) {
|
|
16715
16715
|
if (error instanceof TaskTimeoutError) {
|
|
16716
|
-
logger$
|
|
16716
|
+
logger$1c.warning('task_did_not_shutdown', {
|
|
16717
16717
|
task_name: task.name || task.id,
|
|
16718
16718
|
join_timeout_ms: joinTimeout,
|
|
16719
16719
|
});
|
|
@@ -16724,7 +16724,7 @@
|
|
|
16724
16724
|
}
|
|
16725
16725
|
else if (!(error instanceof TaskCancelledError)) {
|
|
16726
16726
|
/* istanbul ignore next - unreachable defensive branch */
|
|
16727
|
-
logger$
|
|
16727
|
+
logger$1c.error('task_raised_during_cancellation', {
|
|
16728
16728
|
task_name: task.name || task.id,
|
|
16729
16729
|
error: error instanceof Error ? error.message : String(error),
|
|
16730
16730
|
});
|
|
@@ -17298,6 +17298,7 @@
|
|
|
17298
17298
|
* condition/promise and ensure at most one notifier coroutine exists for a
|
|
17299
17299
|
* flow at any time.
|
|
17300
17300
|
*/
|
|
17301
|
+
const logger$1b = getLogger('naylence.fame.flow.flow_controller');
|
|
17301
17302
|
/**
|
|
17302
17303
|
* Simple condition variable implementation for TypeScript/Node.js
|
|
17303
17304
|
* Similar to Python's asyncio.Condition
|
|
@@ -17389,8 +17390,15 @@
|
|
|
17389
17390
|
// Create a notifier promise
|
|
17390
17391
|
const notifierPromise = (async () => {
|
|
17391
17392
|
try {
|
|
17392
|
-
// Use setImmediate to defer to next tick (similar to asyncio scheduling)
|
|
17393
|
-
await new Promise((resolve) =>
|
|
17393
|
+
// Use setImmediate/setTimeout to defer to next tick (similar to asyncio scheduling)
|
|
17394
|
+
await new Promise((resolve) => {
|
|
17395
|
+
if (typeof setImmediate === 'function') {
|
|
17396
|
+
setImmediate(resolve);
|
|
17397
|
+
}
|
|
17398
|
+
else {
|
|
17399
|
+
setTimeout(resolve, 0);
|
|
17400
|
+
}
|
|
17401
|
+
});
|
|
17394
17402
|
condition.notifyAll();
|
|
17395
17403
|
}
|
|
17396
17404
|
finally {
|
|
@@ -17423,8 +17431,17 @@
|
|
|
17423
17431
|
// clamp into [0, initialWindow]
|
|
17424
17432
|
const newBalance = Math.max(0, Math.min(this.initialWindow, prev + delta));
|
|
17425
17433
|
this.credits.set(flowId, newBalance);
|
|
17434
|
+
const crossedZero = prev <= 0 && newBalance > 0;
|
|
17435
|
+
logger$1b.debug('flow_controller_add_credits', {
|
|
17436
|
+
flow_id: flowId,
|
|
17437
|
+
delta,
|
|
17438
|
+
prev_balance: prev,
|
|
17439
|
+
new_balance: newBalance,
|
|
17440
|
+
initial_window: this.initialWindow,
|
|
17441
|
+
crossed_zero: crossedZero,
|
|
17442
|
+
});
|
|
17426
17443
|
// wake waiters only if we crossed the zero boundary
|
|
17427
|
-
if (
|
|
17444
|
+
if (crossedZero) {
|
|
17428
17445
|
this.wakeWaiters(flowId);
|
|
17429
17446
|
}
|
|
17430
17447
|
return newBalance;
|
|
@@ -17435,11 +17452,29 @@
|
|
|
17435
17452
|
async acquire(flowId) {
|
|
17436
17453
|
this.ensureFlow(flowId);
|
|
17437
17454
|
const condition = this.conditions.get(flowId);
|
|
17455
|
+
logger$1b.debug('flow_controller_acquire_attempt', {
|
|
17456
|
+
flow_id: flowId,
|
|
17457
|
+
current_balance: this.credits.get(flowId),
|
|
17458
|
+
});
|
|
17438
17459
|
while (this.credits.get(flowId) <= 0) {
|
|
17460
|
+
logger$1b.debug('flow_controller_waiting_for_credits', {
|
|
17461
|
+
flow_id: flowId,
|
|
17462
|
+
current_balance: this.credits.get(flowId),
|
|
17463
|
+
});
|
|
17439
17464
|
await condition.wait();
|
|
17440
17465
|
}
|
|
17441
|
-
const
|
|
17442
|
-
this.credits.set(flowId,
|
|
17466
|
+
const newBalance = this.credits.get(flowId) - 1;
|
|
17467
|
+
this.credits.set(flowId, newBalance);
|
|
17468
|
+
logger$1b.debug('flow_controller_acquire_success', {
|
|
17469
|
+
flow_id: flowId,
|
|
17470
|
+
new_balance: newBalance,
|
|
17471
|
+
});
|
|
17472
|
+
if (newBalance <= this.lowWatermark) {
|
|
17473
|
+
logger$1b.debug('flow_controller_acquire_below_low_watermark', {
|
|
17474
|
+
flow_id: flowId,
|
|
17475
|
+
low_watermark: this.lowWatermark,
|
|
17476
|
+
});
|
|
17477
|
+
}
|
|
17443
17478
|
}
|
|
17444
17479
|
/**
|
|
17445
17480
|
* Consume *credits* immediately (non-blocking).
|
|
@@ -17459,6 +17494,12 @@
|
|
|
17459
17494
|
const current = this.credits.get(flowId);
|
|
17460
17495
|
const remaining = Math.max(current - credits, 0);
|
|
17461
17496
|
this.credits.set(flowId, remaining);
|
|
17497
|
+
logger$1b.debug('flow_controller_consume', {
|
|
17498
|
+
flow_id: flowId,
|
|
17499
|
+
requested: credits,
|
|
17500
|
+
prev_balance: current,
|
|
17501
|
+
remaining_balance: remaining,
|
|
17502
|
+
});
|
|
17462
17503
|
return remaining;
|
|
17463
17504
|
}
|
|
17464
17505
|
/**
|
|
@@ -17479,6 +17520,10 @@
|
|
|
17479
17520
|
this.windowIds.delete(flowId);
|
|
17480
17521
|
this.credits.set(flowId, this.initialWindow);
|
|
17481
17522
|
this.wakeWaiters(flowId);
|
|
17523
|
+
logger$1b.debug('flow_controller_flow_reset', {
|
|
17524
|
+
flow_id: flowId,
|
|
17525
|
+
reset_balance: this.initialWindow,
|
|
17526
|
+
});
|
|
17482
17527
|
}
|
|
17483
17528
|
/**
|
|
17484
17529
|
* Return `[windowId, flags]` for the next outbound envelope.
|
|
@@ -24039,10 +24084,12 @@
|
|
|
24039
24084
|
throw new FameTransportClose('Connection closed', 1006);
|
|
24040
24085
|
}
|
|
24041
24086
|
// Apply flow control if enabled and not a credit update
|
|
24042
|
-
|
|
24043
|
-
|
|
24044
|
-
|
|
24045
|
-
'credits' in envelope.frame)
|
|
24087
|
+
const isCreditUpdateFrame = Boolean(envelope.frame &&
|
|
24088
|
+
(envelope.frame.type === 'CreditUpdate' ||
|
|
24089
|
+
envelope.frame.type === 'credit_update' ||
|
|
24090
|
+
('flowId' in envelope.frame && 'credits' in envelope.frame) ||
|
|
24091
|
+
('flow_id' in envelope.frame && 'credits' in envelope.frame)));
|
|
24092
|
+
if (this._fcEnabled && !isCreditUpdateFrame) {
|
|
24046
24093
|
const flowId = envelope.flowId || this._connectorFlowId;
|
|
24047
24094
|
envelope.flowId = flowId;
|
|
24048
24095
|
const t0 = this._metrics ? performance.now() : 0;
|
|
@@ -24285,11 +24332,31 @@
|
|
|
24285
24332
|
* Emit credit update if flow control needs refill
|
|
24286
24333
|
*/
|
|
24287
24334
|
async _maybeEmitCredit(flowId, traceId) {
|
|
24288
|
-
|
|
24335
|
+
const remainingCredits = this._flowCtrl.getCredits(flowId);
|
|
24336
|
+
const needsRefill = this._flowCtrl.needsRefill(flowId);
|
|
24337
|
+
logger$$.debug('maybe_emit_credit_check', {
|
|
24338
|
+
connector_id: this._connectorFlowId,
|
|
24339
|
+
flow_id: flowId,
|
|
24340
|
+
trace_id: traceId ?? null,
|
|
24341
|
+
remaining_credits: remainingCredits,
|
|
24342
|
+
low_watermark: this._flowCtrl instanceof FlowController
|
|
24343
|
+
? this._flowCtrl.lowWatermark
|
|
24344
|
+
: null,
|
|
24345
|
+
initial_window: this._initialWindow,
|
|
24346
|
+
needs_refill: needsRefill,
|
|
24347
|
+
});
|
|
24348
|
+
if (!needsRefill) {
|
|
24289
24349
|
return;
|
|
24290
24350
|
}
|
|
24291
24351
|
const delta = this._initialWindow;
|
|
24292
24352
|
this._flowCtrl.addCredits(flowId, delta);
|
|
24353
|
+
logger$$.debug('maybe_emit_credit_emit', {
|
|
24354
|
+
connector_id: this._connectorFlowId,
|
|
24355
|
+
flow_id: flowId,
|
|
24356
|
+
trace_id: traceId ?? null,
|
|
24357
|
+
emitted_credits: delta,
|
|
24358
|
+
post_emit_balance: this._flowCtrl.getCredits(flowId),
|
|
24359
|
+
});
|
|
24293
24360
|
const ackEnv = createFameEnvelope({
|
|
24294
24361
|
...(traceId && { traceId }),
|
|
24295
24362
|
flowId,
|
|
@@ -24301,7 +24368,25 @@
|
|
|
24301
24368
|
},
|
|
24302
24369
|
flags: FlowFlags.ACK,
|
|
24303
24370
|
});
|
|
24304
|
-
|
|
24371
|
+
try {
|
|
24372
|
+
await this.send(ackEnv);
|
|
24373
|
+
logger$$.debug('maybe_emit_credit_sent', {
|
|
24374
|
+
connector_id: this._connectorFlowId,
|
|
24375
|
+
flow_id: flowId,
|
|
24376
|
+
trace_id: traceId ?? null,
|
|
24377
|
+
credits_acknowledged: delta,
|
|
24378
|
+
});
|
|
24379
|
+
}
|
|
24380
|
+
catch (error) {
|
|
24381
|
+
logger$$.error('maybe_emit_credit_send_failed', {
|
|
24382
|
+
connector_id: this._connectorFlowId,
|
|
24383
|
+
flow_id: flowId,
|
|
24384
|
+
trace_id: traceId ?? null,
|
|
24385
|
+
credits_attempted: delta,
|
|
24386
|
+
error: error instanceof Error ? error.message : String(error),
|
|
24387
|
+
});
|
|
24388
|
+
throw error;
|
|
24389
|
+
}
|
|
24305
24390
|
}
|
|
24306
24391
|
// ---------------------------------------------------------------------
|
|
24307
24392
|
// Shutdown Management
|
|
@@ -24517,15 +24602,30 @@
|
|
|
24517
24602
|
}
|
|
24518
24603
|
return null;
|
|
24519
24604
|
}
|
|
24605
|
+
static normalizeNodeId(value) {
|
|
24606
|
+
if (typeof value !== 'string') {
|
|
24607
|
+
return null;
|
|
24608
|
+
}
|
|
24609
|
+
const trimmed = value.trim();
|
|
24610
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
24611
|
+
}
|
|
24612
|
+
static normalizeTargetNodeId(value) {
|
|
24613
|
+
if (typeof value !== 'string') {
|
|
24614
|
+
return undefined;
|
|
24615
|
+
}
|
|
24616
|
+
const trimmed = value.trim();
|
|
24617
|
+
if (trimmed.length === 0) {
|
|
24618
|
+
return undefined;
|
|
24619
|
+
}
|
|
24620
|
+
if (trimmed === '*') {
|
|
24621
|
+
return '*';
|
|
24622
|
+
}
|
|
24623
|
+
return trimmed;
|
|
24624
|
+
}
|
|
24520
24625
|
constructor(config, baseConfig = {}) {
|
|
24521
24626
|
ensureBroadcastEnvironment();
|
|
24522
24627
|
super(baseConfig);
|
|
24523
24628
|
this.listenerRegistered = false;
|
|
24524
|
-
this.seenAckKeys = new Map();
|
|
24525
|
-
this.seenAckOrder = [];
|
|
24526
|
-
this.ackDedupTtlMs = 30000;
|
|
24527
|
-
this.ackDedupMaxEntries = 4096;
|
|
24528
|
-
this.textDecoder = new TextDecoder();
|
|
24529
24629
|
this.visibilityChangeListenerRegistered = false;
|
|
24530
24630
|
this.channelName =
|
|
24531
24631
|
typeof config.channelName === 'string' && config.channelName.trim().length > 0
|
|
@@ -24537,11 +24637,20 @@
|
|
|
24537
24637
|
? Math.floor(config.inboxCapacity)
|
|
24538
24638
|
: DEFAULT_INBOX_CAPACITY$7;
|
|
24539
24639
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
24640
|
+
this.inboxCapacity = preferredCapacity;
|
|
24540
24641
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
24642
|
+
const normalizedLocalNodeId = BroadcastChannelConnector.normalizeNodeId(config.localNodeId);
|
|
24643
|
+
if (!normalizedLocalNodeId) {
|
|
24644
|
+
throw new Error('BroadcastChannelConnector requires a non-empty localNodeId');
|
|
24645
|
+
}
|
|
24646
|
+
this.localNodeId = normalizedLocalNodeId;
|
|
24647
|
+
this.targetNodeId = BroadcastChannelConnector.normalizeTargetNodeId(config.initialTargetNodeId);
|
|
24541
24648
|
this.channel = new BroadcastChannel(this.channelName);
|
|
24542
24649
|
logger$_.debug('broadcast_channel_connector_created', {
|
|
24543
24650
|
channel: this.channelName,
|
|
24544
24651
|
connector_id: this.connectorId,
|
|
24652
|
+
local_node_id: this.localNodeId,
|
|
24653
|
+
target_node_id: this.targetNodeId ?? null,
|
|
24545
24654
|
inbox_capacity: preferredCapacity,
|
|
24546
24655
|
timestamp: new Date().toISOString(),
|
|
24547
24656
|
});
|
|
@@ -24563,15 +24672,32 @@
|
|
|
24563
24672
|
? message.constructor?.name ?? typeof message
|
|
24564
24673
|
: typeof message,
|
|
24565
24674
|
has_sender_id: Boolean(message?.senderId),
|
|
24675
|
+
has_sender_node_id: Boolean(message?.senderNodeId),
|
|
24566
24676
|
});
|
|
24567
24677
|
if (!message || typeof message !== 'object') {
|
|
24568
24678
|
return;
|
|
24569
24679
|
}
|
|
24570
24680
|
const busMessage = message;
|
|
24571
|
-
|
|
24681
|
+
const senderNodeId = BroadcastChannelConnector.normalizeNodeId(busMessage.senderNodeId);
|
|
24682
|
+
if (!senderNodeId) {
|
|
24683
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
24684
|
+
channel: this.channelName,
|
|
24685
|
+
connector_id: this.connectorId,
|
|
24686
|
+
reason: 'missing_sender_node_id',
|
|
24687
|
+
});
|
|
24688
|
+
return;
|
|
24689
|
+
}
|
|
24690
|
+
if (senderNodeId === this.localNodeId) {
|
|
24691
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
24692
|
+
channel: this.channelName,
|
|
24693
|
+
connector_id: this.connectorId,
|
|
24694
|
+
reason: 'self_echo',
|
|
24695
|
+
sender_node_id: senderNodeId,
|
|
24696
|
+
});
|
|
24572
24697
|
return;
|
|
24573
24698
|
}
|
|
24574
|
-
|
|
24699
|
+
const incomingTargetNodeId = BroadcastChannelConnector.normalizeTargetNodeId(busMessage.targetNodeId);
|
|
24700
|
+
if (!this._shouldAcceptMessageFromBus(senderNodeId, incomingTargetNodeId)) {
|
|
24575
24701
|
return;
|
|
24576
24702
|
}
|
|
24577
24703
|
const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
|
|
@@ -24585,26 +24711,37 @@
|
|
|
24585
24711
|
}
|
|
24586
24712
|
logger$_.debug('broadcast_channel_message_received', {
|
|
24587
24713
|
channel: this.channelName,
|
|
24588
|
-
sender_id:
|
|
24714
|
+
sender_id: message?.senderId,
|
|
24715
|
+
sender_node_id: senderNodeId,
|
|
24716
|
+
target_node_id: incomingTargetNodeId ?? null,
|
|
24589
24717
|
connector_id: this.connectorId,
|
|
24590
24718
|
payload_length: payload.byteLength,
|
|
24591
24719
|
});
|
|
24592
|
-
if (this._shouldSkipDuplicateAck(busMessage.senderId, payload)) {
|
|
24593
|
-
return;
|
|
24594
|
-
}
|
|
24595
24720
|
try {
|
|
24596
24721
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
24597
24722
|
const accepted = this.inbox.tryEnqueue(payload);
|
|
24598
24723
|
if (accepted) {
|
|
24724
|
+
this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
|
|
24725
|
+
source: 'listener',
|
|
24726
|
+
enqueue_strategy: 'try',
|
|
24727
|
+
payload_length: payload.byteLength,
|
|
24728
|
+
});
|
|
24599
24729
|
return;
|
|
24600
24730
|
}
|
|
24601
24731
|
}
|
|
24602
24732
|
this.inbox.enqueue(payload);
|
|
24733
|
+
this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
|
|
24734
|
+
source: 'listener',
|
|
24735
|
+
enqueue_strategy: 'enqueue',
|
|
24736
|
+
payload_length: payload.byteLength,
|
|
24737
|
+
});
|
|
24603
24738
|
}
|
|
24604
24739
|
catch (error) {
|
|
24605
24740
|
if (error instanceof QueueFullError) {
|
|
24606
24741
|
logger$_.warning('broadcast_channel_receive_queue_full', {
|
|
24607
24742
|
channel: this.channelName,
|
|
24743
|
+
inbox_capacity: this.inboxCapacity,
|
|
24744
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
24608
24745
|
});
|
|
24609
24746
|
}
|
|
24610
24747
|
else {
|
|
@@ -24615,8 +24752,10 @@
|
|
|
24615
24752
|
}
|
|
24616
24753
|
}
|
|
24617
24754
|
};
|
|
24618
|
-
|
|
24619
|
-
|
|
24755
|
+
if (!config.passive) {
|
|
24756
|
+
this.channel.addEventListener('message', this.onMsg);
|
|
24757
|
+
this.listenerRegistered = true;
|
|
24758
|
+
}
|
|
24620
24759
|
// Setup visibility change monitoring
|
|
24621
24760
|
this.visibilityChangeHandler = () => {
|
|
24622
24761
|
const isHidden = document.hidden;
|
|
@@ -24681,22 +24820,29 @@
|
|
|
24681
24820
|
}
|
|
24682
24821
|
async pushToReceive(rawOrEnvelope) {
|
|
24683
24822
|
const item = this._normalizeInboxItem(rawOrEnvelope);
|
|
24684
|
-
if (this._shouldSkipDuplicateAckFromInboxItem(item)) {
|
|
24685
|
-
return;
|
|
24686
|
-
}
|
|
24687
24823
|
try {
|
|
24688
24824
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
24689
24825
|
const accepted = this.inbox.tryEnqueue(item);
|
|
24690
24826
|
if (accepted) {
|
|
24827
|
+
this.logInboxSnapshot('broadcast_channel_push_enqueued', {
|
|
24828
|
+
enqueue_strategy: 'try',
|
|
24829
|
+
item_type: this._describeInboxItem(item),
|
|
24830
|
+
});
|
|
24691
24831
|
return;
|
|
24692
24832
|
}
|
|
24693
24833
|
}
|
|
24694
24834
|
this.inbox.enqueue(item);
|
|
24835
|
+
this.logInboxSnapshot('broadcast_channel_push_enqueued', {
|
|
24836
|
+
enqueue_strategy: 'enqueue',
|
|
24837
|
+
item_type: this._describeInboxItem(item),
|
|
24838
|
+
});
|
|
24695
24839
|
}
|
|
24696
24840
|
catch (error) {
|
|
24697
24841
|
if (error instanceof QueueFullError) {
|
|
24698
24842
|
logger$_.warning('broadcast_channel_push_queue_full', {
|
|
24699
24843
|
channel: this.channelName,
|
|
24844
|
+
inbox_capacity: this.inboxCapacity,
|
|
24845
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
24700
24846
|
});
|
|
24701
24847
|
throw error;
|
|
24702
24848
|
}
|
|
@@ -24709,17 +24855,26 @@
|
|
|
24709
24855
|
}
|
|
24710
24856
|
async _transportSendBytes(data) {
|
|
24711
24857
|
ensureBroadcastEnvironment();
|
|
24858
|
+
const targetNodeId = this.targetNodeId ?? '*';
|
|
24712
24859
|
logger$_.debug('broadcast_channel_message_sending', {
|
|
24713
24860
|
channel: this.channelName,
|
|
24714
24861
|
sender_id: this.connectorId,
|
|
24862
|
+
sender_node_id: this.localNodeId,
|
|
24863
|
+
target_node_id: targetNodeId,
|
|
24715
24864
|
});
|
|
24716
24865
|
this.channel.postMessage({
|
|
24717
24866
|
senderId: this.connectorId,
|
|
24867
|
+
senderNodeId: this.localNodeId,
|
|
24868
|
+
targetNodeId,
|
|
24718
24869
|
payload: data,
|
|
24719
24870
|
});
|
|
24720
24871
|
}
|
|
24721
24872
|
async _transportReceive() {
|
|
24722
|
-
|
|
24873
|
+
const item = await this.inbox.dequeue();
|
|
24874
|
+
this.logInboxSnapshot('broadcast_channel_inbox_dequeued', {
|
|
24875
|
+
item_type: this._describeInboxItem(item),
|
|
24876
|
+
});
|
|
24877
|
+
return item;
|
|
24723
24878
|
}
|
|
24724
24879
|
async _transportClose(code, reason) {
|
|
24725
24880
|
logger$_.debug('broadcast_channel_transport_closing', {
|
|
@@ -24764,8 +24919,6 @@
|
|
|
24764
24919
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
24765
24920
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
24766
24921
|
this.inbox.drain(shutdownError);
|
|
24767
|
-
this.seenAckKeys.clear();
|
|
24768
|
-
this.seenAckOrder.length = 0;
|
|
24769
24922
|
}
|
|
24770
24923
|
_normalizeInboxItem(rawOrEnvelope) {
|
|
24771
24924
|
if (rawOrEnvelope instanceof Uint8Array) {
|
|
@@ -24773,78 +24926,74 @@
|
|
|
24773
24926
|
}
|
|
24774
24927
|
return rawOrEnvelope;
|
|
24775
24928
|
}
|
|
24776
|
-
|
|
24777
|
-
|
|
24778
|
-
if (!dedupKey) {
|
|
24779
|
-
return false;
|
|
24780
|
-
}
|
|
24781
|
-
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
24782
|
-
? senderId
|
|
24783
|
-
: undefined;
|
|
24784
|
-
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
24929
|
+
_isWildcardTarget() {
|
|
24930
|
+
return this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined';
|
|
24785
24931
|
}
|
|
24786
|
-
|
|
24787
|
-
if (
|
|
24788
|
-
|
|
24789
|
-
|
|
24790
|
-
|
|
24791
|
-
|
|
24792
|
-
|
|
24793
|
-
|
|
24794
|
-
|
|
24795
|
-
|
|
24796
|
-
|
|
24932
|
+
_shouldAcceptMessageFromBus(senderNodeId, targetNodeId) {
|
|
24933
|
+
if (this._isWildcardTarget()) {
|
|
24934
|
+
if (targetNodeId &&
|
|
24935
|
+
targetNodeId !== '*' &&
|
|
24936
|
+
targetNodeId !== this.localNodeId) {
|
|
24937
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
24938
|
+
channel: this.channelName,
|
|
24939
|
+
connector_id: this.connectorId,
|
|
24940
|
+
reason: 'wildcard_target_mismatch',
|
|
24941
|
+
sender_node_id: senderNodeId,
|
|
24942
|
+
target_node_id: targetNodeId,
|
|
24943
|
+
local_node_id: this.localNodeId,
|
|
24944
|
+
});
|
|
24945
|
+
return false;
|
|
24946
|
+
}
|
|
24947
|
+
return true;
|
|
24797
24948
|
}
|
|
24798
|
-
const
|
|
24799
|
-
|
|
24800
|
-
|
|
24801
|
-
|
|
24802
|
-
|
|
24949
|
+
const expectedSender = this.targetNodeId;
|
|
24950
|
+
if (expectedSender && expectedSender !== '*' && senderNodeId !== expectedSender) {
|
|
24951
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
24952
|
+
channel: this.channelName,
|
|
24953
|
+
connector_id: this.connectorId,
|
|
24954
|
+
reason: 'unexpected_sender',
|
|
24955
|
+
expected_sender_node_id: expectedSender,
|
|
24956
|
+
sender_node_id: senderNodeId,
|
|
24957
|
+
local_node_id: this.localNodeId,
|
|
24958
|
+
});
|
|
24803
24959
|
return false;
|
|
24804
24960
|
}
|
|
24805
|
-
|
|
24806
|
-
|
|
24807
|
-
|
|
24808
|
-
|
|
24809
|
-
const now = Date.now();
|
|
24810
|
-
const lastSeen = this.seenAckKeys.get(dedupKey);
|
|
24811
|
-
if (lastSeen && now - lastSeen < this.ackDedupTtlMs) {
|
|
24812
|
-
logger$_.debug('broadcast_channel_duplicate_ack_suppressed', {
|
|
24961
|
+
if (targetNodeId &&
|
|
24962
|
+
targetNodeId !== '*' &&
|
|
24963
|
+
targetNodeId !== this.localNodeId) {
|
|
24964
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
24813
24965
|
channel: this.channelName,
|
|
24814
24966
|
connector_id: this.connectorId,
|
|
24815
|
-
|
|
24816
|
-
|
|
24967
|
+
reason: 'unexpected_target',
|
|
24968
|
+
sender_node_id: senderNodeId,
|
|
24969
|
+
target_node_id: targetNodeId,
|
|
24970
|
+
local_node_id: this.localNodeId,
|
|
24817
24971
|
});
|
|
24818
|
-
return
|
|
24972
|
+
return false;
|
|
24819
24973
|
}
|
|
24820
|
-
|
|
24821
|
-
this.seenAckOrder.push(dedupKey);
|
|
24822
|
-
this._trimSeenAcks(now);
|
|
24823
|
-
return false;
|
|
24974
|
+
return true;
|
|
24824
24975
|
}
|
|
24825
|
-
|
|
24826
|
-
if (
|
|
24827
|
-
return
|
|
24976
|
+
_describeInboxItem(item) {
|
|
24977
|
+
if (item instanceof Uint8Array) {
|
|
24978
|
+
return 'bytes';
|
|
24828
24979
|
}
|
|
24829
|
-
if (
|
|
24830
|
-
return
|
|
24980
|
+
if (item.envelope) {
|
|
24981
|
+
return 'channel_message';
|
|
24831
24982
|
}
|
|
24832
|
-
if (
|
|
24833
|
-
return
|
|
24983
|
+
if (item.frame) {
|
|
24984
|
+
return 'envelope';
|
|
24834
24985
|
}
|
|
24835
|
-
return
|
|
24986
|
+
return 'unknown';
|
|
24836
24987
|
}
|
|
24837
|
-
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
24843
|
-
|
|
24844
|
-
|
|
24845
|
-
|
|
24846
|
-
}
|
|
24847
|
-
return undefined;
|
|
24988
|
+
logInboxSnapshot(event, extra = {}) {
|
|
24989
|
+
logger$_.debug(event, {
|
|
24990
|
+
channel: this.channelName,
|
|
24991
|
+
connector_id: this.connectorId,
|
|
24992
|
+
connector_state: this.state,
|
|
24993
|
+
inbox_capacity: this.inboxCapacity,
|
|
24994
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
24995
|
+
...extra,
|
|
24996
|
+
});
|
|
24848
24997
|
}
|
|
24849
24998
|
/**
|
|
24850
24999
|
* Override start() to check initial visibility state
|
|
@@ -24871,46 +25020,33 @@
|
|
|
24871
25020
|
});
|
|
24872
25021
|
}
|
|
24873
25022
|
}
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
if (timestamp === undefined) {
|
|
24879
|
-
this.seenAckOrder.shift();
|
|
24880
|
-
continue;
|
|
24881
|
-
}
|
|
24882
|
-
if (this.seenAckKeys.size > this.ackDedupMaxEntries ||
|
|
24883
|
-
now - timestamp > this.ackDedupTtlMs) {
|
|
24884
|
-
this.seenAckKeys.delete(candidate);
|
|
24885
|
-
this.seenAckOrder.shift();
|
|
24886
|
-
continue;
|
|
24887
|
-
}
|
|
24888
|
-
break;
|
|
24889
|
-
}
|
|
24890
|
-
}
|
|
24891
|
-
_extractAckDedupKey(payload) {
|
|
24892
|
-
try {
|
|
24893
|
-
const decoded = this.textDecoder.decode(payload);
|
|
24894
|
-
const parsed = JSON.parse(decoded);
|
|
24895
|
-
const envelopeId = typeof parsed?.id === 'string' ? parsed.id : null;
|
|
24896
|
-
const frameType = parsed?.frame?.type;
|
|
24897
|
-
if (typeof frameType !== 'string' || frameType !== 'DeliveryAck') {
|
|
24898
|
-
return null;
|
|
24899
|
-
}
|
|
24900
|
-
const refId = parsed.frame?.refId;
|
|
24901
|
-
if (typeof refId === 'string' && refId.length > 0) {
|
|
24902
|
-
return refId;
|
|
24903
|
-
}
|
|
24904
|
-
return envelopeId;
|
|
25023
|
+
setTargetNodeId(nodeId) {
|
|
25024
|
+
const normalized = BroadcastChannelConnector.normalizeNodeId(nodeId);
|
|
25025
|
+
if (!normalized) {
|
|
25026
|
+
throw new Error('BroadcastChannelConnector target node id must be a non-empty string');
|
|
24905
25027
|
}
|
|
24906
|
-
|
|
24907
|
-
|
|
24908
|
-
|
|
24909
|
-
connector_id: this.connectorId,
|
|
24910
|
-
error: error instanceof Error ? error.message : String(error),
|
|
24911
|
-
});
|
|
24912
|
-
return null;
|
|
25028
|
+
if (normalized === '*') {
|
|
25029
|
+
this.setWildcardTarget();
|
|
25030
|
+
return;
|
|
24913
25031
|
}
|
|
25032
|
+
this.targetNodeId = normalized;
|
|
25033
|
+
logger$_.debug('broadcast_channel_target_updated', {
|
|
25034
|
+
channel: this.channelName,
|
|
25035
|
+
connector_id: this.connectorId,
|
|
25036
|
+
local_node_id: this.localNodeId,
|
|
25037
|
+
target_node_id: this.targetNodeId,
|
|
25038
|
+
target_mode: 'direct',
|
|
25039
|
+
});
|
|
25040
|
+
}
|
|
25041
|
+
setWildcardTarget() {
|
|
25042
|
+
this.targetNodeId = '*';
|
|
25043
|
+
logger$_.debug('broadcast_channel_target_updated', {
|
|
25044
|
+
channel: this.channelName,
|
|
25045
|
+
connector_id: this.connectorId,
|
|
25046
|
+
local_node_id: this.localNodeId,
|
|
25047
|
+
target_node_id: this.targetNodeId,
|
|
25048
|
+
target_mode: 'wildcard',
|
|
25049
|
+
});
|
|
24914
25050
|
}
|
|
24915
25051
|
};
|
|
24916
25052
|
|
|
@@ -25019,6 +25155,15 @@
|
|
|
25019
25155
|
}
|
|
25020
25156
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
25021
25157
|
}
|
|
25158
|
+
const windowValue = candidate.initialWindow ?? candidate['initial_window'];
|
|
25159
|
+
if (windowValue !== undefined) {
|
|
25160
|
+
if (typeof windowValue !== 'number' ||
|
|
25161
|
+
!Number.isFinite(windowValue) ||
|
|
25162
|
+
windowValue <= 0) {
|
|
25163
|
+
throw new TypeError('BroadcastChannelConnectionGrant "initialWindow" must be a positive number when provided');
|
|
25164
|
+
}
|
|
25165
|
+
result.initialWindow = Math.floor(windowValue);
|
|
25166
|
+
}
|
|
25022
25167
|
return result;
|
|
25023
25168
|
}
|
|
25024
25169
|
function broadcastChannelGrantToConnectorConfig(grant) {
|
|
@@ -25032,6 +25177,9 @@
|
|
|
25032
25177
|
if (normalized.inboxCapacity !== undefined) {
|
|
25033
25178
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
25034
25179
|
}
|
|
25180
|
+
if (normalized.initialWindow !== undefined) {
|
|
25181
|
+
config.initialWindow = normalized.initialWindow;
|
|
25182
|
+
}
|
|
25035
25183
|
return config;
|
|
25036
25184
|
}
|
|
25037
25185
|
|
|
@@ -25303,6 +25451,20 @@
|
|
|
25303
25451
|
waitEvent(event, signal) {
|
|
25304
25452
|
return signal ? event.wait({ signal }) : event.wait();
|
|
25305
25453
|
}
|
|
25454
|
+
_getLocalNodeId() {
|
|
25455
|
+
const normalized = this._normalizeNodeId(this.node.id);
|
|
25456
|
+
if (!normalized) {
|
|
25457
|
+
throw new Error('UpstreamSessionManager requires node with a stable identifier');
|
|
25458
|
+
}
|
|
25459
|
+
return normalized;
|
|
25460
|
+
}
|
|
25461
|
+
_normalizeNodeId(value) {
|
|
25462
|
+
if (typeof value !== 'string') {
|
|
25463
|
+
return null;
|
|
25464
|
+
}
|
|
25465
|
+
const trimmed = value.trim();
|
|
25466
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
25467
|
+
}
|
|
25306
25468
|
async connectCycle() {
|
|
25307
25469
|
if (!this.admissionClient) {
|
|
25308
25470
|
throw new FameConnectError('Admission client is required to attach upstream');
|
|
@@ -25324,6 +25486,8 @@
|
|
|
25324
25486
|
await this.onWelcome(welcome.frame);
|
|
25325
25487
|
const connector = await ConnectorFactory.createConnector(grant, {
|
|
25326
25488
|
systemId: welcome.frame.systemId,
|
|
25489
|
+
localNodeId: this._getLocalNodeId(),
|
|
25490
|
+
initialTargetNodeId: '*',
|
|
25327
25491
|
});
|
|
25328
25492
|
await connector.start(this.wrappedHandler);
|
|
25329
25493
|
this.connector = connector;
|
|
@@ -25349,6 +25513,20 @@
|
|
|
25349
25513
|
}
|
|
25350
25514
|
const attachInfo = await this.attachClient.attach(this.node, this.outboundOriginType, connector, welcome.frame, this.wrappedHandler, this.getKeys() ?? undefined, callbackGrants);
|
|
25351
25515
|
this.targetSystemId = attachInfo.targetSystemId ?? null;
|
|
25516
|
+
if (this.targetSystemId) {
|
|
25517
|
+
const targetAware = connector;
|
|
25518
|
+
if (typeof targetAware.setTargetNodeId === 'function') {
|
|
25519
|
+
try {
|
|
25520
|
+
targetAware.setTargetNodeId(this.targetSystemId);
|
|
25521
|
+
}
|
|
25522
|
+
catch (error) {
|
|
25523
|
+
logger$Z.warning('broadcast_channel_target_apply_failed', {
|
|
25524
|
+
error: error instanceof Error ? error.message : String(error),
|
|
25525
|
+
target_node_id: this.targetSystemId,
|
|
25526
|
+
});
|
|
25527
|
+
}
|
|
25528
|
+
}
|
|
25529
|
+
}
|
|
25352
25530
|
await this.onAttach(attachInfo, connector);
|
|
25353
25531
|
// Close the admission client immediately after attach completes
|
|
25354
25532
|
// This releases HTTP keep-alive connections (Node.js fetch/undici requires explicit cleanup)
|
|
@@ -25411,7 +25589,7 @@
|
|
|
25411
25589
|
this.currentStopSubtasks = null;
|
|
25412
25590
|
await Promise.allSettled(tasks.map((task) => task.promise));
|
|
25413
25591
|
if (this.connector) {
|
|
25414
|
-
logger$Z.
|
|
25592
|
+
logger$Z.debug('upstream_stopping_old_connector', {
|
|
25415
25593
|
connect_epoch: this.connectEpoch,
|
|
25416
25594
|
target_system_id: this.targetSystemId,
|
|
25417
25595
|
timestamp: new Date().toISOString(),
|
|
@@ -25422,7 +25600,7 @@
|
|
|
25422
25600
|
error: err instanceof Error ? err.message : String(err),
|
|
25423
25601
|
});
|
|
25424
25602
|
});
|
|
25425
|
-
logger$Z.
|
|
25603
|
+
logger$Z.debug('upstream_old_connector_stopped', {
|
|
25426
25604
|
connect_epoch: this.connectEpoch,
|
|
25427
25605
|
target_system_id: this.targetSystemId,
|
|
25428
25606
|
timestamp: new Date().toISOString(),
|
|
@@ -25624,8 +25802,15 @@
|
|
|
25624
25802
|
if (!envelope) {
|
|
25625
25803
|
continue;
|
|
25626
25804
|
}
|
|
25805
|
+
logger$Z.debug('upstream_pump_sending_envelope', {
|
|
25806
|
+
envelopeId: envelope.id,
|
|
25807
|
+
type: envelope.frame?.type,
|
|
25808
|
+
});
|
|
25627
25809
|
try {
|
|
25628
25810
|
await connector.send(envelope);
|
|
25811
|
+
logger$Z.debug('upstream_pump_sent_envelope', {
|
|
25812
|
+
envelopeId: envelope.id,
|
|
25813
|
+
});
|
|
25629
25814
|
}
|
|
25630
25815
|
catch (error) {
|
|
25631
25816
|
if (error instanceof FameMessageTooLarge) {
|
|
@@ -34846,10 +35031,31 @@
|
|
|
34846
35031
|
}
|
|
34847
35032
|
return null;
|
|
34848
35033
|
}
|
|
35034
|
+
static normalizeNodeId(value) {
|
|
35035
|
+
if (typeof value !== 'string') {
|
|
35036
|
+
return null;
|
|
35037
|
+
}
|
|
35038
|
+
const trimmed = value.trim();
|
|
35039
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
35040
|
+
}
|
|
35041
|
+
static normalizeTargetNodeId(value) {
|
|
35042
|
+
if (typeof value !== 'string') {
|
|
35043
|
+
return undefined;
|
|
35044
|
+
}
|
|
35045
|
+
const trimmed = value.trim();
|
|
35046
|
+
if (trimmed.length === 0) {
|
|
35047
|
+
return undefined;
|
|
35048
|
+
}
|
|
35049
|
+
if (trimmed === '*') {
|
|
35050
|
+
return '*';
|
|
35051
|
+
}
|
|
35052
|
+
return trimmed;
|
|
35053
|
+
}
|
|
34849
35054
|
constructor(config, baseConfig = {}) {
|
|
34850
35055
|
ensureBrowserEnvironment$2();
|
|
34851
35056
|
super(baseConfig);
|
|
34852
35057
|
this.listenerRegistered = false;
|
|
35058
|
+
this.visibilityChangeListenerRegistered = false;
|
|
34853
35059
|
this.channelName =
|
|
34854
35060
|
typeof config.channelName === 'string' && config.channelName.trim().length > 0
|
|
34855
35061
|
? config.channelName.trim()
|
|
@@ -34860,41 +35066,68 @@
|
|
|
34860
35066
|
? Math.floor(config.inboxCapacity)
|
|
34861
35067
|
: DEFAULT_INBOX_CAPACITY$6;
|
|
34862
35068
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
35069
|
+
this.inboxCapacity = preferredCapacity;
|
|
34863
35070
|
this.connectorId = InPageConnector.generateConnectorId();
|
|
35071
|
+
const normalizedLocalNodeId = InPageConnector.normalizeNodeId(config.localNodeId);
|
|
35072
|
+
if (!normalizedLocalNodeId) {
|
|
35073
|
+
throw new Error('InPageConnector requires a non-empty localNodeId');
|
|
35074
|
+
}
|
|
35075
|
+
this.localNodeId = normalizedLocalNodeId;
|
|
35076
|
+
this.targetNodeId = InPageConnector.normalizeTargetNodeId(config.initialTargetNodeId);
|
|
34864
35077
|
logger$G.debug('inpage_connector_initialized', {
|
|
34865
35078
|
channel: this.channelName,
|
|
34866
35079
|
connector_id: this.connectorId,
|
|
35080
|
+
local_node_id: this.localNodeId,
|
|
35081
|
+
target_node_id: this.targetNodeId ?? null,
|
|
35082
|
+
inbox_capacity: preferredCapacity,
|
|
34867
35083
|
});
|
|
34868
35084
|
this.onMsg = (event) => {
|
|
35085
|
+
if (!this.listenerRegistered) {
|
|
35086
|
+
logger$G.warning('inpage_message_after_unregister', {
|
|
35087
|
+
channel: this.channelName,
|
|
35088
|
+
connector_id: this.connectorId,
|
|
35089
|
+
timestamp: new Date().toISOString(),
|
|
35090
|
+
});
|
|
35091
|
+
return;
|
|
35092
|
+
}
|
|
34869
35093
|
const messageEvent = event;
|
|
34870
35094
|
const message = messageEvent.data;
|
|
34871
35095
|
logger$G.debug('inpage_raw_event', {
|
|
34872
35096
|
channel: this.channelName,
|
|
34873
35097
|
connector_id: this.connectorId,
|
|
34874
|
-
message_type: message && typeof message === 'object'
|
|
34875
|
-
|
|
34876
|
-
payload_type: message && typeof message === 'object'
|
|
34877
|
-
? message?.payload instanceof Uint8Array
|
|
34878
|
-
? 'Uint8Array'
|
|
34879
|
-
: message?.payload instanceof ArrayBuffer
|
|
34880
|
-
? 'ArrayBuffer'
|
|
34881
|
-
: typeof message?.payload
|
|
35098
|
+
message_type: message && typeof message === 'object'
|
|
35099
|
+
? message.constructor?.name ?? typeof message
|
|
34882
35100
|
: typeof message,
|
|
34883
|
-
|
|
34884
|
-
|
|
34885
|
-
: undefined,
|
|
34886
|
-
payload_keys: message && typeof message === 'object' && message?.payload && typeof message?.payload === 'object'
|
|
34887
|
-
? Object.keys(message.payload).slice(0, 5)
|
|
34888
|
-
: undefined,
|
|
35101
|
+
has_sender_id: Boolean(message?.senderId),
|
|
35102
|
+
has_sender_node_id: Boolean(message?.senderNodeId),
|
|
34889
35103
|
});
|
|
34890
35104
|
if (!message || typeof message !== 'object') {
|
|
34891
35105
|
return;
|
|
34892
35106
|
}
|
|
34893
35107
|
const busMessage = message;
|
|
34894
|
-
|
|
35108
|
+
const senderId = typeof busMessage.senderId === 'string' && busMessage.senderId.length > 0
|
|
35109
|
+
? busMessage.senderId
|
|
35110
|
+
: null;
|
|
35111
|
+
const senderNodeId = InPageConnector.normalizeNodeId(busMessage.senderNodeId);
|
|
35112
|
+
if (!senderId || !senderNodeId) {
|
|
35113
|
+
logger$G.debug('inpage_message_rejected', {
|
|
35114
|
+
channel: this.channelName,
|
|
35115
|
+
connector_id: this.connectorId,
|
|
35116
|
+
reason: 'missing_sender_metadata',
|
|
35117
|
+
});
|
|
35118
|
+
return;
|
|
35119
|
+
}
|
|
35120
|
+
if (senderId === this.connectorId || senderNodeId === this.localNodeId) {
|
|
35121
|
+
logger$G.debug('inpage_message_rejected', {
|
|
35122
|
+
channel: this.channelName,
|
|
35123
|
+
connector_id: this.connectorId,
|
|
35124
|
+
reason: 'self_echo',
|
|
35125
|
+
sender_node_id: senderNodeId,
|
|
35126
|
+
});
|
|
34895
35127
|
return;
|
|
34896
35128
|
}
|
|
34897
|
-
|
|
35129
|
+
const incomingTargetNodeId = InPageConnector.normalizeTargetNodeId(busMessage.targetNodeId);
|
|
35130
|
+
if (!this._shouldAcceptMessageFromBus(senderNodeId, incomingTargetNodeId)) {
|
|
34898
35131
|
return;
|
|
34899
35132
|
}
|
|
34900
35133
|
const payload = InPageConnector.coercePayload(busMessage.payload);
|
|
@@ -34908,7 +35141,9 @@
|
|
|
34908
35141
|
}
|
|
34909
35142
|
logger$G.debug('inpage_message_received', {
|
|
34910
35143
|
channel: this.channelName,
|
|
34911
|
-
sender_id:
|
|
35144
|
+
sender_id: senderId,
|
|
35145
|
+
sender_node_id: senderNodeId,
|
|
35146
|
+
target_node_id: incomingTargetNodeId ?? null,
|
|
34912
35147
|
connector_id: this.connectorId,
|
|
34913
35148
|
payload_length: payload.byteLength,
|
|
34914
35149
|
});
|
|
@@ -34916,15 +35151,27 @@
|
|
|
34916
35151
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
34917
35152
|
const accepted = this.inbox.tryEnqueue(payload);
|
|
34918
35153
|
if (accepted) {
|
|
35154
|
+
this.logInboxSnapshot('inpage_inbox_enqueued', {
|
|
35155
|
+
source: 'listener',
|
|
35156
|
+
enqueue_strategy: 'try',
|
|
35157
|
+
payload_length: payload.byteLength,
|
|
35158
|
+
});
|
|
34919
35159
|
return;
|
|
34920
35160
|
}
|
|
34921
35161
|
}
|
|
34922
35162
|
this.inbox.enqueue(payload);
|
|
35163
|
+
this.logInboxSnapshot('inpage_inbox_enqueued', {
|
|
35164
|
+
source: 'listener',
|
|
35165
|
+
enqueue_strategy: 'enqueue',
|
|
35166
|
+
payload_length: payload.byteLength,
|
|
35167
|
+
});
|
|
34923
35168
|
}
|
|
34924
35169
|
catch (error) {
|
|
34925
35170
|
if (error instanceof QueueFullError) {
|
|
34926
35171
|
logger$G.warning('inpage_receive_queue_full', {
|
|
34927
35172
|
channel: this.channelName,
|
|
35173
|
+
inbox_capacity: this.inboxCapacity,
|
|
35174
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
34928
35175
|
});
|
|
34929
35176
|
}
|
|
34930
35177
|
else {
|
|
@@ -34937,6 +35184,92 @@
|
|
|
34937
35184
|
};
|
|
34938
35185
|
getSharedBus$1().addEventListener(this.channelName, this.onMsg);
|
|
34939
35186
|
this.listenerRegistered = true;
|
|
35187
|
+
// Setup visibility change monitoring
|
|
35188
|
+
this.visibilityChangeHandler = () => {
|
|
35189
|
+
const isHidden = document.hidden;
|
|
35190
|
+
logger$G.debug('inpage_visibility_changed', {
|
|
35191
|
+
channel: this.channelName,
|
|
35192
|
+
connector_id: this.connectorId,
|
|
35193
|
+
visibility: isHidden ? 'hidden' : 'visible',
|
|
35194
|
+
timestamp: new Date().toISOString(),
|
|
35195
|
+
});
|
|
35196
|
+
// Pause/resume connector based on visibility
|
|
35197
|
+
if (isHidden && this.state === ConnectorState.STARTED) {
|
|
35198
|
+
this.pause().catch((err) => {
|
|
35199
|
+
logger$G.warning('inpage_pause_failed', {
|
|
35200
|
+
channel: this.channelName,
|
|
35201
|
+
connector_id: this.connectorId,
|
|
35202
|
+
error: err instanceof Error ? err.message : String(err),
|
|
35203
|
+
});
|
|
35204
|
+
});
|
|
35205
|
+
}
|
|
35206
|
+
else if (!isHidden && this.state === ConnectorState.PAUSED) {
|
|
35207
|
+
this.resume().catch((err) => {
|
|
35208
|
+
logger$G.warning('inpage_resume_failed', {
|
|
35209
|
+
channel: this.channelName,
|
|
35210
|
+
connector_id: this.connectorId,
|
|
35211
|
+
error: err instanceof Error ? err.message : String(err),
|
|
35212
|
+
});
|
|
35213
|
+
});
|
|
35214
|
+
}
|
|
35215
|
+
};
|
|
35216
|
+
if (typeof document !== 'undefined') {
|
|
35217
|
+
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
35218
|
+
this.visibilityChangeListenerRegistered = true;
|
|
35219
|
+
// Track page lifecycle events to detect browser unload/discard
|
|
35220
|
+
if (typeof window !== 'undefined') {
|
|
35221
|
+
const lifecycleLogger = (event) => {
|
|
35222
|
+
logger$G.info('inpage_page_lifecycle', {
|
|
35223
|
+
channel: this.channelName,
|
|
35224
|
+
connector_id: this.connectorId,
|
|
35225
|
+
event_type: event.type,
|
|
35226
|
+
visibility_state: document.visibilityState,
|
|
35227
|
+
timestamp: new Date().toISOString(),
|
|
35228
|
+
});
|
|
35229
|
+
};
|
|
35230
|
+
window.addEventListener('beforeunload', lifecycleLogger);
|
|
35231
|
+
window.addEventListener('unload', lifecycleLogger);
|
|
35232
|
+
window.addEventListener('pagehide', lifecycleLogger);
|
|
35233
|
+
window.addEventListener('pageshow', lifecycleLogger);
|
|
35234
|
+
document.addEventListener('freeze', lifecycleLogger);
|
|
35235
|
+
document.addEventListener('resume', lifecycleLogger);
|
|
35236
|
+
}
|
|
35237
|
+
// Log initial state with detailed visibility info
|
|
35238
|
+
logger$G.debug('inpage_initial_visibility', {
|
|
35239
|
+
channel: this.channelName,
|
|
35240
|
+
connector_id: this.connectorId,
|
|
35241
|
+
visibility: document.hidden ? 'hidden' : 'visible',
|
|
35242
|
+
document_hidden: document.hidden,
|
|
35243
|
+
visibility_state: document.visibilityState,
|
|
35244
|
+
has_focus: document.hasFocus(),
|
|
35245
|
+
timestamp: new Date().toISOString(),
|
|
35246
|
+
});
|
|
35247
|
+
}
|
|
35248
|
+
}
|
|
35249
|
+
/**
|
|
35250
|
+
* Override start() to check initial visibility state
|
|
35251
|
+
*/
|
|
35252
|
+
async start(inboundHandler) {
|
|
35253
|
+
await super.start(inboundHandler);
|
|
35254
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
35255
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
35256
|
+
logger$G.debug('inpage_start_in_hidden_tab', {
|
|
35257
|
+
channel: this.channelName,
|
|
35258
|
+
connector_id: this.connectorId,
|
|
35259
|
+
document_hidden: document.hidden,
|
|
35260
|
+
visibility_state: document.visibilityState,
|
|
35261
|
+
has_focus: document.hasFocus(),
|
|
35262
|
+
timestamp: new Date().toISOString(),
|
|
35263
|
+
});
|
|
35264
|
+
// Immediately pause if tab is hidden at start time
|
|
35265
|
+
await this.pause().catch((err) => {
|
|
35266
|
+
logger$G.warning('inpage_initial_pause_failed', {
|
|
35267
|
+
channel: this.channelName,
|
|
35268
|
+
connector_id: this.connectorId,
|
|
35269
|
+
error: err instanceof Error ? err.message : String(err),
|
|
35270
|
+
});
|
|
35271
|
+
});
|
|
35272
|
+
}
|
|
34940
35273
|
}
|
|
34941
35274
|
// Allow listeners to feed envelopes directly into the in-page receive queue.
|
|
34942
35275
|
async pushToReceive(rawOrEnvelope) {
|
|
@@ -34945,15 +35278,25 @@
|
|
|
34945
35278
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
34946
35279
|
const accepted = this.inbox.tryEnqueue(item);
|
|
34947
35280
|
if (accepted) {
|
|
35281
|
+
this.logInboxSnapshot('inpage_push_enqueued', {
|
|
35282
|
+
enqueue_strategy: 'try',
|
|
35283
|
+
item_type: this._describeInboxItem(item),
|
|
35284
|
+
});
|
|
34948
35285
|
return;
|
|
34949
35286
|
}
|
|
34950
35287
|
}
|
|
34951
35288
|
this.inbox.enqueue(item);
|
|
35289
|
+
this.logInboxSnapshot('inpage_push_enqueued', {
|
|
35290
|
+
enqueue_strategy: 'enqueue',
|
|
35291
|
+
item_type: this._describeInboxItem(item),
|
|
35292
|
+
});
|
|
34952
35293
|
}
|
|
34953
35294
|
catch (error) {
|
|
34954
35295
|
if (error instanceof QueueFullError) {
|
|
34955
35296
|
logger$G.warning('inpage_push_queue_full', {
|
|
34956
35297
|
channel: this.channelName,
|
|
35298
|
+
inbox_capacity: this.inboxCapacity,
|
|
35299
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
34957
35300
|
});
|
|
34958
35301
|
throw error;
|
|
34959
35302
|
}
|
|
@@ -34966,25 +35309,57 @@
|
|
|
34966
35309
|
}
|
|
34967
35310
|
async _transportSendBytes(data) {
|
|
34968
35311
|
ensureBrowserEnvironment$2();
|
|
35312
|
+
const targetNodeId = this.targetNodeId ?? '*';
|
|
34969
35313
|
logger$G.debug('inpage_message_sending', {
|
|
34970
35314
|
channel: this.channelName,
|
|
34971
35315
|
sender_id: this.connectorId,
|
|
35316
|
+
sender_node_id: this.localNodeId,
|
|
35317
|
+
target_node_id: targetNodeId,
|
|
34972
35318
|
});
|
|
34973
35319
|
const event = new MessageEvent(this.channelName, {
|
|
34974
35320
|
data: {
|
|
34975
35321
|
senderId: this.connectorId,
|
|
35322
|
+
senderNodeId: this.localNodeId,
|
|
35323
|
+
targetNodeId,
|
|
34976
35324
|
payload: data,
|
|
34977
35325
|
},
|
|
34978
35326
|
});
|
|
34979
35327
|
getSharedBus$1().dispatchEvent(event);
|
|
34980
35328
|
}
|
|
34981
35329
|
async _transportReceive() {
|
|
34982
|
-
|
|
35330
|
+
const item = await this.inbox.dequeue();
|
|
35331
|
+
this.logInboxSnapshot('inpage_inbox_dequeued', {
|
|
35332
|
+
item_type: this._describeInboxItem(item),
|
|
35333
|
+
});
|
|
35334
|
+
return item;
|
|
34983
35335
|
}
|
|
34984
35336
|
async _transportClose(code, reason) {
|
|
35337
|
+
logger$G.debug('inpage_transport_closing', {
|
|
35338
|
+
channel: this.channelName,
|
|
35339
|
+
connector_id: this.connectorId,
|
|
35340
|
+
code,
|
|
35341
|
+
reason,
|
|
35342
|
+
listener_registered: this.listenerRegistered,
|
|
35343
|
+
timestamp: new Date().toISOString(),
|
|
35344
|
+
});
|
|
34985
35345
|
if (this.listenerRegistered) {
|
|
35346
|
+
logger$G.debug('inpage_removing_listener', {
|
|
35347
|
+
channel: this.channelName,
|
|
35348
|
+
connector_id: this.connectorId,
|
|
35349
|
+
timestamp: new Date().toISOString(),
|
|
35350
|
+
});
|
|
34986
35351
|
getSharedBus$1().removeEventListener(this.channelName, this.onMsg);
|
|
34987
35352
|
this.listenerRegistered = false;
|
|
35353
|
+
logger$G.debug('inpage_listener_removed', {
|
|
35354
|
+
channel: this.channelName,
|
|
35355
|
+
connector_id: this.connectorId,
|
|
35356
|
+
timestamp: new Date().toISOString(),
|
|
35357
|
+
});
|
|
35358
|
+
}
|
|
35359
|
+
if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
35360
|
+
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
35361
|
+
this.visibilityChangeListenerRegistered = false;
|
|
35362
|
+
this.visibilityChangeHandler = undefined;
|
|
34988
35363
|
}
|
|
34989
35364
|
const closeCode = typeof code === 'number' ? code : 1000;
|
|
34990
35365
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
@@ -34997,6 +35372,103 @@
|
|
|
34997
35372
|
}
|
|
34998
35373
|
return rawOrEnvelope;
|
|
34999
35374
|
}
|
|
35375
|
+
_isWildcardTarget() {
|
|
35376
|
+
return this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined';
|
|
35377
|
+
}
|
|
35378
|
+
_shouldAcceptMessageFromBus(senderNodeId, targetNodeId) {
|
|
35379
|
+
if (this._isWildcardTarget()) {
|
|
35380
|
+
if (targetNodeId &&
|
|
35381
|
+
targetNodeId !== '*' &&
|
|
35382
|
+
targetNodeId !== this.localNodeId) {
|
|
35383
|
+
logger$G.debug('inpage_message_rejected', {
|
|
35384
|
+
channel: this.channelName,
|
|
35385
|
+
connector_id: this.connectorId,
|
|
35386
|
+
reason: 'wildcard_target_mismatch',
|
|
35387
|
+
sender_node_id: senderNodeId,
|
|
35388
|
+
target_node_id: targetNodeId,
|
|
35389
|
+
local_node_id: this.localNodeId,
|
|
35390
|
+
});
|
|
35391
|
+
return false;
|
|
35392
|
+
}
|
|
35393
|
+
return true;
|
|
35394
|
+
}
|
|
35395
|
+
const expectedSender = this.targetNodeId;
|
|
35396
|
+
if (expectedSender && expectedSender !== '*' && senderNodeId !== expectedSender) {
|
|
35397
|
+
logger$G.debug('inpage_message_rejected', {
|
|
35398
|
+
channel: this.channelName,
|
|
35399
|
+
connector_id: this.connectorId,
|
|
35400
|
+
reason: 'unexpected_sender',
|
|
35401
|
+
expected_sender_node_id: expectedSender,
|
|
35402
|
+
sender_node_id: senderNodeId,
|
|
35403
|
+
local_node_id: this.localNodeId,
|
|
35404
|
+
});
|
|
35405
|
+
return false;
|
|
35406
|
+
}
|
|
35407
|
+
if (targetNodeId &&
|
|
35408
|
+
targetNodeId !== '*' &&
|
|
35409
|
+
targetNodeId !== this.localNodeId) {
|
|
35410
|
+
logger$G.debug('inpage_message_rejected', {
|
|
35411
|
+
channel: this.channelName,
|
|
35412
|
+
connector_id: this.connectorId,
|
|
35413
|
+
reason: 'unexpected_target',
|
|
35414
|
+
sender_node_id: senderNodeId,
|
|
35415
|
+
target_node_id: targetNodeId,
|
|
35416
|
+
local_node_id: this.localNodeId,
|
|
35417
|
+
});
|
|
35418
|
+
return false;
|
|
35419
|
+
}
|
|
35420
|
+
return true;
|
|
35421
|
+
}
|
|
35422
|
+
_describeInboxItem(item) {
|
|
35423
|
+
if (item instanceof Uint8Array) {
|
|
35424
|
+
return 'bytes';
|
|
35425
|
+
}
|
|
35426
|
+
if (item.envelope) {
|
|
35427
|
+
return 'channel_message';
|
|
35428
|
+
}
|
|
35429
|
+
if (item.frame) {
|
|
35430
|
+
return 'envelope';
|
|
35431
|
+
}
|
|
35432
|
+
return 'unknown';
|
|
35433
|
+
}
|
|
35434
|
+
logInboxSnapshot(event, extra = {}) {
|
|
35435
|
+
logger$G.debug(event, {
|
|
35436
|
+
channel: this.channelName,
|
|
35437
|
+
connector_id: this.connectorId,
|
|
35438
|
+
connector_state: this.state,
|
|
35439
|
+
inbox_capacity: this.inboxCapacity,
|
|
35440
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
35441
|
+
...extra,
|
|
35442
|
+
});
|
|
35443
|
+
}
|
|
35444
|
+
setTargetNodeId(nodeId) {
|
|
35445
|
+
const normalized = InPageConnector.normalizeNodeId(nodeId);
|
|
35446
|
+
if (!normalized) {
|
|
35447
|
+
throw new Error('InPageConnector target node id must be a non-empty string');
|
|
35448
|
+
}
|
|
35449
|
+
if (normalized === '*') {
|
|
35450
|
+
this.setWildcardTarget();
|
|
35451
|
+
return;
|
|
35452
|
+
}
|
|
35453
|
+
this.targetNodeId = normalized;
|
|
35454
|
+
logger$G.debug('inpage_target_updated', {
|
|
35455
|
+
channel: this.channelName,
|
|
35456
|
+
connector_id: this.connectorId,
|
|
35457
|
+
local_node_id: this.localNodeId,
|
|
35458
|
+
target_node_id: this.targetNodeId,
|
|
35459
|
+
target_mode: 'direct',
|
|
35460
|
+
});
|
|
35461
|
+
}
|
|
35462
|
+
setWildcardTarget() {
|
|
35463
|
+
this.targetNodeId = '*';
|
|
35464
|
+
logger$G.debug('inpage_target_updated', {
|
|
35465
|
+
channel: this.channelName,
|
|
35466
|
+
connector_id: this.connectorId,
|
|
35467
|
+
local_node_id: this.localNodeId,
|
|
35468
|
+
target_node_id: this.targetNodeId,
|
|
35469
|
+
target_mode: 'wildcard',
|
|
35470
|
+
});
|
|
35471
|
+
}
|
|
35000
35472
|
}
|
|
35001
35473
|
|
|
35002
35474
|
const RPC_REGISTRY = Symbol('naylence.rpc.registry');
|
|
@@ -42424,8 +42896,16 @@
|
|
|
42424
42896
|
}
|
|
42425
42897
|
const normalized = this._normalizeConfig(config);
|
|
42426
42898
|
const options = (factoryArgs[0] ?? {});
|
|
42899
|
+
const normalizedLocalNodeFromConfig = this._normalizeNodeId(normalized.localNodeId);
|
|
42900
|
+
const localNodeId = this._normalizeNodeId(options.localNodeId) ?? normalizedLocalNodeFromConfig;
|
|
42901
|
+
if (!localNodeId) {
|
|
42902
|
+
throw new Error('InPageConnectorFactory requires a localNodeId from config or create() options');
|
|
42903
|
+
}
|
|
42427
42904
|
const channelName = normalized.channelName ?? DEFAULT_CHANNEL$5;
|
|
42428
42905
|
const inboxCapacity = normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
|
|
42906
|
+
const targetFromOptions = this._normalizeTargetNodeId(options.initialTargetNodeId);
|
|
42907
|
+
const targetFromConfig = this._normalizeTargetNodeId(normalized.initialTargetNodeId);
|
|
42908
|
+
const resolvedTarget = targetFromOptions ?? targetFromConfig ?? '*';
|
|
42429
42909
|
const baseConfig = {
|
|
42430
42910
|
drainTimeout: normalized.drainTimeout,
|
|
42431
42911
|
flowControl: normalized.flowControl,
|
|
@@ -42440,6 +42920,8 @@
|
|
|
42440
42920
|
type: INPAGE_CONNECTOR_TYPE,
|
|
42441
42921
|
channelName,
|
|
42442
42922
|
inboxCapacity,
|
|
42923
|
+
localNodeId,
|
|
42924
|
+
initialTargetNodeId: resolvedTarget,
|
|
42443
42925
|
};
|
|
42444
42926
|
const connector = new InPageConnector(connectorConfig, baseConfig);
|
|
42445
42927
|
if (options.authorization) {
|
|
@@ -42475,6 +42957,16 @@
|
|
|
42475
42957
|
capacity > 0) {
|
|
42476
42958
|
normalized.inboxCapacity = Math.floor(capacity);
|
|
42477
42959
|
}
|
|
42960
|
+
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
42961
|
+
const normalizedLocalNodeId = this._normalizeNodeId(localNodeId);
|
|
42962
|
+
if (normalizedLocalNodeId) {
|
|
42963
|
+
normalized.localNodeId = normalizedLocalNodeId;
|
|
42964
|
+
}
|
|
42965
|
+
const initialTargetNodeId = candidate.initialTargetNodeId ?? candidate['initial_target_node_id'];
|
|
42966
|
+
const normalizedTarget = this._normalizeTargetNodeId(initialTargetNodeId);
|
|
42967
|
+
if (normalizedTarget) {
|
|
42968
|
+
normalized.initialTargetNodeId = normalizedTarget;
|
|
42969
|
+
}
|
|
42478
42970
|
if (typeof candidate.flowControl === 'boolean') {
|
|
42479
42971
|
normalized.flowControl = candidate.flowControl;
|
|
42480
42972
|
}
|
|
@@ -42513,6 +43005,22 @@
|
|
|
42513
43005
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
|
|
42514
43006
|
return normalized;
|
|
42515
43007
|
}
|
|
43008
|
+
_normalizeNodeId(value) {
|
|
43009
|
+
if (typeof value !== 'string') {
|
|
43010
|
+
return null;
|
|
43011
|
+
}
|
|
43012
|
+
const trimmed = value.trim();
|
|
43013
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
43014
|
+
}
|
|
43015
|
+
_normalizeTargetNodeId(value) {
|
|
43016
|
+
if (value === undefined || value === null) {
|
|
43017
|
+
return undefined;
|
|
43018
|
+
}
|
|
43019
|
+
if (value === '*') {
|
|
43020
|
+
return '*';
|
|
43021
|
+
}
|
|
43022
|
+
return this._normalizeNodeId(value) ?? undefined;
|
|
43023
|
+
}
|
|
42516
43024
|
}
|
|
42517
43025
|
|
|
42518
43026
|
var inpageConnectorFactory = /*#__PURE__*/Object.freeze({
|
|
@@ -42558,6 +43066,7 @@
|
|
|
42558
43066
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
42559
43067
|
channelName: connectorConfig.channelName,
|
|
42560
43068
|
inboxCapacity: connectorConfig.inboxCapacity,
|
|
43069
|
+
initialWindow: connectorConfig.initialWindow,
|
|
42561
43070
|
};
|
|
42562
43071
|
}
|
|
42563
43072
|
const config = {
|
|
@@ -42582,6 +43091,7 @@
|
|
|
42582
43091
|
purpose: 'connection',
|
|
42583
43092
|
channelName: normalizedConfig.channelName,
|
|
42584
43093
|
inboxCapacity: normalizedConfig.inboxCapacity,
|
|
43094
|
+
initialWindow: normalizedConfig.initialWindow,
|
|
42585
43095
|
});
|
|
42586
43096
|
return grant;
|
|
42587
43097
|
}
|
|
@@ -42591,8 +43101,16 @@
|
|
|
42591
43101
|
}
|
|
42592
43102
|
const normalized = this._normalizeConfig(config);
|
|
42593
43103
|
const options = (factoryArgs[0] ?? {});
|
|
43104
|
+
const normalizedLocalNodeFromConfig = this._normalizeNodeId(normalized.localNodeId);
|
|
43105
|
+
const localNodeId = this._normalizeNodeId(options.localNodeId) ?? normalizedLocalNodeFromConfig;
|
|
43106
|
+
if (!localNodeId) {
|
|
43107
|
+
throw new Error('BroadcastChannelConnectorFactory requires a localNodeId from config or create() options');
|
|
43108
|
+
}
|
|
42594
43109
|
const channelName = normalized.channelName ?? DEFAULT_CHANNEL$4;
|
|
42595
43110
|
const inboxCapacity = normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$4;
|
|
43111
|
+
const targetFromOptions = this._normalizeTargetNodeId(options.initialTargetNodeId);
|
|
43112
|
+
const targetFromConfig = this._normalizeTargetNodeId(normalized.initialTargetNodeId);
|
|
43113
|
+
const resolvedTarget = targetFromOptions ?? targetFromConfig ?? '*';
|
|
42596
43114
|
const baseConfig = {
|
|
42597
43115
|
drainTimeout: normalized.drainTimeout,
|
|
42598
43116
|
flowControl: normalized.flowControl,
|
|
@@ -42607,6 +43125,8 @@
|
|
|
42607
43125
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
42608
43126
|
channelName,
|
|
42609
43127
|
inboxCapacity,
|
|
43128
|
+
localNodeId,
|
|
43129
|
+
initialTargetNodeId: resolvedTarget,
|
|
42610
43130
|
};
|
|
42611
43131
|
const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
42612
43132
|
if (options.authorization) {
|
|
@@ -42630,11 +43150,21 @@
|
|
|
42630
43150
|
normalized.channelName = channel.trim();
|
|
42631
43151
|
}
|
|
42632
43152
|
const capacity = candidate.inboxCapacity ?? candidate['inbox_capacity'];
|
|
43153
|
+
const initialTargetNodeId = candidate.initialTargetNodeId ?? candidate['initial_target_node_id'];
|
|
43154
|
+
const normalizedTarget = this._normalizeTargetNodeId(initialTargetNodeId);
|
|
43155
|
+
if (normalizedTarget) {
|
|
43156
|
+
normalized.initialTargetNodeId = normalizedTarget;
|
|
43157
|
+
}
|
|
42633
43158
|
if (typeof capacity === 'number' &&
|
|
42634
43159
|
Number.isFinite(capacity) &&
|
|
42635
43160
|
capacity > 0) {
|
|
42636
43161
|
normalized.inboxCapacity = Math.floor(capacity);
|
|
42637
43162
|
}
|
|
43163
|
+
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
43164
|
+
const normalizedLocalNodeId = this._normalizeNodeId(localNodeId);
|
|
43165
|
+
if (normalizedLocalNodeId) {
|
|
43166
|
+
normalized.localNodeId = normalizedLocalNodeId;
|
|
43167
|
+
}
|
|
42638
43168
|
if (typeof candidate.flowControl === 'boolean') {
|
|
42639
43169
|
normalized.flowControl = candidate.flowControl;
|
|
42640
43170
|
}
|
|
@@ -42673,6 +43203,22 @@
|
|
|
42673
43203
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$4;
|
|
42674
43204
|
return normalized;
|
|
42675
43205
|
}
|
|
43206
|
+
_normalizeNodeId(value) {
|
|
43207
|
+
if (typeof value !== 'string') {
|
|
43208
|
+
return null;
|
|
43209
|
+
}
|
|
43210
|
+
const trimmed = value.trim();
|
|
43211
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
43212
|
+
}
|
|
43213
|
+
_normalizeTargetNodeId(value) {
|
|
43214
|
+
if (value === undefined || value === null) {
|
|
43215
|
+
return undefined;
|
|
43216
|
+
}
|
|
43217
|
+
if (value === '*') {
|
|
43218
|
+
return '*';
|
|
43219
|
+
}
|
|
43220
|
+
return this._normalizeNodeId(value) ?? undefined;
|
|
43221
|
+
}
|
|
42676
43222
|
}
|
|
42677
43223
|
|
|
42678
43224
|
var broadcastChannelConnectorFactory = /*#__PURE__*/Object.freeze({
|
|
@@ -43253,7 +43799,7 @@
|
|
|
43253
43799
|
node: routingNode,
|
|
43254
43800
|
});
|
|
43255
43801
|
const selection = defaultGrantSelectionPolicy.selectCallbackGrant(selectionContext);
|
|
43256
|
-
connectorConfig = this._grantToConnectorConfig(selection.grant);
|
|
43802
|
+
connectorConfig = this._buildConnectorConfigForSystem(systemId, this._grantToConnectorConfig(selection.grant));
|
|
43257
43803
|
}
|
|
43258
43804
|
catch (error) {
|
|
43259
43805
|
logger$p.debug('inpage_listener_grant_selection_failed', {
|
|
@@ -43261,13 +43807,13 @@
|
|
|
43261
43807
|
system_id: systemId,
|
|
43262
43808
|
error: error instanceof Error ? error.message : String(error),
|
|
43263
43809
|
});
|
|
43264
|
-
|
|
43265
|
-
|
|
43266
|
-
|
|
43267
|
-
|
|
43268
|
-
|
|
43269
|
-
|
|
43270
|
-
|
|
43810
|
+
const fallbackConfig = this._extractInPageConnectorConfig(frame) ??
|
|
43811
|
+
{
|
|
43812
|
+
type: INPAGE_CONNECTOR_TYPE,
|
|
43813
|
+
channelName: this._channelName,
|
|
43814
|
+
inboxCapacity: this._inboxCapacity,
|
|
43815
|
+
};
|
|
43816
|
+
connectorConfig = this._buildConnectorConfigForSystem(systemId, fallbackConfig);
|
|
43271
43817
|
}
|
|
43272
43818
|
try {
|
|
43273
43819
|
const connector = await routingNode.createOriginConnector({
|
|
@@ -43386,6 +43932,65 @@
|
|
|
43386
43932
|
typeof frame === 'object' &&
|
|
43387
43933
|
frame.type === 'NodeAttach');
|
|
43388
43934
|
}
|
|
43935
|
+
_buildConnectorConfigForSystem(systemId, baseConfig) {
|
|
43936
|
+
const localNodeId = this._requireLocalNodeId();
|
|
43937
|
+
const targetSystemId = this._normalizeNodeId(systemId);
|
|
43938
|
+
if (!targetSystemId) {
|
|
43939
|
+
throw new Error('InPageListener requires a valid system id for connector creation');
|
|
43940
|
+
}
|
|
43941
|
+
const candidate = baseConfig ?? null;
|
|
43942
|
+
const channelCandidate = candidate && 'channelName' in candidate
|
|
43943
|
+
? candidate.channelName
|
|
43944
|
+
: undefined;
|
|
43945
|
+
const inboxCandidate = candidate && 'inboxCapacity' in candidate
|
|
43946
|
+
? candidate.inboxCapacity
|
|
43947
|
+
: undefined;
|
|
43948
|
+
const targetCandidate = candidate && 'initialTargetNodeId' in candidate
|
|
43949
|
+
? candidate.initialTargetNodeId
|
|
43950
|
+
: undefined;
|
|
43951
|
+
const channelName = typeof channelCandidate === 'string' && channelCandidate.trim().length > 0
|
|
43952
|
+
? channelCandidate.trim()
|
|
43953
|
+
: this._channelName;
|
|
43954
|
+
const inboxCapacity = typeof inboxCandidate === 'number' &&
|
|
43955
|
+
Number.isFinite(inboxCandidate) &&
|
|
43956
|
+
inboxCandidate > 0
|
|
43957
|
+
? Math.floor(inboxCandidate)
|
|
43958
|
+
: this._inboxCapacity;
|
|
43959
|
+
const normalizedTarget = this._normalizeTargetNodeId(targetCandidate);
|
|
43960
|
+
return {
|
|
43961
|
+
type: INPAGE_CONNECTOR_TYPE,
|
|
43962
|
+
channelName,
|
|
43963
|
+
inboxCapacity,
|
|
43964
|
+
localNodeId,
|
|
43965
|
+
initialTargetNodeId: normalizedTarget ?? targetSystemId,
|
|
43966
|
+
};
|
|
43967
|
+
}
|
|
43968
|
+
_requireLocalNodeId() {
|
|
43969
|
+
if (!this._routingNode) {
|
|
43970
|
+
throw new Error('InPageListener requires routing node context');
|
|
43971
|
+
}
|
|
43972
|
+
const normalized = this._normalizeNodeId(this._routingNode.id);
|
|
43973
|
+
if (!normalized) {
|
|
43974
|
+
throw new Error('InPageListener requires routing node with a stable identifier');
|
|
43975
|
+
}
|
|
43976
|
+
return normalized;
|
|
43977
|
+
}
|
|
43978
|
+
_normalizeNodeId(value) {
|
|
43979
|
+
if (typeof value !== 'string') {
|
|
43980
|
+
return null;
|
|
43981
|
+
}
|
|
43982
|
+
const trimmed = value.trim();
|
|
43983
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
43984
|
+
}
|
|
43985
|
+
_normalizeTargetNodeId(value) {
|
|
43986
|
+
if (value === undefined || value === null) {
|
|
43987
|
+
return undefined;
|
|
43988
|
+
}
|
|
43989
|
+
if (value === '*') {
|
|
43990
|
+
return '*';
|
|
43991
|
+
}
|
|
43992
|
+
return this._normalizeNodeId(value) ?? undefined;
|
|
43993
|
+
}
|
|
43389
43994
|
}
|
|
43390
43995
|
function getInPageListenerInstance() {
|
|
43391
43996
|
return _lastInPageListenerInstance;
|
|
@@ -43776,7 +44381,7 @@
|
|
|
43776
44381
|
node: routingNode,
|
|
43777
44382
|
});
|
|
43778
44383
|
const selection = defaultGrantSelectionPolicy.selectCallbackGrant(selectionContext);
|
|
43779
|
-
connectorConfig = this._grantToConnectorConfig(selection.grant);
|
|
44384
|
+
connectorConfig = this._grantToConnectorConfig(selection.grant, systemId);
|
|
43780
44385
|
}
|
|
43781
44386
|
catch (error) {
|
|
43782
44387
|
logger$o.debug('broadcast_channel_listener_grant_selection_failed', {
|
|
@@ -43785,12 +44390,20 @@
|
|
|
43785
44390
|
error: error instanceof Error ? error.message : String(error),
|
|
43786
44391
|
});
|
|
43787
44392
|
connectorConfig =
|
|
43788
|
-
this._extractBroadcastConnectorConfig(frame) ??
|
|
43789
|
-
{
|
|
44393
|
+
this._extractBroadcastConnectorConfig(frame, systemId) ??
|
|
44394
|
+
this._buildConnectorConfigForSystem(systemId, {
|
|
43790
44395
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
43791
44396
|
channelName: this._channelName,
|
|
43792
44397
|
inboxCapacity: this._inboxCapacity,
|
|
43793
|
-
|
|
44398
|
+
passive: true,
|
|
44399
|
+
});
|
|
44400
|
+
}
|
|
44401
|
+
if (!connectorConfig) {
|
|
44402
|
+
logger$o.error('broadcast_channel_listener_missing_connector_config', {
|
|
44403
|
+
sender_id: params.senderId,
|
|
44404
|
+
system_id: systemId,
|
|
44405
|
+
});
|
|
44406
|
+
return null;
|
|
43794
44407
|
}
|
|
43795
44408
|
try {
|
|
43796
44409
|
const connector = await routingNode.createOriginConnector({
|
|
@@ -43816,7 +44429,7 @@
|
|
|
43816
44429
|
return null;
|
|
43817
44430
|
}
|
|
43818
44431
|
}
|
|
43819
|
-
_extractBroadcastConnectorConfig(frame) {
|
|
44432
|
+
_extractBroadcastConnectorConfig(frame, systemId) {
|
|
43820
44433
|
const rawGrants = frame.callbackGrants;
|
|
43821
44434
|
if (!Array.isArray(rawGrants)) {
|
|
43822
44435
|
return null;
|
|
@@ -43827,7 +44440,10 @@
|
|
|
43827
44440
|
(grant.type === BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE ||
|
|
43828
44441
|
grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE)) {
|
|
43829
44442
|
try {
|
|
43830
|
-
|
|
44443
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
44444
|
+
return this._buildConnectorConfigForSystem(systemId, grant);
|
|
44445
|
+
}
|
|
44446
|
+
return this._buildConnectorConfigForSystem(systemId, broadcastChannelGrantToConnectorConfig(grant));
|
|
43831
44447
|
}
|
|
43832
44448
|
catch (error) {
|
|
43833
44449
|
logger$o.debug('broadcast_channel_listener_grant_normalization_failed', {
|
|
@@ -43838,30 +44454,86 @@
|
|
|
43838
44454
|
}
|
|
43839
44455
|
return null;
|
|
43840
44456
|
}
|
|
43841
|
-
_grantToConnectorConfig(grant) {
|
|
43842
|
-
if (grant.type
|
|
43843
|
-
|
|
43844
|
-
|
|
44457
|
+
_grantToConnectorConfig(grant, systemId) {
|
|
44458
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
44459
|
+
return this._buildConnectorConfigForSystem(systemId, grant);
|
|
44460
|
+
}
|
|
44461
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE) {
|
|
44462
|
+
return this._buildConnectorConfigForSystem(systemId, broadcastChannelGrantToConnectorConfig(grant));
|
|
44463
|
+
}
|
|
44464
|
+
if ('toConnectorConfig' in grant &&
|
|
44465
|
+
typeof grant.toConnectorConfig ===
|
|
44466
|
+
'function') {
|
|
44467
|
+
const normalized = grant.toConnectorConfig();
|
|
44468
|
+
if (normalized.type !== BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
44469
|
+
throw new Error(`Unsupported grant connector type: ${normalized.type}`);
|
|
43845
44470
|
}
|
|
43846
|
-
|
|
44471
|
+
return this._buildConnectorConfigForSystem(systemId, normalized);
|
|
43847
44472
|
}
|
|
43848
|
-
|
|
43849
|
-
|
|
44473
|
+
throw new Error(`Unsupported grant type: ${grant.type}`);
|
|
44474
|
+
}
|
|
44475
|
+
_buildConnectorConfigForSystem(systemId, baseConfig) {
|
|
44476
|
+
const localNodeId = this._requireLocalNodeId();
|
|
44477
|
+
const targetSystemId = this._normalizeNodeId(systemId);
|
|
44478
|
+
if (!targetSystemId) {
|
|
44479
|
+
throw new Error('BroadcastChannelListener requires a valid system id');
|
|
44480
|
+
}
|
|
44481
|
+
const candidate = baseConfig ?? null;
|
|
44482
|
+
const channelCandidate = candidate && 'channelName' in candidate
|
|
44483
|
+
? candidate.channelName
|
|
44484
|
+
: undefined;
|
|
44485
|
+
const inboxCandidate = candidate && 'inboxCapacity' in candidate
|
|
44486
|
+
? candidate.inboxCapacity
|
|
44487
|
+
: undefined;
|
|
44488
|
+
const initialWindowCandidate = candidate && 'initialWindow' in candidate
|
|
44489
|
+
? candidate.initialWindow
|
|
44490
|
+
: undefined;
|
|
44491
|
+
const passiveCandidate = candidate && 'passive' in candidate
|
|
44492
|
+
? candidate.passive
|
|
44493
|
+
: undefined;
|
|
44494
|
+
const targetCandidate = candidate && 'initialTargetNodeId' in candidate
|
|
44495
|
+
? candidate.initialTargetNodeId
|
|
44496
|
+
: undefined;
|
|
44497
|
+
const channelName = typeof channelCandidate === 'string' && channelCandidate.trim().length > 0
|
|
44498
|
+
? channelCandidate.trim()
|
|
44499
|
+
: this._channelName;
|
|
44500
|
+
const inboxCapacity = typeof inboxCandidate === 'number' &&
|
|
44501
|
+
Number.isFinite(inboxCandidate) &&
|
|
44502
|
+
inboxCandidate > 0
|
|
44503
|
+
? Math.floor(inboxCandidate)
|
|
44504
|
+
: this._inboxCapacity;
|
|
44505
|
+
const initialWindow = typeof initialWindowCandidate === 'number' &&
|
|
44506
|
+
Number.isFinite(initialWindowCandidate) &&
|
|
44507
|
+
initialWindowCandidate > 0
|
|
44508
|
+
? Math.floor(initialWindowCandidate)
|
|
44509
|
+
: undefined;
|
|
44510
|
+
const initialTargetNodeId = this._normalizeNodeId(targetCandidate) ?? targetSystemId;
|
|
44511
|
+
return {
|
|
43850
44512
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
43851
|
-
channelName
|
|
43852
|
-
inboxCapacity
|
|
44513
|
+
channelName,
|
|
44514
|
+
inboxCapacity,
|
|
44515
|
+
passive: typeof passiveCandidate === 'boolean' ? passiveCandidate : true,
|
|
44516
|
+
initialWindow,
|
|
44517
|
+
localNodeId,
|
|
44518
|
+
initialTargetNodeId,
|
|
43853
44519
|
};
|
|
43854
|
-
|
|
43855
|
-
|
|
43856
|
-
|
|
44520
|
+
}
|
|
44521
|
+
_requireLocalNodeId() {
|
|
44522
|
+
if (!this._routingNode) {
|
|
44523
|
+
throw new Error('BroadcastChannelListener requires routing node context');
|
|
43857
44524
|
}
|
|
43858
|
-
const
|
|
43859
|
-
if (
|
|
43860
|
-
|
|
43861
|
-
inboxCandidate > 0) {
|
|
43862
|
-
config.inboxCapacity = Math.floor(inboxCandidate);
|
|
44525
|
+
const normalized = this._normalizeNodeId(this._routingNode.id);
|
|
44526
|
+
if (!normalized) {
|
|
44527
|
+
throw new Error('BroadcastChannelListener requires routing node with a stable identifier');
|
|
43863
44528
|
}
|
|
43864
|
-
return
|
|
44529
|
+
return normalized;
|
|
44530
|
+
}
|
|
44531
|
+
_normalizeNodeId(value) {
|
|
44532
|
+
if (typeof value !== 'string') {
|
|
44533
|
+
return null;
|
|
44534
|
+
}
|
|
44535
|
+
const trimmed = value.trim();
|
|
44536
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
43865
44537
|
}
|
|
43866
44538
|
_monitorConnectorLifecycle(senderId, systemId, connector) {
|
|
43867
44539
|
const maybeClosable = connector;
|