@naylence/runtime 0.3.5-test.953 → 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.
- package/dist/browser/index.cjs +133 -530
- package/dist/browser/index.mjs +133 -530
- package/dist/cjs/naylence/fame/channel/flow-controller.js +38 -1
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector-factory.js +2 -14
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +51 -109
- package/dist/cjs/naylence/fame/connector/broadcast-channel-listener.js +10 -76
- package/dist/cjs/naylence/fame/connector/inpage-connector-factory.js +0 -12
- package/dist/cjs/naylence/fame/connector/inpage-connector.js +1 -105
- package/dist/cjs/naylence/fame/connector/inpage-listener.js +2 -49
- package/dist/cjs/naylence/fame/grants/broadcast-channel-connection-grant.js +12 -23
- package/dist/cjs/naylence/fame/grants/inpage-connection-grant.js +0 -28
- package/dist/cjs/naylence/fame/node/admission/default-node-attach-client.js +0 -14
- package/dist/cjs/naylence/fame/node/upstream-session-manager.js +0 -6
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/channel/flow-controller.js +38 -1
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector-factory.js +2 -14
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +51 -109
- package/dist/esm/naylence/fame/connector/broadcast-channel-listener.js +10 -76
- package/dist/esm/naylence/fame/connector/inpage-connector-factory.js +0 -12
- package/dist/esm/naylence/fame/connector/inpage-connector.js +1 -105
- package/dist/esm/naylence/fame/connector/inpage-listener.js +2 -49
- package/dist/esm/naylence/fame/grants/broadcast-channel-connection-grant.js +12 -23
- package/dist/esm/naylence/fame/grants/inpage-connection-grant.js +0 -28
- package/dist/esm/naylence/fame/node/admission/default-node-attach-client.js +0 -14
- package/dist/esm/naylence/fame/node/upstream-session-manager.js +0 -6
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +133 -530
- package/dist/node/index.mjs +133 -530
- package/dist/node/node.cjs +133 -546
- package/dist/node/node.mjs +133 -546
- package/dist/types/naylence/fame/connector/broadcast-channel-connector-factory.d.ts +0 -2
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +4 -9
- package/dist/types/naylence/fame/connector/inpage-connector-factory.d.ts +0 -2
- package/dist/types/naylence/fame/connector/inpage-connector.d.ts +0 -9
- package/dist/types/naylence/fame/connector/inpage-listener.d.ts +0 -1
- package/dist/types/naylence/fame/grants/broadcast-channel-connection-grant.d.ts +3 -6
- package/dist/types/naylence/fame/grants/inpage-connection-grant.d.ts +0 -8
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/dist/cjs/naylence/fame/connector/transport-frame.js +0 -100
- package/dist/esm/naylence/fame/connector/transport-frame.js +0 -93
- package/dist/types/naylence/fame/connector/transport-frame.d.ts +0 -56
package/dist/node/node.mjs
CHANGED
|
@@ -724,7 +724,7 @@ class TaskCancelledError extends Error {
|
|
|
724
724
|
* Provides functionality similar to Python's asyncio TaskSpawner with proper
|
|
725
725
|
* error handling, cancellation, and graceful shutdown capabilities.
|
|
726
726
|
*/
|
|
727
|
-
const logger$
|
|
727
|
+
const logger$1h = getLogger('naylence.fame.util.task_spawner');
|
|
728
728
|
function firstDefined(source, keys) {
|
|
729
729
|
for (const key of keys) {
|
|
730
730
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
@@ -885,7 +885,7 @@ class TaskSpawner {
|
|
|
885
885
|
const taskId = `task-${++this._taskCounter}`;
|
|
886
886
|
const taskName = normalizedOptions.name || `unnamed-${taskId}`;
|
|
887
887
|
const timeout = normalizedOptions.timeout ?? this._config.defaultTimeout;
|
|
888
|
-
logger$
|
|
888
|
+
logger$1h.debug('starting_background_task', {
|
|
889
889
|
task_name: taskName,
|
|
890
890
|
task_id: taskId,
|
|
891
891
|
});
|
|
@@ -902,7 +902,7 @@ class TaskSpawner {
|
|
|
902
902
|
task.promise
|
|
903
903
|
.then(() => {
|
|
904
904
|
if (!this._suppressCompletionLogging) {
|
|
905
|
-
logger$
|
|
905
|
+
logger$1h.debug('task_completed_successfully', {
|
|
906
906
|
task_name: taskName,
|
|
907
907
|
task_id: taskId,
|
|
908
908
|
duration_ms: Date.now() - task.startTime,
|
|
@@ -956,7 +956,7 @@ class TaskSpawner {
|
|
|
956
956
|
error.name === 'AbortError' ||
|
|
957
957
|
error.message === 'Task cancelled' ||
|
|
958
958
|
error.message === 'Aborted') {
|
|
959
|
-
logger$
|
|
959
|
+
logger$1h.debug('task_cancelled', {
|
|
960
960
|
task_name: taskName,
|
|
961
961
|
note: 'Task cancelled as requested',
|
|
962
962
|
});
|
|
@@ -964,7 +964,7 @@ class TaskSpawner {
|
|
|
964
964
|
}
|
|
965
965
|
// Handle timeout
|
|
966
966
|
if (error instanceof TaskTimeoutError) {
|
|
967
|
-
logger$
|
|
967
|
+
logger$1h.warning('task_timed_out', {
|
|
968
968
|
task_name: taskName,
|
|
969
969
|
error: error.message,
|
|
970
970
|
});
|
|
@@ -976,7 +976,7 @@ class TaskSpawner {
|
|
|
976
976
|
// Handle known WebSocket shutdown race condition (similar to Python version)
|
|
977
977
|
if (error.message.includes("await wasn't used with future") ||
|
|
978
978
|
error.message.includes('WebSocket closed during receive')) {
|
|
979
|
-
logger$
|
|
979
|
+
logger$1h.debug('task_shutdown_race_condition_handled', {
|
|
980
980
|
task_name: taskName,
|
|
981
981
|
note: 'Normal WebSocket close timing during shutdown - not an error',
|
|
982
982
|
});
|
|
@@ -986,7 +986,7 @@ class TaskSpawner {
|
|
|
986
986
|
if (error.name === 'FameTransportClose' ||
|
|
987
987
|
error.message.includes('normal closure') ||
|
|
988
988
|
error.message.includes('Connection closed')) {
|
|
989
|
-
logger$
|
|
989
|
+
logger$1h.debug('task_shutdown_completed_normally', {
|
|
990
990
|
task_name: taskName,
|
|
991
991
|
note: 'Task closed normally during shutdown',
|
|
992
992
|
});
|
|
@@ -999,14 +999,14 @@ class TaskSpawner {
|
|
|
999
999
|
// Log retriable errors as warnings (they'll be retried by upstream logic)
|
|
1000
1000
|
// Log non-retriable errors as errors (fatal failures)
|
|
1001
1001
|
if (isRetriableError) {
|
|
1002
|
-
logger$
|
|
1002
|
+
logger$1h.warning('background_task_failed', {
|
|
1003
1003
|
task_name: taskName,
|
|
1004
1004
|
error: error.message,
|
|
1005
1005
|
retriable: true,
|
|
1006
1006
|
});
|
|
1007
1007
|
}
|
|
1008
1008
|
else {
|
|
1009
|
-
logger$
|
|
1009
|
+
logger$1h.error('background_task_failed', {
|
|
1010
1010
|
task_name: taskName,
|
|
1011
1011
|
error: error.message,
|
|
1012
1012
|
stack: error.stack,
|
|
@@ -1025,11 +1025,11 @@ class TaskSpawner {
|
|
|
1025
1025
|
async shutdownTasks(options = {}) {
|
|
1026
1026
|
const { gracePeriod, cancelHanging, joinTimeout } = normalizeShutdownOptions(options);
|
|
1027
1027
|
if (this._tasks.size === 0) {
|
|
1028
|
-
logger$
|
|
1028
|
+
logger$1h.debug('shutdown_tasks_no_tasks_to_shutdown');
|
|
1029
1029
|
return;
|
|
1030
1030
|
}
|
|
1031
1031
|
this._suppressCompletionLogging = true;
|
|
1032
|
-
logger$
|
|
1032
|
+
logger$1h.debug('shutting_down_tasks', {
|
|
1033
1033
|
task_count: this._tasks.size,
|
|
1034
1034
|
task_names: Array.from(this._tasks.values()).map((t) => t.name),
|
|
1035
1035
|
grace_period_ms: gracePeriod,
|
|
@@ -1044,7 +1044,7 @@ class TaskSpawner {
|
|
|
1044
1044
|
if (cancelHanging) {
|
|
1045
1045
|
const stillRunning = tasks.filter((task) => task.getState() === TaskState.RUNNING && !completed.has(task));
|
|
1046
1046
|
if (stillRunning.length > 0) {
|
|
1047
|
-
logger$
|
|
1047
|
+
logger$1h.debug('tasks_did_not_complete_within_grace_period', {
|
|
1048
1048
|
hanging_count: stillRunning.length,
|
|
1049
1049
|
});
|
|
1050
1050
|
// Wait for them to finish with individual timeouts
|
|
@@ -1054,7 +1054,7 @@ class TaskSpawner {
|
|
|
1054
1054
|
}
|
|
1055
1055
|
catch (error) {
|
|
1056
1056
|
if (error instanceof TaskTimeoutError) {
|
|
1057
|
-
logger$
|
|
1057
|
+
logger$1h.warning('task_did_not_shutdown', {
|
|
1058
1058
|
task_name: task.name || task.id,
|
|
1059
1059
|
join_timeout_ms: joinTimeout,
|
|
1060
1060
|
});
|
|
@@ -1065,7 +1065,7 @@ class TaskSpawner {
|
|
|
1065
1065
|
}
|
|
1066
1066
|
else if (!(error instanceof TaskCancelledError)) {
|
|
1067
1067
|
/* istanbul ignore next - unreachable defensive branch */
|
|
1068
|
-
logger$
|
|
1068
|
+
logger$1h.error('task_raised_during_cancellation', {
|
|
1069
1069
|
task_name: task.name || task.id,
|
|
1070
1070
|
error: error instanceof Error ? error.message : String(error),
|
|
1071
1071
|
});
|
|
@@ -1184,6 +1184,7 @@ class TaskSpawner {
|
|
|
1184
1184
|
* condition/promise and ensure at most one notifier coroutine exists for a
|
|
1185
1185
|
* flow at any time.
|
|
1186
1186
|
*/
|
|
1187
|
+
const logger$1g = getLogger('naylence.fame.flow.flow_controller');
|
|
1187
1188
|
/**
|
|
1188
1189
|
* Simple condition variable implementation for TypeScript/Node.js
|
|
1189
1190
|
* Similar to Python's asyncio.Condition
|
|
@@ -1309,8 +1310,17 @@ class FlowController {
|
|
|
1309
1310
|
// clamp into [0, initialWindow]
|
|
1310
1311
|
const newBalance = Math.max(0, Math.min(this.initialWindow, prev + delta));
|
|
1311
1312
|
this.credits.set(flowId, newBalance);
|
|
1313
|
+
const crossedZero = prev <= 0 && newBalance > 0;
|
|
1314
|
+
logger$1g.debug('flow_controller_add_credits', {
|
|
1315
|
+
flow_id: flowId,
|
|
1316
|
+
delta,
|
|
1317
|
+
prev_balance: prev,
|
|
1318
|
+
new_balance: newBalance,
|
|
1319
|
+
initial_window: this.initialWindow,
|
|
1320
|
+
crossed_zero: crossedZero,
|
|
1321
|
+
});
|
|
1312
1322
|
// wake waiters only if we crossed the zero boundary
|
|
1313
|
-
if (
|
|
1323
|
+
if (crossedZero) {
|
|
1314
1324
|
this.wakeWaiters(flowId);
|
|
1315
1325
|
}
|
|
1316
1326
|
return newBalance;
|
|
@@ -1321,11 +1331,27 @@ class FlowController {
|
|
|
1321
1331
|
async acquire(flowId) {
|
|
1322
1332
|
this.ensureFlow(flowId);
|
|
1323
1333
|
const condition = this.conditions.get(flowId);
|
|
1334
|
+
logger$1g.debug('flow_controller_acquire_attempt', {
|
|
1335
|
+
flow_id: flowId,
|
|
1336
|
+
current_balance: this.credits.get(flowId),
|
|
1337
|
+
});
|
|
1324
1338
|
while (this.credits.get(flowId) <= 0) {
|
|
1339
|
+
logger$1g.debug('flow_controller_waiting_for_credit', {
|
|
1340
|
+
flow_id: flowId,
|
|
1341
|
+
});
|
|
1325
1342
|
await condition.wait();
|
|
1343
|
+
logger$1g.debug('flow_controller_woke_with_credit', {
|
|
1344
|
+
flow_id: flowId,
|
|
1345
|
+
balance_after_wake: this.credits.get(flowId),
|
|
1346
|
+
});
|
|
1326
1347
|
}
|
|
1327
1348
|
const current = this.credits.get(flowId);
|
|
1328
1349
|
this.credits.set(flowId, current - 1);
|
|
1350
|
+
logger$1g.debug('flow_controller_credit_consumed', {
|
|
1351
|
+
flow_id: flowId,
|
|
1352
|
+
prev_balance: current,
|
|
1353
|
+
remaining_balance: current - 1,
|
|
1354
|
+
});
|
|
1329
1355
|
}
|
|
1330
1356
|
/**
|
|
1331
1357
|
* Consume *credits* immediately (non-blocking).
|
|
@@ -1345,6 +1371,12 @@ class FlowController {
|
|
|
1345
1371
|
const current = this.credits.get(flowId);
|
|
1346
1372
|
const remaining = Math.max(current - credits, 0);
|
|
1347
1373
|
this.credits.set(flowId, remaining);
|
|
1374
|
+
logger$1g.debug('flow_controller_consume', {
|
|
1375
|
+
flow_id: flowId,
|
|
1376
|
+
requested: credits,
|
|
1377
|
+
prev_balance: current,
|
|
1378
|
+
remaining_balance: remaining,
|
|
1379
|
+
});
|
|
1348
1380
|
return remaining;
|
|
1349
1381
|
}
|
|
1350
1382
|
/**
|
|
@@ -1365,6 +1397,10 @@ class FlowController {
|
|
|
1365
1397
|
this.windowIds.delete(flowId);
|
|
1366
1398
|
this.credits.set(flowId, this.initialWindow);
|
|
1367
1399
|
this.wakeWaiters(flowId);
|
|
1400
|
+
logger$1g.debug('flow_controller_flow_reset', {
|
|
1401
|
+
flow_id: flowId,
|
|
1402
|
+
reset_balance: this.initialWindow,
|
|
1403
|
+
});
|
|
1368
1404
|
}
|
|
1369
1405
|
/**
|
|
1370
1406
|
* Return `[windowId, flags]` for the next outbound envelope.
|
|
@@ -5477,12 +5513,12 @@ for (const [name, config] of Object.entries(SQLITE_PROFILES)) {
|
|
|
5477
5513
|
}
|
|
5478
5514
|
|
|
5479
5515
|
// This file is auto-generated during build - do not edit manually
|
|
5480
|
-
// Generated from package.json version: 0.3.5-test.
|
|
5516
|
+
// Generated from package.json version: 0.3.5-test.955
|
|
5481
5517
|
/**
|
|
5482
5518
|
* The package version, injected at build time.
|
|
5483
5519
|
* @internal
|
|
5484
5520
|
*/
|
|
5485
|
-
const VERSION = '0.3.5-test.
|
|
5521
|
+
const VERSION = '0.3.5-test.955';
|
|
5486
5522
|
|
|
5487
5523
|
/**
|
|
5488
5524
|
* Fame errors module - Fame protocol specific error classes
|
|
@@ -11470,100 +11506,6 @@ class BoundedAsyncQueue {
|
|
|
11470
11506
|
}
|
|
11471
11507
|
}
|
|
11472
11508
|
|
|
11473
|
-
/**
|
|
11474
|
-
* Transport frame layer for multiplexing logical links on physical channels.
|
|
11475
|
-
*
|
|
11476
|
-
* This lightweight framing layer wraps raw FAME payloads to enable multiple
|
|
11477
|
-
* logical connections over a single physical channel (BroadcastChannel or InPage bus).
|
|
11478
|
-
*
|
|
11479
|
-
* The transport frame does NOT modify FAME envelopes - it only wraps the raw
|
|
11480
|
-
* Uint8Array payload at the connector level.
|
|
11481
|
-
*/
|
|
11482
|
-
/**
|
|
11483
|
-
* Transport frame version for future compatibility
|
|
11484
|
-
*/
|
|
11485
|
-
const TRANSPORT_FRAME_VERSION = 1;
|
|
11486
|
-
/**
|
|
11487
|
-
* Wrap a raw payload in a transport frame
|
|
11488
|
-
*
|
|
11489
|
-
* @param payload - Raw FAME envelope bytes
|
|
11490
|
-
* @param srcNodeId - Local node ID (this connector)
|
|
11491
|
-
* @param dstNodeId - Remote node ID (target connector)
|
|
11492
|
-
* @returns Transport frame ready for transmission
|
|
11493
|
-
*/
|
|
11494
|
-
function wrapTransportFrame(payload, srcNodeId, dstNodeId) {
|
|
11495
|
-
return {
|
|
11496
|
-
v: TRANSPORT_FRAME_VERSION,
|
|
11497
|
-
src: srcNodeId,
|
|
11498
|
-
dst: dstNodeId,
|
|
11499
|
-
payload,
|
|
11500
|
-
};
|
|
11501
|
-
}
|
|
11502
|
-
/**
|
|
11503
|
-
* Serialize a transport frame for transmission over the bus
|
|
11504
|
-
*
|
|
11505
|
-
* @param frame - Transport frame to serialize
|
|
11506
|
-
* @returns Serialized frame data ready for postMessage/dispatchEvent
|
|
11507
|
-
*/
|
|
11508
|
-
function serializeTransportFrame(frame) {
|
|
11509
|
-
// Convert Uint8Array to regular array for JSON serialization
|
|
11510
|
-
const serializable = {
|
|
11511
|
-
v: frame.v,
|
|
11512
|
-
src: frame.src,
|
|
11513
|
-
dst: frame.dst,
|
|
11514
|
-
payload: Array.from(frame.payload),
|
|
11515
|
-
};
|
|
11516
|
-
return serializable;
|
|
11517
|
-
}
|
|
11518
|
-
/**
|
|
11519
|
-
* Unwrap a transport frame (pure deserializer - no filtering)
|
|
11520
|
-
*
|
|
11521
|
-
* @param raw - Raw data from the bus
|
|
11522
|
-
* @returns Unwrapped frame with payload as Uint8Array, or null if invalid structure
|
|
11523
|
-
*/
|
|
11524
|
-
function unwrapTransportFrame(raw) {
|
|
11525
|
-
// Validate basic structure
|
|
11526
|
-
if (!raw || typeof raw !== 'object') {
|
|
11527
|
-
return null;
|
|
11528
|
-
}
|
|
11529
|
-
const frame = raw;
|
|
11530
|
-
// Check version
|
|
11531
|
-
if (frame.v !== TRANSPORT_FRAME_VERSION) {
|
|
11532
|
-
return null;
|
|
11533
|
-
}
|
|
11534
|
-
// Check src and dst
|
|
11535
|
-
if (typeof frame.src !== 'string' || typeof frame.dst !== 'string') {
|
|
11536
|
-
return null;
|
|
11537
|
-
}
|
|
11538
|
-
// Extract payload
|
|
11539
|
-
if (!frame.payload || !Array.isArray(frame.payload)) {
|
|
11540
|
-
return null;
|
|
11541
|
-
}
|
|
11542
|
-
// Convert array back to Uint8Array and return full frame
|
|
11543
|
-
return {
|
|
11544
|
-
v: frame.v,
|
|
11545
|
-
src: frame.src,
|
|
11546
|
-
dst: frame.dst,
|
|
11547
|
-
payload: Uint8Array.from(frame.payload),
|
|
11548
|
-
};
|
|
11549
|
-
}
|
|
11550
|
-
/**
|
|
11551
|
-
* Check if raw data looks like a transport frame
|
|
11552
|
-
*
|
|
11553
|
-
* @param raw - Raw data from the bus
|
|
11554
|
-
* @returns True if this appears to be a transport frame
|
|
11555
|
-
*/
|
|
11556
|
-
function isTransportFrame(raw) {
|
|
11557
|
-
if (!raw || typeof raw !== 'object') {
|
|
11558
|
-
return false;
|
|
11559
|
-
}
|
|
11560
|
-
const frame = raw;
|
|
11561
|
-
return (typeof frame.v === 'number' &&
|
|
11562
|
-
typeof frame.src === 'string' &&
|
|
11563
|
-
typeof frame.dst === 'string' &&
|
|
11564
|
-
Array.isArray(frame.payload));
|
|
11565
|
-
}
|
|
11566
|
-
|
|
11567
11509
|
const logger$10 = getLogger('naylence.fame.connector.broadcast_channel_connector');
|
|
11568
11510
|
const BROADCAST_CHANNEL_CONNECTOR_TYPE$1 = 'broadcast-channel-connector';
|
|
11569
11511
|
const DEFAULT_CHANNEL$7 = 'naylence-fabric';
|
|
@@ -11627,22 +11569,12 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11627
11569
|
? Math.floor(config.inboxCapacity)
|
|
11628
11570
|
: DEFAULT_INBOX_CAPACITY$7;
|
|
11629
11571
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
11572
|
+
this.inboxCapacity = preferredCapacity;
|
|
11630
11573
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
11631
11574
|
this.channel = new BroadcastChannel(this.channelName);
|
|
11632
|
-
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
11633
|
-
this.localNodeId =
|
|
11634
|
-
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
11635
|
-
? config.localNodeId.trim()
|
|
11636
|
-
: this.connectorId;
|
|
11637
|
-
this.remoteNodeId =
|
|
11638
|
-
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
11639
|
-
? config.remoteNodeId.trim()
|
|
11640
|
-
: '*'; // Accept from any remote if not specified
|
|
11641
11575
|
logger$10.debug('broadcast_channel_connector_created', {
|
|
11642
11576
|
channel: this.channelName,
|
|
11643
11577
|
connector_id: this.connectorId,
|
|
11644
|
-
local_node_id: this.localNodeId,
|
|
11645
|
-
remote_node_id: this.remoteNodeId,
|
|
11646
11578
|
inbox_capacity: preferredCapacity,
|
|
11647
11579
|
timestamp: new Date().toISOString(),
|
|
11648
11580
|
});
|
|
@@ -11675,67 +11607,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11675
11607
|
if (busMessage.senderId === this.connectorId) {
|
|
11676
11608
|
return;
|
|
11677
11609
|
}
|
|
11678
|
-
// Try to unwrap as transport frame
|
|
11679
|
-
const frame = unwrapTransportFrame(busMessage.payload);
|
|
11680
|
-
if (frame) {
|
|
11681
|
-
// Apply connector's filtering policy: strict dst check, src accepts wildcard
|
|
11682
|
-
const srcMatches = this.remoteNodeId === '*' || frame.src === this.remoteNodeId;
|
|
11683
|
-
const dstMatches = frame.dst === this.localNodeId;
|
|
11684
|
-
if (dstMatches && srcMatches) {
|
|
11685
|
-
// Successfully received and filtered transport frame
|
|
11686
|
-
logger$10.debug('broadcast_channel_transport_frame_received', {
|
|
11687
|
-
channel: this.channelName,
|
|
11688
|
-
sender_id: busMessage.senderId,
|
|
11689
|
-
connector_id: this.connectorId,
|
|
11690
|
-
local_node_id: this.localNodeId,
|
|
11691
|
-
remote_node_id: this.remoteNodeId,
|
|
11692
|
-
frame_src: frame.src,
|
|
11693
|
-
frame_dst: frame.dst,
|
|
11694
|
-
payload_length: frame.payload.byteLength,
|
|
11695
|
-
});
|
|
11696
|
-
const unwrapped = frame.payload;
|
|
11697
|
-
if (this._shouldSkipDuplicateAck(busMessage.senderId, unwrapped)) {
|
|
11698
|
-
return;
|
|
11699
|
-
}
|
|
11700
|
-
try {
|
|
11701
|
-
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
11702
|
-
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
11703
|
-
if (accepted) {
|
|
11704
|
-
return;
|
|
11705
|
-
}
|
|
11706
|
-
}
|
|
11707
|
-
this.inbox.enqueue(unwrapped);
|
|
11708
|
-
}
|
|
11709
|
-
catch (error) {
|
|
11710
|
-
if (error instanceof QueueFullError) {
|
|
11711
|
-
logger$10.warning('broadcast_channel_receive_queue_full', {
|
|
11712
|
-
channel: this.channelName,
|
|
11713
|
-
});
|
|
11714
|
-
}
|
|
11715
|
-
else {
|
|
11716
|
-
logger$10.error('broadcast_channel_receive_error', {
|
|
11717
|
-
channel: this.channelName,
|
|
11718
|
-
error: error instanceof Error ? error.message : String(error),
|
|
11719
|
-
});
|
|
11720
|
-
}
|
|
11721
|
-
}
|
|
11722
|
-
return;
|
|
11723
|
-
}
|
|
11724
|
-
else {
|
|
11725
|
-
// Frame filtered out by addressing rules
|
|
11726
|
-
logger$10.debug('broadcast_channel_transport_frame_filtered', {
|
|
11727
|
-
channel: this.channelName,
|
|
11728
|
-
connector_id: this.connectorId,
|
|
11729
|
-
local_node_id: this.localNodeId,
|
|
11730
|
-
remote_node_id: this.remoteNodeId,
|
|
11731
|
-
frame_src: frame.src,
|
|
11732
|
-
frame_dst: frame.dst,
|
|
11733
|
-
reason: !dstMatches ? 'wrong_destination' : 'wrong_source',
|
|
11734
|
-
});
|
|
11735
|
-
return;
|
|
11736
|
-
}
|
|
11737
|
-
}
|
|
11738
|
-
// Fall back to legacy format (no transport frame)
|
|
11739
11610
|
const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
|
|
11740
11611
|
if (!payload) {
|
|
11741
11612
|
logger$10.debug('broadcast_channel_payload_rejected', {
|
|
@@ -11758,15 +11629,27 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11758
11629
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
11759
11630
|
const accepted = this.inbox.tryEnqueue(payload);
|
|
11760
11631
|
if (accepted) {
|
|
11632
|
+
this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
|
|
11633
|
+
source: 'listener',
|
|
11634
|
+
enqueue_strategy: 'try',
|
|
11635
|
+
payload_length: payload.byteLength,
|
|
11636
|
+
});
|
|
11761
11637
|
return;
|
|
11762
11638
|
}
|
|
11763
11639
|
}
|
|
11764
11640
|
this.inbox.enqueue(payload);
|
|
11641
|
+
this.logInboxSnapshot('broadcast_channel_inbox_enqueued', {
|
|
11642
|
+
source: 'listener',
|
|
11643
|
+
enqueue_strategy: 'enqueue',
|
|
11644
|
+
payload_length: payload.byteLength,
|
|
11645
|
+
});
|
|
11765
11646
|
}
|
|
11766
11647
|
catch (error) {
|
|
11767
11648
|
if (error instanceof QueueFullError) {
|
|
11768
11649
|
logger$10.warning('broadcast_channel_receive_queue_full', {
|
|
11769
11650
|
channel: this.channelName,
|
|
11651
|
+
inbox_capacity: this.inboxCapacity,
|
|
11652
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
11770
11653
|
});
|
|
11771
11654
|
}
|
|
11772
11655
|
else {
|
|
@@ -11850,15 +11733,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11850
11733
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
11851
11734
|
const accepted = this.inbox.tryEnqueue(item);
|
|
11852
11735
|
if (accepted) {
|
|
11736
|
+
this.logInboxSnapshot('broadcast_channel_push_enqueued', {
|
|
11737
|
+
enqueue_strategy: 'try',
|
|
11738
|
+
item_type: this._describeInboxItem(item),
|
|
11739
|
+
});
|
|
11853
11740
|
return;
|
|
11854
11741
|
}
|
|
11855
11742
|
}
|
|
11856
11743
|
this.inbox.enqueue(item);
|
|
11744
|
+
this.logInboxSnapshot('broadcast_channel_push_enqueued', {
|
|
11745
|
+
enqueue_strategy: 'enqueue',
|
|
11746
|
+
item_type: this._describeInboxItem(item),
|
|
11747
|
+
});
|
|
11857
11748
|
}
|
|
11858
11749
|
catch (error) {
|
|
11859
11750
|
if (error instanceof QueueFullError) {
|
|
11860
11751
|
logger$10.warning('broadcast_channel_push_queue_full', {
|
|
11861
11752
|
channel: this.channelName,
|
|
11753
|
+
inbox_capacity: this.inboxCapacity,
|
|
11754
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
11862
11755
|
});
|
|
11863
11756
|
throw error;
|
|
11864
11757
|
}
|
|
@@ -11874,30 +11767,18 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11874
11767
|
logger$10.debug('broadcast_channel_message_sending', {
|
|
11875
11768
|
channel: this.channelName,
|
|
11876
11769
|
sender_id: this.connectorId,
|
|
11877
|
-
|
|
11878
|
-
remote_node_id: this.remoteNodeId,
|
|
11879
|
-
});
|
|
11880
|
-
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
11881
|
-
// (not using default values). This ensures backwards compatibility.
|
|
11882
|
-
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
11883
|
-
this.remoteNodeId !== '*';
|
|
11884
|
-
let payload;
|
|
11885
|
-
if (useTransportFrame) {
|
|
11886
|
-
// Wrap payload in transport frame
|
|
11887
|
-
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
11888
|
-
payload = serializeTransportFrame(frame);
|
|
11889
|
-
}
|
|
11890
|
-
else {
|
|
11891
|
-
// Legacy format: send raw payload
|
|
11892
|
-
payload = data;
|
|
11893
|
-
}
|
|
11770
|
+
});
|
|
11894
11771
|
this.channel.postMessage({
|
|
11895
11772
|
senderId: this.connectorId,
|
|
11896
|
-
payload,
|
|
11773
|
+
payload: data,
|
|
11897
11774
|
});
|
|
11898
11775
|
}
|
|
11899
11776
|
async _transportReceive() {
|
|
11900
|
-
|
|
11777
|
+
const item = await this.inbox.dequeue();
|
|
11778
|
+
this.logInboxSnapshot('broadcast_channel_inbox_dequeued', {
|
|
11779
|
+
item_type: this._describeInboxItem(item),
|
|
11780
|
+
});
|
|
11781
|
+
return item;
|
|
11901
11782
|
}
|
|
11902
11783
|
async _transportClose(code, reason) {
|
|
11903
11784
|
logger$10.debug('broadcast_channel_transport_closing', {
|
|
@@ -11951,6 +11832,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11951
11832
|
}
|
|
11952
11833
|
return rawOrEnvelope;
|
|
11953
11834
|
}
|
|
11835
|
+
_describeInboxItem(item) {
|
|
11836
|
+
if (item instanceof Uint8Array) {
|
|
11837
|
+
return 'bytes';
|
|
11838
|
+
}
|
|
11839
|
+
if (item.envelope) {
|
|
11840
|
+
return 'channel_message';
|
|
11841
|
+
}
|
|
11842
|
+
if (item.frame) {
|
|
11843
|
+
return 'envelope';
|
|
11844
|
+
}
|
|
11845
|
+
return 'unknown';
|
|
11846
|
+
}
|
|
11847
|
+
logInboxSnapshot(event, extra = {}) {
|
|
11848
|
+
logger$10.debug(event, {
|
|
11849
|
+
channel: this.channelName,
|
|
11850
|
+
connector_id: this.connectorId,
|
|
11851
|
+
connector_state: this.state,
|
|
11852
|
+
inbox_capacity: this.inboxCapacity,
|
|
11853
|
+
inbox_remaining_capacity: this.inbox.remainingCapacity,
|
|
11854
|
+
...extra,
|
|
11855
|
+
});
|
|
11856
|
+
}
|
|
11954
11857
|
_shouldSkipDuplicateAck(senderId, payload) {
|
|
11955
11858
|
const dedupKey = this._extractAckDedupKey(payload);
|
|
11956
11859
|
if (!dedupKey) {
|
|
@@ -12049,24 +11952,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
12049
11952
|
});
|
|
12050
11953
|
}
|
|
12051
11954
|
}
|
|
12052
|
-
/**
|
|
12053
|
-
* Update the remote node ID after learning it from NodeAttachAck
|
|
12054
|
-
* This allows upstream connectors to switch from wildcard to specific addressing
|
|
12055
|
-
*/
|
|
12056
|
-
updateRemoteNodeId(newRemoteNodeId) {
|
|
12057
|
-
if (typeof newRemoteNodeId !== 'string' || newRemoteNodeId.trim().length === 0) {
|
|
12058
|
-
throw new Error('Invalid remote node ID');
|
|
12059
|
-
}
|
|
12060
|
-
const oldValue = this.remoteNodeId;
|
|
12061
|
-
this.remoteNodeId = newRemoteNodeId.trim();
|
|
12062
|
-
logger$10.debug('broadcast_channel_connector_remote_node_id_updated', {
|
|
12063
|
-
channel: this.channelName,
|
|
12064
|
-
connector_id: this.connectorId,
|
|
12065
|
-
local_node_id: this.localNodeId,
|
|
12066
|
-
old_remote_node_id: oldValue,
|
|
12067
|
-
new_remote_node_id: this.remoteNodeId,
|
|
12068
|
-
});
|
|
12069
|
-
}
|
|
12070
11955
|
_trimSeenAcks(now) {
|
|
12071
11956
|
while (this.seenAckOrder.length > 0) {
|
|
12072
11957
|
const candidate = this.seenAckOrder[0];
|
|
@@ -12159,12 +12044,9 @@ function isBroadcastChannelConnectionGrant(candidate) {
|
|
|
12159
12044
|
record.inboxCapacity <= 0)) {
|
|
12160
12045
|
return false;
|
|
12161
12046
|
}
|
|
12162
|
-
if (record.
|
|
12163
|
-
(
|
|
12164
|
-
|
|
12165
|
-
}
|
|
12166
|
-
if (record.remoteNodeId !== undefined &&
|
|
12167
|
-
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
12047
|
+
if (record.initialWindow !== undefined &&
|
|
12048
|
+
(!Number.isFinite(record.initialWindow) ||
|
|
12049
|
+
record.initialWindow <= 0)) {
|
|
12168
12050
|
return false;
|
|
12169
12051
|
}
|
|
12170
12052
|
return true;
|
|
@@ -12200,19 +12082,14 @@ function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
|
12200
12082
|
}
|
|
12201
12083
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
12202
12084
|
}
|
|
12203
|
-
const
|
|
12204
|
-
if (
|
|
12205
|
-
if (typeof
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
}
|
|
12210
|
-
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
12211
|
-
if (remoteNodeIdValue !== undefined) {
|
|
12212
|
-
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
12213
|
-
throw new TypeError('BroadcastChannelConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
12085
|
+
const windowValue = candidate.initialWindow ?? candidate['initial_window'];
|
|
12086
|
+
if (windowValue !== undefined) {
|
|
12087
|
+
if (typeof windowValue !== 'number' ||
|
|
12088
|
+
!Number.isFinite(windowValue) ||
|
|
12089
|
+
windowValue <= 0) {
|
|
12090
|
+
throw new TypeError('BroadcastChannelConnectionGrant "initialWindow" must be a positive number when provided');
|
|
12214
12091
|
}
|
|
12215
|
-
result.
|
|
12092
|
+
result.initialWindow = Math.floor(windowValue);
|
|
12216
12093
|
}
|
|
12217
12094
|
return result;
|
|
12218
12095
|
}
|
|
@@ -12227,11 +12104,8 @@ function broadcastChannelGrantToConnectorConfig(grant) {
|
|
|
12227
12104
|
if (normalized.inboxCapacity !== undefined) {
|
|
12228
12105
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
12229
12106
|
}
|
|
12230
|
-
if (normalized.
|
|
12231
|
-
config.
|
|
12232
|
-
}
|
|
12233
|
-
if (normalized.remoteNodeId) {
|
|
12234
|
-
config.remoteNodeId = normalized.remoteNodeId;
|
|
12107
|
+
if (normalized.initialWindow !== undefined) {
|
|
12108
|
+
config.initialWindow = normalized.initialWindow;
|
|
12235
12109
|
}
|
|
12236
12110
|
return config;
|
|
12237
12111
|
}
|
|
@@ -12523,12 +12397,6 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
12523
12397
|
cryptoProvider.prepareForAttach(welcome.frame.systemId, welcome.frame.assignedPath, welcome.frame.acceptedLogicals ?? []);
|
|
12524
12398
|
}
|
|
12525
12399
|
await this.onWelcome(welcome.frame);
|
|
12526
|
-
// Inject node ID into grant for transport frame multiplexing
|
|
12527
|
-
// This ensures localNodeId matches the node's systemId for proper frame filtering
|
|
12528
|
-
grant.localNodeId = welcome.frame.systemId;
|
|
12529
|
-
if (welcome.frame.targetSystemId) {
|
|
12530
|
-
grant.remoteNodeId = welcome.frame.targetSystemId;
|
|
12531
|
-
}
|
|
12532
12400
|
const connector = await ConnectorFactory.createConnector(grant, {
|
|
12533
12401
|
systemId: welcome.frame.systemId,
|
|
12534
12402
|
});
|
|
@@ -14485,20 +14353,6 @@ class DefaultNodeAttachClient {
|
|
|
14485
14353
|
if (!targetSystemId) {
|
|
14486
14354
|
throw new Error('Target system ID must be set in NodeAttachAckFrame on success');
|
|
14487
14355
|
}
|
|
14488
|
-
// Update connector's remote node ID if it supports it (e.g., BroadcastChannelConnector, InPageConnector)
|
|
14489
|
-
// This allows upstream connectors to switch from wildcard '*' to specific node addressing
|
|
14490
|
-
const updatableConnector = connector;
|
|
14491
|
-
if (typeof updatableConnector.updateRemoteNodeId === 'function') {
|
|
14492
|
-
try {
|
|
14493
|
-
updatableConnector.updateRemoteNodeId(targetSystemId);
|
|
14494
|
-
}
|
|
14495
|
-
catch (error) {
|
|
14496
|
-
logger$Y.debug('connector_remote_node_id_update_failed', {
|
|
14497
|
-
target_system_id: targetSystemId,
|
|
14498
|
-
error: error instanceof Error ? error.message : String(error),
|
|
14499
|
-
});
|
|
14500
|
-
}
|
|
14501
|
-
}
|
|
14502
14356
|
try {
|
|
14503
14357
|
if (this.replicaStickinessManager) {
|
|
14504
14358
|
this.replicaStickinessManager.accept(ackFrame.stickiness ?? null);
|
|
@@ -21685,20 +21539,9 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
21685
21539
|
: DEFAULT_INBOX_CAPACITY$6;
|
|
21686
21540
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
21687
21541
|
this.connectorId = InPageConnector.generateConnectorId();
|
|
21688
|
-
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
21689
|
-
this.localNodeId =
|
|
21690
|
-
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
21691
|
-
? config.localNodeId.trim()
|
|
21692
|
-
: this.connectorId;
|
|
21693
|
-
this.remoteNodeId =
|
|
21694
|
-
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
21695
|
-
? config.remoteNodeId.trim()
|
|
21696
|
-
: '*'; // Accept from any remote if not specified
|
|
21697
21542
|
logger$J.debug('inpage_connector_initialized', {
|
|
21698
21543
|
channel: this.channelName,
|
|
21699
21544
|
connector_id: this.connectorId,
|
|
21700
|
-
local_node_id: this.localNodeId,
|
|
21701
|
-
remote_node_id: this.remoteNodeId,
|
|
21702
21545
|
});
|
|
21703
21546
|
this.onMsg = (event) => {
|
|
21704
21547
|
const messageEvent = event;
|
|
@@ -21732,64 +21575,6 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
21732
21575
|
if (busMessage.senderId === this.connectorId) {
|
|
21733
21576
|
return;
|
|
21734
21577
|
}
|
|
21735
|
-
// Try to unwrap as transport frame
|
|
21736
|
-
const frame = unwrapTransportFrame(busMessage.payload);
|
|
21737
|
-
if (frame) {
|
|
21738
|
-
// Apply connector's filtering policy: strict dst check, src accepts wildcard
|
|
21739
|
-
const srcMatches = this.remoteNodeId === '*' || frame.src === this.remoteNodeId;
|
|
21740
|
-
const dstMatches = frame.dst === this.localNodeId;
|
|
21741
|
-
if (dstMatches && srcMatches) {
|
|
21742
|
-
// Successfully received and filtered transport frame
|
|
21743
|
-
logger$J.debug('inpage_transport_frame_received', {
|
|
21744
|
-
channel: this.channelName,
|
|
21745
|
-
sender_id: busMessage.senderId,
|
|
21746
|
-
connector_id: this.connectorId,
|
|
21747
|
-
local_node_id: this.localNodeId,
|
|
21748
|
-
remote_node_id: this.remoteNodeId,
|
|
21749
|
-
frame_src: frame.src,
|
|
21750
|
-
frame_dst: frame.dst,
|
|
21751
|
-
payload_length: frame.payload.byteLength,
|
|
21752
|
-
});
|
|
21753
|
-
const unwrapped = frame.payload;
|
|
21754
|
-
try {
|
|
21755
|
-
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
21756
|
-
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
21757
|
-
if (accepted) {
|
|
21758
|
-
return;
|
|
21759
|
-
}
|
|
21760
|
-
}
|
|
21761
|
-
this.inbox.enqueue(unwrapped);
|
|
21762
|
-
}
|
|
21763
|
-
catch (error) {
|
|
21764
|
-
if (error instanceof QueueFullError) {
|
|
21765
|
-
logger$J.warning('inpage_receive_queue_full', {
|
|
21766
|
-
channel: this.channelName,
|
|
21767
|
-
});
|
|
21768
|
-
}
|
|
21769
|
-
else {
|
|
21770
|
-
logger$J.error('inpage_receive_error', {
|
|
21771
|
-
channel: this.channelName,
|
|
21772
|
-
error: error instanceof Error ? error.message : String(error),
|
|
21773
|
-
});
|
|
21774
|
-
}
|
|
21775
|
-
}
|
|
21776
|
-
return;
|
|
21777
|
-
}
|
|
21778
|
-
else {
|
|
21779
|
-
// Frame filtered out by addressing rules
|
|
21780
|
-
logger$J.debug('inpage_transport_frame_filtered', {
|
|
21781
|
-
channel: this.channelName,
|
|
21782
|
-
connector_id: this.connectorId,
|
|
21783
|
-
local_node_id: this.localNodeId,
|
|
21784
|
-
remote_node_id: this.remoteNodeId,
|
|
21785
|
-
frame_src: frame.src,
|
|
21786
|
-
frame_dst: frame.dst,
|
|
21787
|
-
reason: !dstMatches ? 'wrong_destination' : 'wrong_source',
|
|
21788
|
-
});
|
|
21789
|
-
return;
|
|
21790
|
-
}
|
|
21791
|
-
}
|
|
21792
|
-
// Fall back to legacy format (no transport frame)
|
|
21793
21578
|
const payload = InPageConnector.coercePayload(busMessage.payload);
|
|
21794
21579
|
if (!payload) {
|
|
21795
21580
|
logger$J.debug('inpage_payload_rejected', {
|
|
@@ -21948,27 +21733,11 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
21948
21733
|
logger$J.debug('inpage_message_sending', {
|
|
21949
21734
|
channel: this.channelName,
|
|
21950
21735
|
sender_id: this.connectorId,
|
|
21951
|
-
|
|
21952
|
-
remote_node_id: this.remoteNodeId,
|
|
21953
|
-
});
|
|
21954
|
-
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
21955
|
-
// (not using default values). This ensures backwards compatibility.
|
|
21956
|
-
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
21957
|
-
this.remoteNodeId !== '*';
|
|
21958
|
-
let payload;
|
|
21959
|
-
if (useTransportFrame) {
|
|
21960
|
-
// Wrap payload in transport frame
|
|
21961
|
-
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
21962
|
-
payload = serializeTransportFrame(frame);
|
|
21963
|
-
}
|
|
21964
|
-
else {
|
|
21965
|
-
// Legacy format: send raw payload
|
|
21966
|
-
payload = data;
|
|
21967
|
-
}
|
|
21736
|
+
});
|
|
21968
21737
|
const event = new MessageEvent(this.channelName, {
|
|
21969
21738
|
data: {
|
|
21970
21739
|
senderId: this.connectorId,
|
|
21971
|
-
payload,
|
|
21740
|
+
payload: data,
|
|
21972
21741
|
},
|
|
21973
21742
|
});
|
|
21974
21743
|
getSharedBus$1().dispatchEvent(event);
|
|
@@ -21997,24 +21766,6 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
21997
21766
|
}
|
|
21998
21767
|
return rawOrEnvelope;
|
|
21999
21768
|
}
|
|
22000
|
-
/**
|
|
22001
|
-
* Update the remote node ID after learning it from NodeAttachAck
|
|
22002
|
-
* This allows upstream connectors to switch from wildcard to specific addressing
|
|
22003
|
-
*/
|
|
22004
|
-
updateRemoteNodeId(newRemoteNodeId) {
|
|
22005
|
-
if (typeof newRemoteNodeId !== 'string' || newRemoteNodeId.trim().length === 0) {
|
|
22006
|
-
throw new Error('Invalid remote node ID');
|
|
22007
|
-
}
|
|
22008
|
-
const oldValue = this.remoteNodeId;
|
|
22009
|
-
this.remoteNodeId = newRemoteNodeId.trim();
|
|
22010
|
-
logger$J.debug('inpage_connector_remote_node_id_updated', {
|
|
22011
|
-
channel: this.channelName,
|
|
22012
|
-
connector_id: this.connectorId,
|
|
22013
|
-
local_node_id: this.localNodeId,
|
|
22014
|
-
old_remote_node_id: oldValue,
|
|
22015
|
-
new_remote_node_id: this.remoteNodeId,
|
|
22016
|
-
});
|
|
22017
|
-
}
|
|
22018
21769
|
}
|
|
22019
21770
|
|
|
22020
21771
|
const RPC_REGISTRY = Symbol('naylence.rpc.registry');
|
|
@@ -29298,14 +29049,6 @@ function isInPageConnectionGrant(candidate) {
|
|
|
29298
29049
|
record.inboxCapacity <= 0)) {
|
|
29299
29050
|
return false;
|
|
29300
29051
|
}
|
|
29301
|
-
if (record.localNodeId !== undefined &&
|
|
29302
|
-
(typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
|
|
29303
|
-
return false;
|
|
29304
|
-
}
|
|
29305
|
-
if (record.remoteNodeId !== undefined &&
|
|
29306
|
-
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
29307
|
-
return false;
|
|
29308
|
-
}
|
|
29309
29052
|
return true;
|
|
29310
29053
|
}
|
|
29311
29054
|
function normalizeInPageConnectionGrant(candidate) {
|
|
@@ -29339,20 +29082,6 @@ function normalizeInPageConnectionGrant(candidate) {
|
|
|
29339
29082
|
}
|
|
29340
29083
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
29341
29084
|
}
|
|
29342
|
-
const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
|
|
29343
|
-
if (localNodeIdValue !== undefined) {
|
|
29344
|
-
if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
|
|
29345
|
-
throw new TypeError('InPageConnectionGrant "localNodeId" must be a non-empty string when provided');
|
|
29346
|
-
}
|
|
29347
|
-
result.localNodeId = localNodeIdValue.trim();
|
|
29348
|
-
}
|
|
29349
|
-
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
29350
|
-
if (remoteNodeIdValue !== undefined) {
|
|
29351
|
-
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
29352
|
-
throw new TypeError('InPageConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
29353
|
-
}
|
|
29354
|
-
result.remoteNodeId = remoteNodeIdValue.trim();
|
|
29355
|
-
}
|
|
29356
29085
|
return result;
|
|
29357
29086
|
}
|
|
29358
29087
|
function inPageGrantToConnectorConfig(grant) {
|
|
@@ -29366,12 +29095,6 @@ function inPageGrantToConnectorConfig(grant) {
|
|
|
29366
29095
|
if (normalized.inboxCapacity !== undefined) {
|
|
29367
29096
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
29368
29097
|
}
|
|
29369
|
-
if (normalized.localNodeId) {
|
|
29370
|
-
config.localNodeId = normalized.localNodeId;
|
|
29371
|
-
}
|
|
29372
|
-
if (normalized.remoteNodeId) {
|
|
29373
|
-
config.remoteNodeId = normalized.remoteNodeId;
|
|
29374
|
-
}
|
|
29375
29098
|
return config;
|
|
29376
29099
|
}
|
|
29377
29100
|
|
|
@@ -30639,8 +30362,6 @@ class InPageConnectorFactory extends ConnectorFactory {
|
|
|
30639
30362
|
type: INPAGE_CONNECTOR_TYPE,
|
|
30640
30363
|
channelName,
|
|
30641
30364
|
inboxCapacity,
|
|
30642
|
-
localNodeId: normalized.localNodeId,
|
|
30643
|
-
remoteNodeId: normalized.remoteNodeId,
|
|
30644
30365
|
};
|
|
30645
30366
|
const connector = new InPageConnector(connectorConfig, baseConfig);
|
|
30646
30367
|
if (options.authorization) {
|
|
@@ -30709,16 +30430,6 @@ class InPageConnectorFactory extends ConnectorFactory {
|
|
|
30709
30430
|
if (candidate.authorizationContext !== undefined) {
|
|
30710
30431
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
30711
30432
|
}
|
|
30712
|
-
// Handle localNodeId
|
|
30713
|
-
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
30714
|
-
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
30715
|
-
normalized.localNodeId = localNodeId.trim();
|
|
30716
|
-
}
|
|
30717
|
-
// Handle remoteNodeId
|
|
30718
|
-
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
30719
|
-
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
30720
|
-
normalized.remoteNodeId = remoteNodeId.trim();
|
|
30721
|
-
}
|
|
30722
30433
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$3;
|
|
30723
30434
|
normalized.inboxCapacity =
|
|
30724
30435
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$3;
|
|
@@ -30769,8 +30480,7 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
30769
30480
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE$1,
|
|
30770
30481
|
channelName: connectorConfig.channelName,
|
|
30771
30482
|
inboxCapacity: connectorConfig.inboxCapacity,
|
|
30772
|
-
|
|
30773
|
-
remoteNodeId: connectorConfig.remoteNodeId,
|
|
30483
|
+
initialWindow: connectorConfig.initialWindow,
|
|
30774
30484
|
};
|
|
30775
30485
|
}
|
|
30776
30486
|
const config = {
|
|
@@ -30795,6 +30505,7 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
30795
30505
|
purpose: 'connection',
|
|
30796
30506
|
channelName: normalizedConfig.channelName,
|
|
30797
30507
|
inboxCapacity: normalizedConfig.inboxCapacity,
|
|
30508
|
+
initialWindow: normalizedConfig.initialWindow,
|
|
30798
30509
|
});
|
|
30799
30510
|
return grant;
|
|
30800
30511
|
}
|
|
@@ -30820,8 +30531,6 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
30820
30531
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE$1,
|
|
30821
30532
|
channelName,
|
|
30822
30533
|
inboxCapacity,
|
|
30823
|
-
localNodeId: normalized.localNodeId,
|
|
30824
|
-
remoteNodeId: normalized.remoteNodeId,
|
|
30825
30534
|
};
|
|
30826
30535
|
const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
30827
30536
|
if (options.authorization) {
|
|
@@ -30883,16 +30592,6 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
30883
30592
|
if (candidate.authorizationContext !== undefined) {
|
|
30884
30593
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
30885
30594
|
}
|
|
30886
|
-
// Handle localNodeId
|
|
30887
|
-
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
30888
|
-
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
30889
|
-
normalized.localNodeId = localNodeId.trim();
|
|
30890
|
-
}
|
|
30891
|
-
// Handle remoteNodeId
|
|
30892
|
-
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
30893
|
-
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
30894
|
-
normalized.remoteNodeId = remoteNodeId.trim();
|
|
30895
|
-
}
|
|
30896
30595
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$2;
|
|
30897
30596
|
normalized.inboxCapacity =
|
|
30898
30597
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$2;
|
|
@@ -32377,7 +32076,6 @@ class InPageListener extends TransportListener {
|
|
|
32377
32076
|
this._busHandler = null;
|
|
32378
32077
|
this._senderRegistry = new Map();
|
|
32379
32078
|
this._systemToSender = new Map();
|
|
32380
|
-
this._flowIdToSender = new Map();
|
|
32381
32079
|
this._pendingAttachments = new Map();
|
|
32382
32080
|
ensureBrowserEnvironment$1();
|
|
32383
32081
|
const channelCandidate = options?.channelName;
|
|
@@ -32444,7 +32142,6 @@ class InPageListener extends TransportListener {
|
|
|
32444
32142
|
this._unregisterBusListener();
|
|
32445
32143
|
this._senderRegistry.clear();
|
|
32446
32144
|
this._systemToSender.clear();
|
|
32447
|
-
this._flowIdToSender.clear();
|
|
32448
32145
|
this._pendingAttachments.clear();
|
|
32449
32146
|
logger$o.debug('inpage_listener_stopped', {
|
|
32450
32147
|
channel: this._channelName,
|
|
@@ -32498,25 +32195,10 @@ class InPageListener extends TransportListener {
|
|
|
32498
32195
|
await this._handleAttachFrame(senderId, envelope);
|
|
32499
32196
|
return;
|
|
32500
32197
|
}
|
|
32501
|
-
|
|
32502
|
-
let entry = this._senderRegistry.get(senderId);
|
|
32503
|
-
// If not found and we have a flowId, try to route based on flow
|
|
32504
|
-
if (!entry && envelope.flowId) {
|
|
32505
|
-
const originalSenderId = this._flowIdToSender.get(envelope.flowId);
|
|
32506
|
-
if (originalSenderId) {
|
|
32507
|
-
entry = this._senderRegistry.get(originalSenderId);
|
|
32508
|
-
logger$o.debug('inpage_listener_routed_by_flow_id', {
|
|
32509
|
-
sender_id: senderId,
|
|
32510
|
-
original_sender_id: originalSenderId,
|
|
32511
|
-
flow_id: envelope.flowId,
|
|
32512
|
-
frame_type: envelope.frame?.type ?? 'unknown',
|
|
32513
|
-
});
|
|
32514
|
-
}
|
|
32515
|
-
}
|
|
32198
|
+
const entry = this._senderRegistry.get(senderId);
|
|
32516
32199
|
if (!entry) {
|
|
32517
32200
|
logger$o.debug('inpage_listener_no_connector_for_sender', {
|
|
32518
32201
|
sender_id: senderId,
|
|
32519
|
-
flow_id: envelope.flowId,
|
|
32520
32202
|
frame_type: envelope.frame?.type ?? 'unknown',
|
|
32521
32203
|
});
|
|
32522
32204
|
return;
|
|
@@ -32593,15 +32275,6 @@ class InPageListener extends TransportListener {
|
|
|
32593
32275
|
}
|
|
32594
32276
|
this._senderRegistry.set(senderId, entry);
|
|
32595
32277
|
this._systemToSender.set(entry.systemId, senderId);
|
|
32596
|
-
// Track the flowId if present so we can route responses back
|
|
32597
|
-
if (envelope.flowId) {
|
|
32598
|
-
this._flowIdToSender.set(envelope.flowId, senderId);
|
|
32599
|
-
logger$o.debug('inpage_listener_registered_flow_id', {
|
|
32600
|
-
sender_id: senderId,
|
|
32601
|
-
system_id: entry.systemId,
|
|
32602
|
-
flow_id: envelope.flowId,
|
|
32603
|
-
});
|
|
32604
|
-
}
|
|
32605
32278
|
await this._deliverEnvelope(entry, envelope);
|
|
32606
32279
|
}
|
|
32607
32280
|
async _createConnectorForAttach(params) {
|
|
@@ -32649,7 +32322,7 @@ class InPageListener extends TransportListener {
|
|
|
32649
32322
|
origin_type: originType,
|
|
32650
32323
|
connector_type: connector.constructor?.name ?? 'unknown',
|
|
32651
32324
|
});
|
|
32652
|
-
return { connector, systemId, originType
|
|
32325
|
+
return { connector, systemId, originType };
|
|
32653
32326
|
}
|
|
32654
32327
|
catch (error) {
|
|
32655
32328
|
logger$o.error('inpage_listener_connector_creation_failed', {
|
|
@@ -32703,12 +32376,6 @@ class InPageListener extends TransportListener {
|
|
|
32703
32376
|
if (this._systemToSender.get(systemId) === senderId) {
|
|
32704
32377
|
this._systemToSender.delete(systemId);
|
|
32705
32378
|
}
|
|
32706
|
-
// Clean up flowId mappings for this sender
|
|
32707
|
-
for (const [flowId, sid] of this._flowIdToSender.entries()) {
|
|
32708
|
-
if (sid === senderId) {
|
|
32709
|
-
this._flowIdToSender.delete(flowId);
|
|
32710
|
-
}
|
|
32711
|
-
}
|
|
32712
32379
|
})
|
|
32713
32380
|
.catch((error) => {
|
|
32714
32381
|
logger$o.debug('inpage_listener_wait_until_closed_failed', {
|
|
@@ -32720,24 +32387,9 @@ class InPageListener extends TransportListener {
|
|
|
32720
32387
|
if (this._systemToSender.get(systemId) === senderId) {
|
|
32721
32388
|
this._systemToSender.delete(systemId);
|
|
32722
32389
|
}
|
|
32723
|
-
// Clean up flowId mappings for this sender
|
|
32724
|
-
for (const [flowId, sid] of this._flowIdToSender.entries()) {
|
|
32725
|
-
if (sid === senderId) {
|
|
32726
|
-
this._flowIdToSender.delete(flowId);
|
|
32727
|
-
}
|
|
32728
|
-
}
|
|
32729
32390
|
});
|
|
32730
32391
|
}
|
|
32731
32392
|
async _deliverEnvelope(entry, envelope) {
|
|
32732
|
-
// Track flowId for routing responses back
|
|
32733
|
-
if (envelope.flowId && !this._flowIdToSender.has(envelope.flowId)) {
|
|
32734
|
-
this._flowIdToSender.set(envelope.flowId, entry.senderId);
|
|
32735
|
-
logger$o.debug('inpage_listener_registered_flow_id_on_delivery', {
|
|
32736
|
-
sender_id: entry.senderId,
|
|
32737
|
-
system_id: entry.systemId,
|
|
32738
|
-
flow_id: envelope.flowId,
|
|
32739
|
-
});
|
|
32740
|
-
}
|
|
32741
32393
|
const message = this._buildChannelMessage({
|
|
32742
32394
|
envelope,
|
|
32743
32395
|
connector: entry.connector,
|
|
@@ -32916,18 +32568,13 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
32916
32568
|
});
|
|
32917
32569
|
}
|
|
32918
32570
|
asCallbackGrant() {
|
|
32919
|
-
|
|
32571
|
+
return this.withLegacySnakeCaseKeys({
|
|
32920
32572
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE$1,
|
|
32921
32573
|
connectorType: BROADCAST_CHANNEL_CONNECTOR_TYPE$1,
|
|
32922
32574
|
connectionGrantType: BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE,
|
|
32923
32575
|
channelName: this._channelName,
|
|
32924
32576
|
inboxCapacity: this._inboxCapacity,
|
|
32925
|
-
};
|
|
32926
|
-
// Include localNodeId for transport frame multiplexing if node is available
|
|
32927
|
-
if (this._routingNode) {
|
|
32928
|
-
grant.localNodeId = this._routingNode.id;
|
|
32929
|
-
}
|
|
32930
|
-
return this.withLegacySnakeCaseKeys(grant);
|
|
32577
|
+
});
|
|
32931
32578
|
}
|
|
32932
32579
|
_registerChannelListener() {
|
|
32933
32580
|
if (this._channelHandler) {
|
|
@@ -32987,54 +32634,23 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
32987
32634
|
if (typeof senderId !== 'string' || senderId.length === 0) {
|
|
32988
32635
|
return null;
|
|
32989
32636
|
}
|
|
32990
|
-
|
|
32991
|
-
|
|
32992
|
-
|
|
32993
|
-
|
|
32994
|
-
|
|
32995
|
-
|
|
32996
|
-
// Apply listener's filtering policy: accept frames addressed to us OR with wildcard destination
|
|
32997
|
-
// Wildcard is needed because downstream nodes don't know the sentinel's ID during initial attach
|
|
32998
|
-
const isAddressedToUs = frame.dst === this._routingNode.id || frame.dst === '*';
|
|
32999
|
-
if (isAddressedToUs) {
|
|
33000
|
-
envelopePayload = frame.payload;
|
|
33001
|
-
logger$n.debug('broadcast_channel_listener_unwrapped_transport_frame', {
|
|
33002
|
-
sender_id: senderId,
|
|
33003
|
-
src: frame.src,
|
|
33004
|
-
dst: frame.dst,
|
|
33005
|
-
});
|
|
33006
|
-
}
|
|
33007
|
-
else {
|
|
33008
|
-
// Frame addressed to a different node, ignore it
|
|
33009
|
-
logger$n.debug('broadcast_channel_listener_ignored_frame_wrong_destination', {
|
|
33010
|
-
sender_id: senderId,
|
|
33011
|
-
dst: frame.dst,
|
|
33012
|
-
expected: this._routingNode.id,
|
|
33013
|
-
});
|
|
33014
|
-
return null;
|
|
33015
|
-
}
|
|
33016
|
-
}
|
|
33017
|
-
}
|
|
33018
|
-
// If not a transport frame, try to coerce as legacy format
|
|
33019
|
-
if (!envelopePayload) {
|
|
33020
|
-
envelopePayload = coercePayload(record.payload);
|
|
33021
|
-
if (!envelopePayload) {
|
|
33022
|
-
logger$n.debug('broadcast_channel_listener_ignored_event_without_payload', {
|
|
33023
|
-
sender_id: senderId,
|
|
33024
|
-
});
|
|
33025
|
-
return null;
|
|
33026
|
-
}
|
|
32637
|
+
const payload = coercePayload(record.payload);
|
|
32638
|
+
if (!payload) {
|
|
32639
|
+
logger$n.debug('broadcast_channel_listener_ignored_event_without_payload', {
|
|
32640
|
+
sender_id: senderId,
|
|
32641
|
+
});
|
|
32642
|
+
return null;
|
|
33027
32643
|
}
|
|
33028
32644
|
let envelope;
|
|
33029
32645
|
try {
|
|
33030
|
-
const decoded = new TextDecoder().decode(
|
|
32646
|
+
const decoded = new TextDecoder().decode(payload);
|
|
33031
32647
|
const parsed = JSON.parse(decoded);
|
|
33032
32648
|
envelope = deserializeEnvelope(parsed);
|
|
33033
32649
|
}
|
|
33034
32650
|
catch (error) {
|
|
33035
32651
|
const decoded = (() => {
|
|
33036
32652
|
try {
|
|
33037
|
-
return new TextDecoder().decode(
|
|
32653
|
+
return new TextDecoder().decode(payload);
|
|
33038
32654
|
}
|
|
33039
32655
|
catch {
|
|
33040
32656
|
return null;
|
|
@@ -33154,20 +32770,6 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
33154
32770
|
inboxCapacity: this._inboxCapacity,
|
|
33155
32771
|
};
|
|
33156
32772
|
}
|
|
33157
|
-
// Automatically configure transport frame multiplexing:
|
|
33158
|
-
// Use node IDs (not connector IDs) for node-to-node targeting
|
|
33159
|
-
const broadcastConfig = connectorConfig;
|
|
33160
|
-
// Always force localNodeId to be this listener's node ID
|
|
33161
|
-
// This ensures the sentinel sets localNodeId=sentinel, not the child's ID
|
|
33162
|
-
broadcastConfig.localNodeId = routingNode.id;
|
|
33163
|
-
// Always force remoteNodeId to be the attaching child's system ID
|
|
33164
|
-
broadcastConfig.remoteNodeId = systemId;
|
|
33165
|
-
logger$n.debug('broadcast_channel_listener_configured_node_ids', {
|
|
33166
|
-
sender_id: params.senderId,
|
|
33167
|
-
system_id: systemId,
|
|
33168
|
-
local_node_id: broadcastConfig.localNodeId,
|
|
33169
|
-
remote_node_id: broadcastConfig.remoteNodeId,
|
|
33170
|
-
});
|
|
33171
32773
|
try {
|
|
33172
32774
|
const connector = await routingNode.createOriginConnector({
|
|
33173
32775
|
originType,
|
|
@@ -33237,21 +32839,6 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
33237
32839
|
inboxCandidate > 0) {
|
|
33238
32840
|
config.inboxCapacity = Math.floor(inboxCandidate);
|
|
33239
32841
|
}
|
|
33240
|
-
// Extract transport frame multiplexing node IDs
|
|
33241
|
-
const localNodeIdCandidate = candidate.localNodeId ?? candidate['local_node_id'];
|
|
33242
|
-
if (typeof localNodeIdCandidate === 'string' && localNodeIdCandidate.trim().length > 0) {
|
|
33243
|
-
config.localNodeId = localNodeIdCandidate.trim();
|
|
33244
|
-
logger$n.debug('broadcast_channel_listener_extracted_local_node_id', {
|
|
33245
|
-
local_node_id: config.localNodeId,
|
|
33246
|
-
});
|
|
33247
|
-
}
|
|
33248
|
-
const remoteNodeIdCandidate = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
33249
|
-
if (typeof remoteNodeIdCandidate === 'string' && remoteNodeIdCandidate.trim().length > 0) {
|
|
33250
|
-
config.remoteNodeId = remoteNodeIdCandidate.trim();
|
|
33251
|
-
logger$n.debug('broadcast_channel_listener_extracted_remote_node_id', {
|
|
33252
|
-
remote_node_id: config.remoteNodeId,
|
|
33253
|
-
});
|
|
33254
|
-
}
|
|
33255
32842
|
return config;
|
|
33256
32843
|
}
|
|
33257
32844
|
_monitorConnectorLifecycle(senderId, systemId, connector) {
|