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