@naylence/runtime 0.3.5-test.961 → 0.3.5-test.962
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 +251 -33
- package/dist/browser/index.mjs +251 -33
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector-factory.js +27 -0
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +131 -6
- package/dist/cjs/naylence/fame/connector/broadcast-channel-listener.js +91 -25
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector-factory.js +27 -0
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +131 -6
- package/dist/esm/naylence/fame/connector/broadcast-channel-listener.js +91 -25
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +251 -33
- package/dist/node/index.mjs +251 -33
- package/dist/node/node.cjs +251 -33
- package/dist/node/node.mjs +251 -33
- package/dist/types/naylence/fame/connector/broadcast-channel-connector-factory.d.ts +5 -0
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +10 -0
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.node.d.ts +1 -6
- package/dist/types/naylence/fame/connector/broadcast-channel-listener.d.ts +3 -0
- package/dist/types/naylence/fame/grants/broadcast-channel-connection-grant.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -324,7 +324,7 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
324
324
|
node: routingNode,
|
|
325
325
|
});
|
|
326
326
|
const selection = defaultGrantSelectionPolicy.selectCallbackGrant(selectionContext);
|
|
327
|
-
connectorConfig = this._grantToConnectorConfig(selection.grant);
|
|
327
|
+
connectorConfig = this._grantToConnectorConfig(selection.grant, systemId);
|
|
328
328
|
}
|
|
329
329
|
catch (error) {
|
|
330
330
|
logger.debug('broadcast_channel_listener_grant_selection_failed', {
|
|
@@ -333,13 +333,20 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
333
333
|
error: error instanceof Error ? error.message : String(error),
|
|
334
334
|
});
|
|
335
335
|
connectorConfig =
|
|
336
|
-
this._extractBroadcastConnectorConfig(frame) ??
|
|
337
|
-
{
|
|
336
|
+
this._extractBroadcastConnectorConfig(frame, systemId) ??
|
|
337
|
+
this._buildConnectorConfigForSystem(systemId, {
|
|
338
338
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
339
339
|
channelName: this._channelName,
|
|
340
340
|
inboxCapacity: this._inboxCapacity,
|
|
341
341
|
passive: true,
|
|
342
|
-
};
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
if (!connectorConfig) {
|
|
345
|
+
logger.error('broadcast_channel_listener_missing_connector_config', {
|
|
346
|
+
sender_id: params.senderId,
|
|
347
|
+
system_id: systemId,
|
|
348
|
+
});
|
|
349
|
+
return null;
|
|
343
350
|
}
|
|
344
351
|
try {
|
|
345
352
|
const connector = await routingNode.createOriginConnector({
|
|
@@ -365,7 +372,7 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
365
372
|
return null;
|
|
366
373
|
}
|
|
367
374
|
}
|
|
368
|
-
_extractBroadcastConnectorConfig(frame) {
|
|
375
|
+
_extractBroadcastConnectorConfig(frame, systemId) {
|
|
369
376
|
const rawGrants = frame.callbackGrants;
|
|
370
377
|
if (!Array.isArray(rawGrants)) {
|
|
371
378
|
return null;
|
|
@@ -376,7 +383,10 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
376
383
|
(grant.type === BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE ||
|
|
377
384
|
grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE)) {
|
|
378
385
|
try {
|
|
379
|
-
|
|
386
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
387
|
+
return this._buildConnectorConfigForSystem(systemId, grant);
|
|
388
|
+
}
|
|
389
|
+
return this._buildConnectorConfigForSystem(systemId, broadcastChannelGrantToConnectorConfig(grant));
|
|
380
390
|
}
|
|
381
391
|
catch (error) {
|
|
382
392
|
logger.debug('broadcast_channel_listener_grant_normalization_failed', {
|
|
@@ -387,31 +397,87 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
387
397
|
}
|
|
388
398
|
return null;
|
|
389
399
|
}
|
|
390
|
-
_grantToConnectorConfig(grant) {
|
|
391
|
-
if (grant.type
|
|
392
|
-
|
|
393
|
-
|
|
400
|
+
_grantToConnectorConfig(grant, systemId) {
|
|
401
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
402
|
+
return this._buildConnectorConfigForSystem(systemId, grant);
|
|
403
|
+
}
|
|
404
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE) {
|
|
405
|
+
return this._buildConnectorConfigForSystem(systemId, broadcastChannelGrantToConnectorConfig(grant));
|
|
406
|
+
}
|
|
407
|
+
if ('toConnectorConfig' in grant &&
|
|
408
|
+
typeof grant.toConnectorConfig ===
|
|
409
|
+
'function') {
|
|
410
|
+
const normalized = grant.toConnectorConfig();
|
|
411
|
+
if (normalized.type !== BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
412
|
+
throw new Error(`Unsupported grant connector type: ${normalized.type}`);
|
|
394
413
|
}
|
|
395
|
-
|
|
414
|
+
return this._buildConnectorConfigForSystem(systemId, normalized);
|
|
396
415
|
}
|
|
397
|
-
|
|
398
|
-
|
|
416
|
+
throw new Error(`Unsupported grant type: ${grant.type}`);
|
|
417
|
+
}
|
|
418
|
+
_buildConnectorConfigForSystem(systemId, baseConfig) {
|
|
419
|
+
const localNodeId = this._requireLocalNodeId();
|
|
420
|
+
const targetSystemId = this._normalizeNodeId(systemId);
|
|
421
|
+
if (!targetSystemId) {
|
|
422
|
+
throw new Error('BroadcastChannelListener requires a valid system id');
|
|
423
|
+
}
|
|
424
|
+
const candidate = baseConfig ?? null;
|
|
425
|
+
const channelCandidate = candidate && 'channelName' in candidate
|
|
426
|
+
? candidate.channelName
|
|
427
|
+
: undefined;
|
|
428
|
+
const inboxCandidate = candidate && 'inboxCapacity' in candidate
|
|
429
|
+
? candidate.inboxCapacity
|
|
430
|
+
: undefined;
|
|
431
|
+
const initialWindowCandidate = candidate && 'initialWindow' in candidate
|
|
432
|
+
? candidate.initialWindow
|
|
433
|
+
: undefined;
|
|
434
|
+
const passiveCandidate = candidate && 'passive' in candidate
|
|
435
|
+
? candidate.passive
|
|
436
|
+
: undefined;
|
|
437
|
+
const targetCandidate = candidate && 'initialTargetNodeId' in candidate
|
|
438
|
+
? candidate.initialTargetNodeId
|
|
439
|
+
: undefined;
|
|
440
|
+
const channelName = typeof channelCandidate === 'string' && channelCandidate.trim().length > 0
|
|
441
|
+
? channelCandidate.trim()
|
|
442
|
+
: this._channelName;
|
|
443
|
+
const inboxCapacity = typeof inboxCandidate === 'number' &&
|
|
444
|
+
Number.isFinite(inboxCandidate) &&
|
|
445
|
+
inboxCandidate > 0
|
|
446
|
+
? Math.floor(inboxCandidate)
|
|
447
|
+
: this._inboxCapacity;
|
|
448
|
+
const initialWindow = typeof initialWindowCandidate === 'number' &&
|
|
449
|
+
Number.isFinite(initialWindowCandidate) &&
|
|
450
|
+
initialWindowCandidate > 0
|
|
451
|
+
? Math.floor(initialWindowCandidate)
|
|
452
|
+
: undefined;
|
|
453
|
+
const initialTargetNodeId = this._normalizeNodeId(targetCandidate) ?? targetSystemId;
|
|
454
|
+
return {
|
|
399
455
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
400
|
-
channelName
|
|
401
|
-
inboxCapacity
|
|
402
|
-
passive: true,
|
|
456
|
+
channelName,
|
|
457
|
+
inboxCapacity,
|
|
458
|
+
passive: typeof passiveCandidate === 'boolean' ? passiveCandidate : true,
|
|
459
|
+
initialWindow,
|
|
460
|
+
localNodeId,
|
|
461
|
+
initialTargetNodeId,
|
|
403
462
|
};
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
463
|
+
}
|
|
464
|
+
_requireLocalNodeId() {
|
|
465
|
+
if (!this._routingNode) {
|
|
466
|
+
throw new Error('BroadcastChannelListener requires routing node context');
|
|
407
467
|
}
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
468
|
+
const normalized = this._normalizeNodeId(this._routingNode.sid) ??
|
|
469
|
+
this._normalizeNodeId(this._routingNode.id);
|
|
470
|
+
if (!normalized) {
|
|
471
|
+
throw new Error('BroadcastChannelListener requires routing node with a stable identifier');
|
|
472
|
+
}
|
|
473
|
+
return normalized;
|
|
474
|
+
}
|
|
475
|
+
_normalizeNodeId(value) {
|
|
476
|
+
if (typeof value !== 'string') {
|
|
477
|
+
return null;
|
|
413
478
|
}
|
|
414
|
-
|
|
479
|
+
const trimmed = value.trim();
|
|
480
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
415
481
|
}
|
|
416
482
|
_monitorConnectorLifecycle(senderId, systemId, connector) {
|
|
417
483
|
const maybeClosable = connector;
|
package/dist/esm/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This file is auto-generated during build - do not edit manually
|
|
2
|
-
// Generated from package.json version: 0.3.5-test.
|
|
2
|
+
// Generated from package.json version: 0.3.5-test.962
|
|
3
3
|
/**
|
|
4
4
|
* The package version, injected at build time.
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
export const VERSION = '0.3.5-test.
|
|
7
|
+
export const VERSION = '0.3.5-test.962';
|
package/dist/node/index.cjs
CHANGED
|
@@ -14,12 +14,12 @@ var fastify = require('fastify');
|
|
|
14
14
|
var websocketPlugin = require('@fastify/websocket');
|
|
15
15
|
|
|
16
16
|
// This file is auto-generated during build - do not edit manually
|
|
17
|
-
// Generated from package.json version: 0.3.5-test.
|
|
17
|
+
// Generated from package.json version: 0.3.5-test.962
|
|
18
18
|
/**
|
|
19
19
|
* The package version, injected at build time.
|
|
20
20
|
* @internal
|
|
21
21
|
*/
|
|
22
|
-
const VERSION = '0.3.5-test.
|
|
22
|
+
const VERSION = '0.3.5-test.962';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9862,6 +9862,26 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9862
9862
|
}
|
|
9863
9863
|
return null;
|
|
9864
9864
|
}
|
|
9865
|
+
static normalizeNodeId(value) {
|
|
9866
|
+
if (typeof value !== 'string') {
|
|
9867
|
+
return null;
|
|
9868
|
+
}
|
|
9869
|
+
const trimmed = value.trim();
|
|
9870
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
9871
|
+
}
|
|
9872
|
+
static normalizeTargetNodeId(value) {
|
|
9873
|
+
if (typeof value !== 'string') {
|
|
9874
|
+
return undefined;
|
|
9875
|
+
}
|
|
9876
|
+
const trimmed = value.trim();
|
|
9877
|
+
if (trimmed.length === 0) {
|
|
9878
|
+
return undefined;
|
|
9879
|
+
}
|
|
9880
|
+
if (trimmed === '*') {
|
|
9881
|
+
return '*';
|
|
9882
|
+
}
|
|
9883
|
+
return trimmed;
|
|
9884
|
+
}
|
|
9865
9885
|
constructor(config, baseConfig = {}) {
|
|
9866
9886
|
ensureBroadcastEnvironment();
|
|
9867
9887
|
super(baseConfig);
|
|
@@ -9884,10 +9904,18 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9884
9904
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9885
9905
|
this.inboxCapacity = preferredCapacity;
|
|
9886
9906
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9907
|
+
const normalizedLocalNodeId = BroadcastChannelConnector.normalizeNodeId(config.localNodeId);
|
|
9908
|
+
if (!normalizedLocalNodeId) {
|
|
9909
|
+
throw new Error('BroadcastChannelConnector requires a non-empty localNodeId');
|
|
9910
|
+
}
|
|
9911
|
+
this.localNodeId = normalizedLocalNodeId;
|
|
9912
|
+
this.targetNodeId = BroadcastChannelConnector.normalizeTargetNodeId(config.initialTargetNodeId);
|
|
9887
9913
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9888
9914
|
logger$_.debug('broadcast_channel_connector_created', {
|
|
9889
9915
|
channel: this.channelName,
|
|
9890
9916
|
connector_id: this.connectorId,
|
|
9917
|
+
local_node_id: this.localNodeId,
|
|
9918
|
+
target_node_id: this.targetNodeId ?? null,
|
|
9891
9919
|
inbox_capacity: preferredCapacity,
|
|
9892
9920
|
timestamp: new Date().toISOString(),
|
|
9893
9921
|
});
|
|
@@ -9909,15 +9937,32 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9909
9937
|
? message.constructor?.name ?? typeof message
|
|
9910
9938
|
: typeof message,
|
|
9911
9939
|
has_sender_id: Boolean(message?.senderId),
|
|
9940
|
+
has_sender_node_id: Boolean(message?.senderNodeId),
|
|
9912
9941
|
});
|
|
9913
9942
|
if (!message || typeof message !== 'object') {
|
|
9914
9943
|
return;
|
|
9915
9944
|
}
|
|
9916
9945
|
const busMessage = message;
|
|
9917
|
-
|
|
9946
|
+
const senderNodeId = BroadcastChannelConnector.normalizeNodeId(busMessage.senderNodeId);
|
|
9947
|
+
if (!senderNodeId) {
|
|
9948
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
9949
|
+
channel: this.channelName,
|
|
9950
|
+
connector_id: this.connectorId,
|
|
9951
|
+
reason: 'missing_sender_node_id',
|
|
9952
|
+
});
|
|
9918
9953
|
return;
|
|
9919
9954
|
}
|
|
9920
|
-
if (
|
|
9955
|
+
if (senderNodeId === this.localNodeId) {
|
|
9956
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
9957
|
+
channel: this.channelName,
|
|
9958
|
+
connector_id: this.connectorId,
|
|
9959
|
+
reason: 'self_echo',
|
|
9960
|
+
sender_node_id: senderNodeId,
|
|
9961
|
+
});
|
|
9962
|
+
return;
|
|
9963
|
+
}
|
|
9964
|
+
const incomingTargetNodeId = BroadcastChannelConnector.normalizeTargetNodeId(busMessage.targetNodeId);
|
|
9965
|
+
if (!this._shouldAcceptMessageFromBus(senderNodeId, incomingTargetNodeId)) {
|
|
9921
9966
|
return;
|
|
9922
9967
|
}
|
|
9923
9968
|
const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
|
|
@@ -9931,11 +9976,13 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9931
9976
|
}
|
|
9932
9977
|
logger$_.debug('broadcast_channel_message_received', {
|
|
9933
9978
|
channel: this.channelName,
|
|
9934
|
-
sender_id:
|
|
9979
|
+
sender_id: message?.senderId,
|
|
9980
|
+
sender_node_id: senderNodeId,
|
|
9981
|
+
target_node_id: incomingTargetNodeId ?? null,
|
|
9935
9982
|
connector_id: this.connectorId,
|
|
9936
9983
|
payload_length: payload.byteLength,
|
|
9937
9984
|
});
|
|
9938
|
-
if (this._shouldSkipDuplicateAck(
|
|
9985
|
+
if (this._shouldSkipDuplicateAck(senderNodeId, payload)) {
|
|
9939
9986
|
return;
|
|
9940
9987
|
}
|
|
9941
9988
|
try {
|
|
@@ -10079,12 +10126,17 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10079
10126
|
}
|
|
10080
10127
|
async _transportSendBytes(data) {
|
|
10081
10128
|
ensureBroadcastEnvironment();
|
|
10129
|
+
const targetNodeId = this.targetNodeId ?? '*';
|
|
10082
10130
|
logger$_.debug('broadcast_channel_message_sending', {
|
|
10083
10131
|
channel: this.channelName,
|
|
10084
10132
|
sender_id: this.connectorId,
|
|
10133
|
+
sender_node_id: this.localNodeId,
|
|
10134
|
+
target_node_id: targetNodeId,
|
|
10085
10135
|
});
|
|
10086
10136
|
this.channel.postMessage({
|
|
10087
10137
|
senderId: this.connectorId,
|
|
10138
|
+
senderNodeId: this.localNodeId,
|
|
10139
|
+
targetNodeId,
|
|
10088
10140
|
payload: data,
|
|
10089
10141
|
});
|
|
10090
10142
|
}
|
|
@@ -10147,6 +10199,51 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10147
10199
|
}
|
|
10148
10200
|
return rawOrEnvelope;
|
|
10149
10201
|
}
|
|
10202
|
+
_isWildcardTarget() {
|
|
10203
|
+
return this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined';
|
|
10204
|
+
}
|
|
10205
|
+
_shouldAcceptMessageFromBus(senderNodeId, targetNodeId) {
|
|
10206
|
+
if (this._isWildcardTarget()) {
|
|
10207
|
+
if (targetNodeId && targetNodeId !== '*') {
|
|
10208
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
10209
|
+
channel: this.channelName,
|
|
10210
|
+
connector_id: this.connectorId,
|
|
10211
|
+
reason: 'wildcard_target_mismatch',
|
|
10212
|
+
sender_node_id: senderNodeId,
|
|
10213
|
+
target_node_id: targetNodeId,
|
|
10214
|
+
local_node_id: this.localNodeId,
|
|
10215
|
+
});
|
|
10216
|
+
return false;
|
|
10217
|
+
}
|
|
10218
|
+
return true;
|
|
10219
|
+
}
|
|
10220
|
+
const expectedSender = this.targetNodeId;
|
|
10221
|
+
if (expectedSender && expectedSender !== '*' && senderNodeId !== expectedSender) {
|
|
10222
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
10223
|
+
channel: this.channelName,
|
|
10224
|
+
connector_id: this.connectorId,
|
|
10225
|
+
reason: 'unexpected_sender',
|
|
10226
|
+
expected_sender_node_id: expectedSender,
|
|
10227
|
+
sender_node_id: senderNodeId,
|
|
10228
|
+
local_node_id: this.localNodeId,
|
|
10229
|
+
});
|
|
10230
|
+
return false;
|
|
10231
|
+
}
|
|
10232
|
+
if (targetNodeId &&
|
|
10233
|
+
targetNodeId !== '*' &&
|
|
10234
|
+
targetNodeId !== this.localNodeId) {
|
|
10235
|
+
logger$_.debug('broadcast_channel_message_rejected', {
|
|
10236
|
+
channel: this.channelName,
|
|
10237
|
+
connector_id: this.connectorId,
|
|
10238
|
+
reason: 'unexpected_target',
|
|
10239
|
+
sender_node_id: senderNodeId,
|
|
10240
|
+
target_node_id: targetNodeId,
|
|
10241
|
+
local_node_id: this.localNodeId,
|
|
10242
|
+
});
|
|
10243
|
+
return false;
|
|
10244
|
+
}
|
|
10245
|
+
return true;
|
|
10246
|
+
}
|
|
10150
10247
|
_describeInboxItem(item) {
|
|
10151
10248
|
if (item instanceof Uint8Array) {
|
|
10152
10249
|
return 'bytes';
|
|
@@ -10177,7 +10274,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10177
10274
|
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
10178
10275
|
? senderId
|
|
10179
10276
|
: undefined;
|
|
10180
|
-
if (normalizedSenderId && normalizedSenderId !== this.
|
|
10277
|
+
if (normalizedSenderId && normalizedSenderId !== this.localNodeId) {
|
|
10181
10278
|
logger$_.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
10182
10279
|
channel: this.channelName,
|
|
10183
10280
|
connector_id: this.connectorId,
|
|
@@ -10217,7 +10314,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10217
10314
|
return false;
|
|
10218
10315
|
}
|
|
10219
10316
|
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
10220
|
-
if (senderId && senderId !== this.
|
|
10317
|
+
if (senderId && senderId !== this.localNodeId) {
|
|
10221
10318
|
logger$_.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
10222
10319
|
channel: this.channelName,
|
|
10223
10320
|
connector_id: this.connectorId,
|
|
@@ -10313,6 +10410,34 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10313
10410
|
});
|
|
10314
10411
|
}
|
|
10315
10412
|
}
|
|
10413
|
+
setTargetNodeId(nodeId) {
|
|
10414
|
+
const normalized = BroadcastChannelConnector.normalizeNodeId(nodeId);
|
|
10415
|
+
if (!normalized) {
|
|
10416
|
+
throw new Error('BroadcastChannelConnector target node id must be a non-empty string');
|
|
10417
|
+
}
|
|
10418
|
+
if (normalized === '*') {
|
|
10419
|
+
this.setWildcardTarget();
|
|
10420
|
+
return;
|
|
10421
|
+
}
|
|
10422
|
+
this.targetNodeId = normalized;
|
|
10423
|
+
logger$_.debug('broadcast_channel_target_updated', {
|
|
10424
|
+
channel: this.channelName,
|
|
10425
|
+
connector_id: this.connectorId,
|
|
10426
|
+
local_node_id: this.localNodeId,
|
|
10427
|
+
target_node_id: this.targetNodeId,
|
|
10428
|
+
target_mode: 'direct',
|
|
10429
|
+
});
|
|
10430
|
+
}
|
|
10431
|
+
setWildcardTarget() {
|
|
10432
|
+
this.targetNodeId = '*';
|
|
10433
|
+
logger$_.debug('broadcast_channel_target_updated', {
|
|
10434
|
+
channel: this.channelName,
|
|
10435
|
+
connector_id: this.connectorId,
|
|
10436
|
+
local_node_id: this.localNodeId,
|
|
10437
|
+
target_node_id: this.targetNodeId,
|
|
10438
|
+
target_mode: 'wildcard',
|
|
10439
|
+
});
|
|
10440
|
+
}
|
|
10316
10441
|
_trimSeenAcks(now) {
|
|
10317
10442
|
while (this.seenAckOrder.length > 0) {
|
|
10318
10443
|
const candidate = this.seenAckOrder[0];
|
|
@@ -28687,8 +28812,13 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28687
28812
|
}
|
|
28688
28813
|
const normalized = this._normalizeConfig(config);
|
|
28689
28814
|
const options = (factoryArgs[0] ?? {});
|
|
28815
|
+
const localNodeId = this._normalizeNodeId(options.localNodeId);
|
|
28816
|
+
if (!localNodeId) {
|
|
28817
|
+
throw new Error('BroadcastChannelConnectorFactory requires a localNodeId in create() options');
|
|
28818
|
+
}
|
|
28690
28819
|
const channelName = normalized.channelName ?? DEFAULT_CHANNEL$5;
|
|
28691
28820
|
const inboxCapacity = normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
|
|
28821
|
+
const resolvedTarget = this._normalizeTargetNodeId(options.initialTargetNodeId ?? normalized.initialTargetNodeId);
|
|
28692
28822
|
const baseConfig = {
|
|
28693
28823
|
drainTimeout: normalized.drainTimeout,
|
|
28694
28824
|
flowControl: normalized.flowControl,
|
|
@@ -28703,6 +28833,8 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28703
28833
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
28704
28834
|
channelName,
|
|
28705
28835
|
inboxCapacity,
|
|
28836
|
+
localNodeId,
|
|
28837
|
+
initialTargetNodeId: resolvedTarget,
|
|
28706
28838
|
};
|
|
28707
28839
|
const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
28708
28840
|
if (options.authorization) {
|
|
@@ -28726,6 +28858,13 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28726
28858
|
normalized.channelName = channel.trim();
|
|
28727
28859
|
}
|
|
28728
28860
|
const capacity = candidate.inboxCapacity ?? candidate['inbox_capacity'];
|
|
28861
|
+
const initialTargetNodeId = candidate.initialTargetNodeId ?? candidate['initial_target_node_id'];
|
|
28862
|
+
if (typeof initialTargetNodeId === 'string' && initialTargetNodeId.trim().length > 0) {
|
|
28863
|
+
normalized.initialTargetNodeId = initialTargetNodeId.trim();
|
|
28864
|
+
}
|
|
28865
|
+
else if (initialTargetNodeId === '*') {
|
|
28866
|
+
normalized.initialTargetNodeId = '*';
|
|
28867
|
+
}
|
|
28729
28868
|
if (typeof capacity === 'number' &&
|
|
28730
28869
|
Number.isFinite(capacity) &&
|
|
28731
28870
|
capacity > 0) {
|
|
@@ -28769,6 +28908,19 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28769
28908
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
|
|
28770
28909
|
return normalized;
|
|
28771
28910
|
}
|
|
28911
|
+
_normalizeNodeId(value) {
|
|
28912
|
+
if (typeof value !== 'string') {
|
|
28913
|
+
return null;
|
|
28914
|
+
}
|
|
28915
|
+
const trimmed = value.trim();
|
|
28916
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
28917
|
+
}
|
|
28918
|
+
_normalizeTargetNodeId(value) {
|
|
28919
|
+
if (value === '*') {
|
|
28920
|
+
return '*';
|
|
28921
|
+
}
|
|
28922
|
+
return this._normalizeNodeId(value) ?? '*';
|
|
28923
|
+
}
|
|
28772
28924
|
}
|
|
28773
28925
|
|
|
28774
28926
|
var broadcastChannelConnectorFactory = /*#__PURE__*/Object.freeze({
|
|
@@ -36346,7 +36498,7 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36346
36498
|
node: routingNode,
|
|
36347
36499
|
});
|
|
36348
36500
|
const selection = defaultGrantSelectionPolicy.selectCallbackGrant(selectionContext);
|
|
36349
|
-
connectorConfig = this._grantToConnectorConfig(selection.grant);
|
|
36501
|
+
connectorConfig = this._grantToConnectorConfig(selection.grant, systemId);
|
|
36350
36502
|
}
|
|
36351
36503
|
catch (error) {
|
|
36352
36504
|
logger$a.debug('broadcast_channel_listener_grant_selection_failed', {
|
|
@@ -36355,13 +36507,20 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36355
36507
|
error: error instanceof Error ? error.message : String(error),
|
|
36356
36508
|
});
|
|
36357
36509
|
connectorConfig =
|
|
36358
|
-
this._extractBroadcastConnectorConfig(frame) ??
|
|
36359
|
-
{
|
|
36510
|
+
this._extractBroadcastConnectorConfig(frame, systemId) ??
|
|
36511
|
+
this._buildConnectorConfigForSystem(systemId, {
|
|
36360
36512
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
36361
36513
|
channelName: this._channelName,
|
|
36362
36514
|
inboxCapacity: this._inboxCapacity,
|
|
36363
36515
|
passive: true,
|
|
36364
|
-
};
|
|
36516
|
+
});
|
|
36517
|
+
}
|
|
36518
|
+
if (!connectorConfig) {
|
|
36519
|
+
logger$a.error('broadcast_channel_listener_missing_connector_config', {
|
|
36520
|
+
sender_id: params.senderId,
|
|
36521
|
+
system_id: systemId,
|
|
36522
|
+
});
|
|
36523
|
+
return null;
|
|
36365
36524
|
}
|
|
36366
36525
|
try {
|
|
36367
36526
|
const connector = await routingNode.createOriginConnector({
|
|
@@ -36387,7 +36546,7 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36387
36546
|
return null;
|
|
36388
36547
|
}
|
|
36389
36548
|
}
|
|
36390
|
-
_extractBroadcastConnectorConfig(frame) {
|
|
36549
|
+
_extractBroadcastConnectorConfig(frame, systemId) {
|
|
36391
36550
|
const rawGrants = frame.callbackGrants;
|
|
36392
36551
|
if (!Array.isArray(rawGrants)) {
|
|
36393
36552
|
return null;
|
|
@@ -36398,7 +36557,10 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36398
36557
|
(grant.type === BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE ||
|
|
36399
36558
|
grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE)) {
|
|
36400
36559
|
try {
|
|
36401
|
-
|
|
36560
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
36561
|
+
return this._buildConnectorConfigForSystem(systemId, grant);
|
|
36562
|
+
}
|
|
36563
|
+
return this._buildConnectorConfigForSystem(systemId, broadcastChannelGrantToConnectorConfig(grant));
|
|
36402
36564
|
}
|
|
36403
36565
|
catch (error) {
|
|
36404
36566
|
logger$a.debug('broadcast_channel_listener_grant_normalization_failed', {
|
|
@@ -36409,31 +36571,87 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36409
36571
|
}
|
|
36410
36572
|
return null;
|
|
36411
36573
|
}
|
|
36412
|
-
_grantToConnectorConfig(grant) {
|
|
36413
|
-
if (grant.type
|
|
36414
|
-
|
|
36415
|
-
|
|
36574
|
+
_grantToConnectorConfig(grant, systemId) {
|
|
36575
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
36576
|
+
return this._buildConnectorConfigForSystem(systemId, grant);
|
|
36577
|
+
}
|
|
36578
|
+
if (grant.type === BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE) {
|
|
36579
|
+
return this._buildConnectorConfigForSystem(systemId, broadcastChannelGrantToConnectorConfig(grant));
|
|
36580
|
+
}
|
|
36581
|
+
if ('toConnectorConfig' in grant &&
|
|
36582
|
+
typeof grant.toConnectorConfig ===
|
|
36583
|
+
'function') {
|
|
36584
|
+
const normalized = grant.toConnectorConfig();
|
|
36585
|
+
if (normalized.type !== BROADCAST_CHANNEL_CONNECTOR_TYPE) {
|
|
36586
|
+
throw new Error(`Unsupported grant connector type: ${normalized.type}`);
|
|
36416
36587
|
}
|
|
36417
|
-
|
|
36588
|
+
return this._buildConnectorConfigForSystem(systemId, normalized);
|
|
36418
36589
|
}
|
|
36419
|
-
|
|
36420
|
-
|
|
36590
|
+
throw new Error(`Unsupported grant type: ${grant.type}`);
|
|
36591
|
+
}
|
|
36592
|
+
_buildConnectorConfigForSystem(systemId, baseConfig) {
|
|
36593
|
+
const localNodeId = this._requireLocalNodeId();
|
|
36594
|
+
const targetSystemId = this._normalizeNodeId(systemId);
|
|
36595
|
+
if (!targetSystemId) {
|
|
36596
|
+
throw new Error('BroadcastChannelListener requires a valid system id');
|
|
36597
|
+
}
|
|
36598
|
+
const candidate = baseConfig ?? null;
|
|
36599
|
+
const channelCandidate = candidate && 'channelName' in candidate
|
|
36600
|
+
? candidate.channelName
|
|
36601
|
+
: undefined;
|
|
36602
|
+
const inboxCandidate = candidate && 'inboxCapacity' in candidate
|
|
36603
|
+
? candidate.inboxCapacity
|
|
36604
|
+
: undefined;
|
|
36605
|
+
const initialWindowCandidate = candidate && 'initialWindow' in candidate
|
|
36606
|
+
? candidate.initialWindow
|
|
36607
|
+
: undefined;
|
|
36608
|
+
const passiveCandidate = candidate && 'passive' in candidate
|
|
36609
|
+
? candidate.passive
|
|
36610
|
+
: undefined;
|
|
36611
|
+
const targetCandidate = candidate && 'initialTargetNodeId' in candidate
|
|
36612
|
+
? candidate.initialTargetNodeId
|
|
36613
|
+
: undefined;
|
|
36614
|
+
const channelName = typeof channelCandidate === 'string' && channelCandidate.trim().length > 0
|
|
36615
|
+
? channelCandidate.trim()
|
|
36616
|
+
: this._channelName;
|
|
36617
|
+
const inboxCapacity = typeof inboxCandidate === 'number' &&
|
|
36618
|
+
Number.isFinite(inboxCandidate) &&
|
|
36619
|
+
inboxCandidate > 0
|
|
36620
|
+
? Math.floor(inboxCandidate)
|
|
36621
|
+
: this._inboxCapacity;
|
|
36622
|
+
const initialWindow = typeof initialWindowCandidate === 'number' &&
|
|
36623
|
+
Number.isFinite(initialWindowCandidate) &&
|
|
36624
|
+
initialWindowCandidate > 0
|
|
36625
|
+
? Math.floor(initialWindowCandidate)
|
|
36626
|
+
: undefined;
|
|
36627
|
+
const initialTargetNodeId = this._normalizeNodeId(targetCandidate) ?? targetSystemId;
|
|
36628
|
+
return {
|
|
36421
36629
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
36422
|
-
channelName
|
|
36423
|
-
inboxCapacity
|
|
36424
|
-
passive: true,
|
|
36630
|
+
channelName,
|
|
36631
|
+
inboxCapacity,
|
|
36632
|
+
passive: typeof passiveCandidate === 'boolean' ? passiveCandidate : true,
|
|
36633
|
+
initialWindow,
|
|
36634
|
+
localNodeId,
|
|
36635
|
+
initialTargetNodeId,
|
|
36425
36636
|
};
|
|
36426
|
-
|
|
36427
|
-
|
|
36428
|
-
|
|
36637
|
+
}
|
|
36638
|
+
_requireLocalNodeId() {
|
|
36639
|
+
if (!this._routingNode) {
|
|
36640
|
+
throw new Error('BroadcastChannelListener requires routing node context');
|
|
36429
36641
|
}
|
|
36430
|
-
const
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
config.inboxCapacity = Math.floor(inboxCandidate);
|
|
36642
|
+
const normalized = this._normalizeNodeId(this._routingNode.sid) ??
|
|
36643
|
+
this._normalizeNodeId(this._routingNode.id);
|
|
36644
|
+
if (!normalized) {
|
|
36645
|
+
throw new Error('BroadcastChannelListener requires routing node with a stable identifier');
|
|
36435
36646
|
}
|
|
36436
|
-
return
|
|
36647
|
+
return normalized;
|
|
36648
|
+
}
|
|
36649
|
+
_normalizeNodeId(value) {
|
|
36650
|
+
if (typeof value !== 'string') {
|
|
36651
|
+
return null;
|
|
36652
|
+
}
|
|
36653
|
+
const trimmed = value.trim();
|
|
36654
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
36437
36655
|
}
|
|
36438
36656
|
_monitorConnectorLifecycle(senderId, systemId, connector) {
|
|
36439
36657
|
const maybeClosable = connector;
|