@naylence/runtime 0.3.5-test.965 → 0.3.5-test.966
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 +2 -175
- package/dist/browser/index.mjs +2 -175
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +0 -173
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +0 -173
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +2 -175
- package/dist/node/index.mjs +2 -175
- package/dist/node/node.cjs +2 -175
- package/dist/node/node.mjs +2 -175
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +0 -12
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -70,11 +70,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
70
70
|
ensureBroadcastEnvironment();
|
|
71
71
|
super(baseConfig);
|
|
72
72
|
this.listenerRegistered = false;
|
|
73
|
-
this.seenAckKeys = new Map();
|
|
74
|
-
this.seenAckOrder = [];
|
|
75
|
-
this.ackDedupTtlMs = 30000;
|
|
76
|
-
this.ackDedupMaxEntries = 4096;
|
|
77
|
-
this.textDecoder = new TextDecoder();
|
|
78
73
|
this.visibilityChangeListenerRegistered = false;
|
|
79
74
|
this.channelName =
|
|
80
75
|
typeof config.channelName === 'string' && config.channelName.trim().length > 0
|
|
@@ -166,9 +161,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
166
161
|
connector_id: this.connectorId,
|
|
167
162
|
payload_length: payload.byteLength,
|
|
168
163
|
});
|
|
169
|
-
if (this._shouldSkipDuplicateAck(senderNodeId, payload)) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
164
|
try {
|
|
173
165
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
174
166
|
const accepted = this.inbox.tryEnqueue(payload);
|
|
@@ -272,9 +264,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
272
264
|
}
|
|
273
265
|
async pushToReceive(rawOrEnvelope) {
|
|
274
266
|
const item = this._normalizeInboxItem(rawOrEnvelope);
|
|
275
|
-
if (this._shouldSkipDuplicateAckFromInboxItem(item)) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
267
|
try {
|
|
279
268
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
280
269
|
const accepted = this.inbox.tryEnqueue(item);
|
|
@@ -374,8 +363,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
374
363
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
375
364
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
376
365
|
this.inbox.drain(shutdownError);
|
|
377
|
-
this.seenAckKeys.clear();
|
|
378
|
-
this.seenAckOrder.length = 0;
|
|
379
366
|
}
|
|
380
367
|
_normalizeInboxItem(rawOrEnvelope) {
|
|
381
368
|
if (rawOrEnvelope instanceof Uint8Array) {
|
|
@@ -452,125 +439,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
452
439
|
...extra,
|
|
453
440
|
});
|
|
454
441
|
}
|
|
455
|
-
_shouldSkipDuplicateAck(senderId, payload) {
|
|
456
|
-
const dedupKey = this._extractAckDedupKey(payload);
|
|
457
|
-
if (!dedupKey) {
|
|
458
|
-
return false;
|
|
459
|
-
}
|
|
460
|
-
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
461
|
-
? senderId
|
|
462
|
-
: undefined;
|
|
463
|
-
if (normalizedSenderId && normalizedSenderId !== this.localNodeId) {
|
|
464
|
-
logger.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
465
|
-
channel: this.channelName,
|
|
466
|
-
connector_id: this.connectorId,
|
|
467
|
-
sender_id: normalizedSenderId,
|
|
468
|
-
dedup_key: dedupKey,
|
|
469
|
-
source: 'listener',
|
|
470
|
-
});
|
|
471
|
-
return false;
|
|
472
|
-
}
|
|
473
|
-
logger.debug('broadcast_channel_duplicate_ack_check', {
|
|
474
|
-
channel: this.channelName,
|
|
475
|
-
connector_id: this.connectorId,
|
|
476
|
-
sender_id: normalizedSenderId ?? null,
|
|
477
|
-
dedup_key: dedupKey,
|
|
478
|
-
source: 'listener',
|
|
479
|
-
cache_entries: this.seenAckKeys.size,
|
|
480
|
-
});
|
|
481
|
-
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
482
|
-
}
|
|
483
|
-
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
484
|
-
if (item instanceof Uint8Array) {
|
|
485
|
-
return this._shouldSkipDuplicateAck(undefined, item);
|
|
486
|
-
}
|
|
487
|
-
const envelope = this._extractEnvelopeFromInboxItem(item);
|
|
488
|
-
if (!envelope) {
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
const frame = envelope.frame;
|
|
492
|
-
if (!frame || frame.type !== 'DeliveryAck') {
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
const refId = typeof frame.refId === 'string' && frame.refId.length > 0
|
|
496
|
-
? frame.refId
|
|
497
|
-
: null;
|
|
498
|
-
const dedupKey = refId ?? envelope.id ?? null;
|
|
499
|
-
if (!dedupKey) {
|
|
500
|
-
return false;
|
|
501
|
-
}
|
|
502
|
-
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
503
|
-
if (senderId && senderId !== this.localNodeId) {
|
|
504
|
-
logger.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
505
|
-
channel: this.channelName,
|
|
506
|
-
connector_id: this.connectorId,
|
|
507
|
-
sender_id: senderId,
|
|
508
|
-
dedup_key: dedupKey,
|
|
509
|
-
source: 'inbox_item',
|
|
510
|
-
});
|
|
511
|
-
return false;
|
|
512
|
-
}
|
|
513
|
-
logger.debug('broadcast_channel_duplicate_ack_check', {
|
|
514
|
-
channel: this.channelName,
|
|
515
|
-
connector_id: this.connectorId,
|
|
516
|
-
sender_id: senderId ?? null,
|
|
517
|
-
dedup_key: dedupKey,
|
|
518
|
-
source: 'inbox_item',
|
|
519
|
-
cache_entries: this.seenAckKeys.size,
|
|
520
|
-
});
|
|
521
|
-
return this._checkDuplicateAck(dedupKey, senderId);
|
|
522
|
-
}
|
|
523
|
-
_checkDuplicateAck(dedupKey, senderId) {
|
|
524
|
-
const now = Date.now();
|
|
525
|
-
const lastSeen = this.seenAckKeys.get(dedupKey);
|
|
526
|
-
if (lastSeen && now - lastSeen < this.ackDedupTtlMs) {
|
|
527
|
-
logger.debug('broadcast_channel_duplicate_ack_suppressed', {
|
|
528
|
-
channel: this.channelName,
|
|
529
|
-
connector_id: this.connectorId,
|
|
530
|
-
sender_id: senderId ?? null,
|
|
531
|
-
dedup_key: dedupKey,
|
|
532
|
-
age_ms: now - lastSeen,
|
|
533
|
-
ttl_ms: this.ackDedupTtlMs,
|
|
534
|
-
cache_entries: this.seenAckKeys.size,
|
|
535
|
-
});
|
|
536
|
-
return true;
|
|
537
|
-
}
|
|
538
|
-
this.seenAckKeys.set(dedupKey, now);
|
|
539
|
-
this.seenAckOrder.push(dedupKey);
|
|
540
|
-
logger.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
541
|
-
channel: this.channelName,
|
|
542
|
-
connector_id: this.connectorId,
|
|
543
|
-
sender_id: senderId ?? null,
|
|
544
|
-
dedup_key: dedupKey,
|
|
545
|
-
cache_entries: this.seenAckKeys.size,
|
|
546
|
-
});
|
|
547
|
-
this._trimSeenAcks(now);
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
_extractEnvelopeFromInboxItem(item) {
|
|
551
|
-
if (!item || typeof item !== 'object') {
|
|
552
|
-
return null;
|
|
553
|
-
}
|
|
554
|
-
if ('envelope' in item) {
|
|
555
|
-
return item.envelope;
|
|
556
|
-
}
|
|
557
|
-
if ('frame' in item) {
|
|
558
|
-
return item;
|
|
559
|
-
}
|
|
560
|
-
return null;
|
|
561
|
-
}
|
|
562
|
-
_extractSenderIdFromInboxItem(item) {
|
|
563
|
-
if (!item || typeof item !== 'object') {
|
|
564
|
-
return undefined;
|
|
565
|
-
}
|
|
566
|
-
if ('context' in item) {
|
|
567
|
-
const context = item.context;
|
|
568
|
-
if (context && typeof context.fromSystemId === 'string') {
|
|
569
|
-
return context.fromSystemId;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
return undefined;
|
|
573
|
-
}
|
|
574
442
|
/**
|
|
575
443
|
* Override start() to check initial visibility state
|
|
576
444
|
*/
|
|
@@ -624,45 +492,4 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
624
492
|
target_mode: 'wildcard',
|
|
625
493
|
});
|
|
626
494
|
}
|
|
627
|
-
_trimSeenAcks(now) {
|
|
628
|
-
while (this.seenAckOrder.length > 0) {
|
|
629
|
-
const candidate = this.seenAckOrder[0];
|
|
630
|
-
const timestamp = this.seenAckKeys.get(candidate);
|
|
631
|
-
if (timestamp === undefined) {
|
|
632
|
-
this.seenAckOrder.shift();
|
|
633
|
-
continue;
|
|
634
|
-
}
|
|
635
|
-
if (this.seenAckKeys.size > this.ackDedupMaxEntries ||
|
|
636
|
-
now - timestamp > this.ackDedupTtlMs) {
|
|
637
|
-
this.seenAckKeys.delete(candidate);
|
|
638
|
-
this.seenAckOrder.shift();
|
|
639
|
-
continue;
|
|
640
|
-
}
|
|
641
|
-
break;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
_extractAckDedupKey(payload) {
|
|
645
|
-
try {
|
|
646
|
-
const decoded = this.textDecoder.decode(payload);
|
|
647
|
-
const parsed = JSON.parse(decoded);
|
|
648
|
-
const envelopeId = typeof parsed?.id === 'string' ? parsed.id : null;
|
|
649
|
-
const frameType = parsed?.frame?.type;
|
|
650
|
-
if (typeof frameType !== 'string' || frameType !== 'DeliveryAck') {
|
|
651
|
-
return null;
|
|
652
|
-
}
|
|
653
|
-
const refId = parsed.frame?.refId;
|
|
654
|
-
if (typeof refId === 'string' && refId.length > 0) {
|
|
655
|
-
return refId;
|
|
656
|
-
}
|
|
657
|
-
return envelopeId;
|
|
658
|
-
}
|
|
659
|
-
catch (error) {
|
|
660
|
-
logger.debug('broadcast_channel_ack_dedup_parse_failed', {
|
|
661
|
-
channel: this.channelName,
|
|
662
|
-
connector_id: this.connectorId,
|
|
663
|
-
error: error instanceof Error ? error.message : String(error),
|
|
664
|
-
});
|
|
665
|
-
return null;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
495
|
}
|
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.966
|
|
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.966';
|
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.966
|
|
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.966';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9886,11 +9886,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9886
9886
|
ensureBroadcastEnvironment();
|
|
9887
9887
|
super(baseConfig);
|
|
9888
9888
|
this.listenerRegistered = false;
|
|
9889
|
-
this.seenAckKeys = new Map();
|
|
9890
|
-
this.seenAckOrder = [];
|
|
9891
|
-
this.ackDedupTtlMs = 30000;
|
|
9892
|
-
this.ackDedupMaxEntries = 4096;
|
|
9893
|
-
this.textDecoder = new TextDecoder();
|
|
9894
9889
|
this.visibilityChangeListenerRegistered = false;
|
|
9895
9890
|
this.channelName =
|
|
9896
9891
|
typeof config.channelName === 'string' && config.channelName.trim().length > 0
|
|
@@ -9982,9 +9977,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9982
9977
|
connector_id: this.connectorId,
|
|
9983
9978
|
payload_length: payload.byteLength,
|
|
9984
9979
|
});
|
|
9985
|
-
if (this._shouldSkipDuplicateAck(senderNodeId, payload)) {
|
|
9986
|
-
return;
|
|
9987
|
-
}
|
|
9988
9980
|
try {
|
|
9989
9981
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
9990
9982
|
const accepted = this.inbox.tryEnqueue(payload);
|
|
@@ -10088,9 +10080,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10088
10080
|
}
|
|
10089
10081
|
async pushToReceive(rawOrEnvelope) {
|
|
10090
10082
|
const item = this._normalizeInboxItem(rawOrEnvelope);
|
|
10091
|
-
if (this._shouldSkipDuplicateAckFromInboxItem(item)) {
|
|
10092
|
-
return;
|
|
10093
|
-
}
|
|
10094
10083
|
try {
|
|
10095
10084
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
10096
10085
|
const accepted = this.inbox.tryEnqueue(item);
|
|
@@ -10190,8 +10179,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10190
10179
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
10191
10180
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
10192
10181
|
this.inbox.drain(shutdownError);
|
|
10193
|
-
this.seenAckKeys.clear();
|
|
10194
|
-
this.seenAckOrder.length = 0;
|
|
10195
10182
|
}
|
|
10196
10183
|
_normalizeInboxItem(rawOrEnvelope) {
|
|
10197
10184
|
if (rawOrEnvelope instanceof Uint8Array) {
|
|
@@ -10268,125 +10255,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10268
10255
|
...extra,
|
|
10269
10256
|
});
|
|
10270
10257
|
}
|
|
10271
|
-
_shouldSkipDuplicateAck(senderId, payload) {
|
|
10272
|
-
const dedupKey = this._extractAckDedupKey(payload);
|
|
10273
|
-
if (!dedupKey) {
|
|
10274
|
-
return false;
|
|
10275
|
-
}
|
|
10276
|
-
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
10277
|
-
? senderId
|
|
10278
|
-
: undefined;
|
|
10279
|
-
if (normalizedSenderId && normalizedSenderId !== this.localNodeId) {
|
|
10280
|
-
logger$_.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
10281
|
-
channel: this.channelName,
|
|
10282
|
-
connector_id: this.connectorId,
|
|
10283
|
-
sender_id: normalizedSenderId,
|
|
10284
|
-
dedup_key: dedupKey,
|
|
10285
|
-
source: 'listener',
|
|
10286
|
-
});
|
|
10287
|
-
return false;
|
|
10288
|
-
}
|
|
10289
|
-
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10290
|
-
channel: this.channelName,
|
|
10291
|
-
connector_id: this.connectorId,
|
|
10292
|
-
sender_id: normalizedSenderId ?? null,
|
|
10293
|
-
dedup_key: dedupKey,
|
|
10294
|
-
source: 'listener',
|
|
10295
|
-
cache_entries: this.seenAckKeys.size,
|
|
10296
|
-
});
|
|
10297
|
-
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
10298
|
-
}
|
|
10299
|
-
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
10300
|
-
if (item instanceof Uint8Array) {
|
|
10301
|
-
return this._shouldSkipDuplicateAck(undefined, item);
|
|
10302
|
-
}
|
|
10303
|
-
const envelope = this._extractEnvelopeFromInboxItem(item);
|
|
10304
|
-
if (!envelope) {
|
|
10305
|
-
return false;
|
|
10306
|
-
}
|
|
10307
|
-
const frame = envelope.frame;
|
|
10308
|
-
if (!frame || frame.type !== 'DeliveryAck') {
|
|
10309
|
-
return false;
|
|
10310
|
-
}
|
|
10311
|
-
const refId = typeof frame.refId === 'string' && frame.refId.length > 0
|
|
10312
|
-
? frame.refId
|
|
10313
|
-
: null;
|
|
10314
|
-
const dedupKey = refId ?? envelope.id ?? null;
|
|
10315
|
-
if (!dedupKey) {
|
|
10316
|
-
return false;
|
|
10317
|
-
}
|
|
10318
|
-
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
10319
|
-
if (senderId && senderId !== this.localNodeId) {
|
|
10320
|
-
logger$_.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
10321
|
-
channel: this.channelName,
|
|
10322
|
-
connector_id: this.connectorId,
|
|
10323
|
-
sender_id: senderId,
|
|
10324
|
-
dedup_key: dedupKey,
|
|
10325
|
-
source: 'inbox_item',
|
|
10326
|
-
});
|
|
10327
|
-
return false;
|
|
10328
|
-
}
|
|
10329
|
-
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10330
|
-
channel: this.channelName,
|
|
10331
|
-
connector_id: this.connectorId,
|
|
10332
|
-
sender_id: senderId ?? null,
|
|
10333
|
-
dedup_key: dedupKey,
|
|
10334
|
-
source: 'inbox_item',
|
|
10335
|
-
cache_entries: this.seenAckKeys.size,
|
|
10336
|
-
});
|
|
10337
|
-
return this._checkDuplicateAck(dedupKey, senderId);
|
|
10338
|
-
}
|
|
10339
|
-
_checkDuplicateAck(dedupKey, senderId) {
|
|
10340
|
-
const now = Date.now();
|
|
10341
|
-
const lastSeen = this.seenAckKeys.get(dedupKey);
|
|
10342
|
-
if (lastSeen && now - lastSeen < this.ackDedupTtlMs) {
|
|
10343
|
-
logger$_.debug('broadcast_channel_duplicate_ack_suppressed', {
|
|
10344
|
-
channel: this.channelName,
|
|
10345
|
-
connector_id: this.connectorId,
|
|
10346
|
-
sender_id: senderId ?? null,
|
|
10347
|
-
dedup_key: dedupKey,
|
|
10348
|
-
age_ms: now - lastSeen,
|
|
10349
|
-
ttl_ms: this.ackDedupTtlMs,
|
|
10350
|
-
cache_entries: this.seenAckKeys.size,
|
|
10351
|
-
});
|
|
10352
|
-
return true;
|
|
10353
|
-
}
|
|
10354
|
-
this.seenAckKeys.set(dedupKey, now);
|
|
10355
|
-
this.seenAckOrder.push(dedupKey);
|
|
10356
|
-
logger$_.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
10357
|
-
channel: this.channelName,
|
|
10358
|
-
connector_id: this.connectorId,
|
|
10359
|
-
sender_id: senderId ?? null,
|
|
10360
|
-
dedup_key: dedupKey,
|
|
10361
|
-
cache_entries: this.seenAckKeys.size,
|
|
10362
|
-
});
|
|
10363
|
-
this._trimSeenAcks(now);
|
|
10364
|
-
return false;
|
|
10365
|
-
}
|
|
10366
|
-
_extractEnvelopeFromInboxItem(item) {
|
|
10367
|
-
if (!item || typeof item !== 'object') {
|
|
10368
|
-
return null;
|
|
10369
|
-
}
|
|
10370
|
-
if ('envelope' in item) {
|
|
10371
|
-
return item.envelope;
|
|
10372
|
-
}
|
|
10373
|
-
if ('frame' in item) {
|
|
10374
|
-
return item;
|
|
10375
|
-
}
|
|
10376
|
-
return null;
|
|
10377
|
-
}
|
|
10378
|
-
_extractSenderIdFromInboxItem(item) {
|
|
10379
|
-
if (!item || typeof item !== 'object') {
|
|
10380
|
-
return undefined;
|
|
10381
|
-
}
|
|
10382
|
-
if ('context' in item) {
|
|
10383
|
-
const context = item.context;
|
|
10384
|
-
if (context && typeof context.fromSystemId === 'string') {
|
|
10385
|
-
return context.fromSystemId;
|
|
10386
|
-
}
|
|
10387
|
-
}
|
|
10388
|
-
return undefined;
|
|
10389
|
-
}
|
|
10390
10258
|
/**
|
|
10391
10259
|
* Override start() to check initial visibility state
|
|
10392
10260
|
*/
|
|
@@ -10440,47 +10308,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10440
10308
|
target_mode: 'wildcard',
|
|
10441
10309
|
});
|
|
10442
10310
|
}
|
|
10443
|
-
_trimSeenAcks(now) {
|
|
10444
|
-
while (this.seenAckOrder.length > 0) {
|
|
10445
|
-
const candidate = this.seenAckOrder[0];
|
|
10446
|
-
const timestamp = this.seenAckKeys.get(candidate);
|
|
10447
|
-
if (timestamp === undefined) {
|
|
10448
|
-
this.seenAckOrder.shift();
|
|
10449
|
-
continue;
|
|
10450
|
-
}
|
|
10451
|
-
if (this.seenAckKeys.size > this.ackDedupMaxEntries ||
|
|
10452
|
-
now - timestamp > this.ackDedupTtlMs) {
|
|
10453
|
-
this.seenAckKeys.delete(candidate);
|
|
10454
|
-
this.seenAckOrder.shift();
|
|
10455
|
-
continue;
|
|
10456
|
-
}
|
|
10457
|
-
break;
|
|
10458
|
-
}
|
|
10459
|
-
}
|
|
10460
|
-
_extractAckDedupKey(payload) {
|
|
10461
|
-
try {
|
|
10462
|
-
const decoded = this.textDecoder.decode(payload);
|
|
10463
|
-
const parsed = JSON.parse(decoded);
|
|
10464
|
-
const envelopeId = typeof parsed?.id === 'string' ? parsed.id : null;
|
|
10465
|
-
const frameType = parsed?.frame?.type;
|
|
10466
|
-
if (typeof frameType !== 'string' || frameType !== 'DeliveryAck') {
|
|
10467
|
-
return null;
|
|
10468
|
-
}
|
|
10469
|
-
const refId = parsed.frame?.refId;
|
|
10470
|
-
if (typeof refId === 'string' && refId.length > 0) {
|
|
10471
|
-
return refId;
|
|
10472
|
-
}
|
|
10473
|
-
return envelopeId;
|
|
10474
|
-
}
|
|
10475
|
-
catch (error) {
|
|
10476
|
-
logger$_.debug('broadcast_channel_ack_dedup_parse_failed', {
|
|
10477
|
-
channel: this.channelName,
|
|
10478
|
-
connector_id: this.connectorId,
|
|
10479
|
-
error: error instanceof Error ? error.message : String(error),
|
|
10480
|
-
});
|
|
10481
|
-
return null;
|
|
10482
|
-
}
|
|
10483
|
-
}
|
|
10484
10311
|
};
|
|
10485
10312
|
|
|
10486
10313
|
const ERROR_MESSAGE = 'BroadcastChannelConnector is browser-only and requires BroadcastChannel support';
|
package/dist/node/index.mjs
CHANGED
|
@@ -13,12 +13,12 @@ import fastify from 'fastify';
|
|
|
13
13
|
import websocketPlugin from '@fastify/websocket';
|
|
14
14
|
|
|
15
15
|
// This file is auto-generated during build - do not edit manually
|
|
16
|
-
// Generated from package.json version: 0.3.5-test.
|
|
16
|
+
// Generated from package.json version: 0.3.5-test.966
|
|
17
17
|
/**
|
|
18
18
|
* The package version, injected at build time.
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
const VERSION = '0.3.5-test.
|
|
21
|
+
const VERSION = '0.3.5-test.966';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9885,11 +9885,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9885
9885
|
ensureBroadcastEnvironment();
|
|
9886
9886
|
super(baseConfig);
|
|
9887
9887
|
this.listenerRegistered = false;
|
|
9888
|
-
this.seenAckKeys = new Map();
|
|
9889
|
-
this.seenAckOrder = [];
|
|
9890
|
-
this.ackDedupTtlMs = 30000;
|
|
9891
|
-
this.ackDedupMaxEntries = 4096;
|
|
9892
|
-
this.textDecoder = new TextDecoder();
|
|
9893
9888
|
this.visibilityChangeListenerRegistered = false;
|
|
9894
9889
|
this.channelName =
|
|
9895
9890
|
typeof config.channelName === 'string' && config.channelName.trim().length > 0
|
|
@@ -9981,9 +9976,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9981
9976
|
connector_id: this.connectorId,
|
|
9982
9977
|
payload_length: payload.byteLength,
|
|
9983
9978
|
});
|
|
9984
|
-
if (this._shouldSkipDuplicateAck(senderNodeId, payload)) {
|
|
9985
|
-
return;
|
|
9986
|
-
}
|
|
9987
9979
|
try {
|
|
9988
9980
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
9989
9981
|
const accepted = this.inbox.tryEnqueue(payload);
|
|
@@ -10087,9 +10079,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10087
10079
|
}
|
|
10088
10080
|
async pushToReceive(rawOrEnvelope) {
|
|
10089
10081
|
const item = this._normalizeInboxItem(rawOrEnvelope);
|
|
10090
|
-
if (this._shouldSkipDuplicateAckFromInboxItem(item)) {
|
|
10091
|
-
return;
|
|
10092
|
-
}
|
|
10093
10082
|
try {
|
|
10094
10083
|
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
10095
10084
|
const accepted = this.inbox.tryEnqueue(item);
|
|
@@ -10189,8 +10178,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10189
10178
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
10190
10179
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
10191
10180
|
this.inbox.drain(shutdownError);
|
|
10192
|
-
this.seenAckKeys.clear();
|
|
10193
|
-
this.seenAckOrder.length = 0;
|
|
10194
10181
|
}
|
|
10195
10182
|
_normalizeInboxItem(rawOrEnvelope) {
|
|
10196
10183
|
if (rawOrEnvelope instanceof Uint8Array) {
|
|
@@ -10267,125 +10254,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10267
10254
|
...extra,
|
|
10268
10255
|
});
|
|
10269
10256
|
}
|
|
10270
|
-
_shouldSkipDuplicateAck(senderId, payload) {
|
|
10271
|
-
const dedupKey = this._extractAckDedupKey(payload);
|
|
10272
|
-
if (!dedupKey) {
|
|
10273
|
-
return false;
|
|
10274
|
-
}
|
|
10275
|
-
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
10276
|
-
? senderId
|
|
10277
|
-
: undefined;
|
|
10278
|
-
if (normalizedSenderId && normalizedSenderId !== this.localNodeId) {
|
|
10279
|
-
logger$_.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
10280
|
-
channel: this.channelName,
|
|
10281
|
-
connector_id: this.connectorId,
|
|
10282
|
-
sender_id: normalizedSenderId,
|
|
10283
|
-
dedup_key: dedupKey,
|
|
10284
|
-
source: 'listener',
|
|
10285
|
-
});
|
|
10286
|
-
return false;
|
|
10287
|
-
}
|
|
10288
|
-
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10289
|
-
channel: this.channelName,
|
|
10290
|
-
connector_id: this.connectorId,
|
|
10291
|
-
sender_id: normalizedSenderId ?? null,
|
|
10292
|
-
dedup_key: dedupKey,
|
|
10293
|
-
source: 'listener',
|
|
10294
|
-
cache_entries: this.seenAckKeys.size,
|
|
10295
|
-
});
|
|
10296
|
-
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
10297
|
-
}
|
|
10298
|
-
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
10299
|
-
if (item instanceof Uint8Array) {
|
|
10300
|
-
return this._shouldSkipDuplicateAck(undefined, item);
|
|
10301
|
-
}
|
|
10302
|
-
const envelope = this._extractEnvelopeFromInboxItem(item);
|
|
10303
|
-
if (!envelope) {
|
|
10304
|
-
return false;
|
|
10305
|
-
}
|
|
10306
|
-
const frame = envelope.frame;
|
|
10307
|
-
if (!frame || frame.type !== 'DeliveryAck') {
|
|
10308
|
-
return false;
|
|
10309
|
-
}
|
|
10310
|
-
const refId = typeof frame.refId === 'string' && frame.refId.length > 0
|
|
10311
|
-
? frame.refId
|
|
10312
|
-
: null;
|
|
10313
|
-
const dedupKey = refId ?? envelope.id ?? null;
|
|
10314
|
-
if (!dedupKey) {
|
|
10315
|
-
return false;
|
|
10316
|
-
}
|
|
10317
|
-
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
10318
|
-
if (senderId && senderId !== this.localNodeId) {
|
|
10319
|
-
logger$_.debug('broadcast_channel_duplicate_ack_bypass_non_self', {
|
|
10320
|
-
channel: this.channelName,
|
|
10321
|
-
connector_id: this.connectorId,
|
|
10322
|
-
sender_id: senderId,
|
|
10323
|
-
dedup_key: dedupKey,
|
|
10324
|
-
source: 'inbox_item',
|
|
10325
|
-
});
|
|
10326
|
-
return false;
|
|
10327
|
-
}
|
|
10328
|
-
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10329
|
-
channel: this.channelName,
|
|
10330
|
-
connector_id: this.connectorId,
|
|
10331
|
-
sender_id: senderId ?? null,
|
|
10332
|
-
dedup_key: dedupKey,
|
|
10333
|
-
source: 'inbox_item',
|
|
10334
|
-
cache_entries: this.seenAckKeys.size,
|
|
10335
|
-
});
|
|
10336
|
-
return this._checkDuplicateAck(dedupKey, senderId);
|
|
10337
|
-
}
|
|
10338
|
-
_checkDuplicateAck(dedupKey, senderId) {
|
|
10339
|
-
const now = Date.now();
|
|
10340
|
-
const lastSeen = this.seenAckKeys.get(dedupKey);
|
|
10341
|
-
if (lastSeen && now - lastSeen < this.ackDedupTtlMs) {
|
|
10342
|
-
logger$_.debug('broadcast_channel_duplicate_ack_suppressed', {
|
|
10343
|
-
channel: this.channelName,
|
|
10344
|
-
connector_id: this.connectorId,
|
|
10345
|
-
sender_id: senderId ?? null,
|
|
10346
|
-
dedup_key: dedupKey,
|
|
10347
|
-
age_ms: now - lastSeen,
|
|
10348
|
-
ttl_ms: this.ackDedupTtlMs,
|
|
10349
|
-
cache_entries: this.seenAckKeys.size,
|
|
10350
|
-
});
|
|
10351
|
-
return true;
|
|
10352
|
-
}
|
|
10353
|
-
this.seenAckKeys.set(dedupKey, now);
|
|
10354
|
-
this.seenAckOrder.push(dedupKey);
|
|
10355
|
-
logger$_.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
10356
|
-
channel: this.channelName,
|
|
10357
|
-
connector_id: this.connectorId,
|
|
10358
|
-
sender_id: senderId ?? null,
|
|
10359
|
-
dedup_key: dedupKey,
|
|
10360
|
-
cache_entries: this.seenAckKeys.size,
|
|
10361
|
-
});
|
|
10362
|
-
this._trimSeenAcks(now);
|
|
10363
|
-
return false;
|
|
10364
|
-
}
|
|
10365
|
-
_extractEnvelopeFromInboxItem(item) {
|
|
10366
|
-
if (!item || typeof item !== 'object') {
|
|
10367
|
-
return null;
|
|
10368
|
-
}
|
|
10369
|
-
if ('envelope' in item) {
|
|
10370
|
-
return item.envelope;
|
|
10371
|
-
}
|
|
10372
|
-
if ('frame' in item) {
|
|
10373
|
-
return item;
|
|
10374
|
-
}
|
|
10375
|
-
return null;
|
|
10376
|
-
}
|
|
10377
|
-
_extractSenderIdFromInboxItem(item) {
|
|
10378
|
-
if (!item || typeof item !== 'object') {
|
|
10379
|
-
return undefined;
|
|
10380
|
-
}
|
|
10381
|
-
if ('context' in item) {
|
|
10382
|
-
const context = item.context;
|
|
10383
|
-
if (context && typeof context.fromSystemId === 'string') {
|
|
10384
|
-
return context.fromSystemId;
|
|
10385
|
-
}
|
|
10386
|
-
}
|
|
10387
|
-
return undefined;
|
|
10388
|
-
}
|
|
10389
10257
|
/**
|
|
10390
10258
|
* Override start() to check initial visibility state
|
|
10391
10259
|
*/
|
|
@@ -10439,47 +10307,6 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10439
10307
|
target_mode: 'wildcard',
|
|
10440
10308
|
});
|
|
10441
10309
|
}
|
|
10442
|
-
_trimSeenAcks(now) {
|
|
10443
|
-
while (this.seenAckOrder.length > 0) {
|
|
10444
|
-
const candidate = this.seenAckOrder[0];
|
|
10445
|
-
const timestamp = this.seenAckKeys.get(candidate);
|
|
10446
|
-
if (timestamp === undefined) {
|
|
10447
|
-
this.seenAckOrder.shift();
|
|
10448
|
-
continue;
|
|
10449
|
-
}
|
|
10450
|
-
if (this.seenAckKeys.size > this.ackDedupMaxEntries ||
|
|
10451
|
-
now - timestamp > this.ackDedupTtlMs) {
|
|
10452
|
-
this.seenAckKeys.delete(candidate);
|
|
10453
|
-
this.seenAckOrder.shift();
|
|
10454
|
-
continue;
|
|
10455
|
-
}
|
|
10456
|
-
break;
|
|
10457
|
-
}
|
|
10458
|
-
}
|
|
10459
|
-
_extractAckDedupKey(payload) {
|
|
10460
|
-
try {
|
|
10461
|
-
const decoded = this.textDecoder.decode(payload);
|
|
10462
|
-
const parsed = JSON.parse(decoded);
|
|
10463
|
-
const envelopeId = typeof parsed?.id === 'string' ? parsed.id : null;
|
|
10464
|
-
const frameType = parsed?.frame?.type;
|
|
10465
|
-
if (typeof frameType !== 'string' || frameType !== 'DeliveryAck') {
|
|
10466
|
-
return null;
|
|
10467
|
-
}
|
|
10468
|
-
const refId = parsed.frame?.refId;
|
|
10469
|
-
if (typeof refId === 'string' && refId.length > 0) {
|
|
10470
|
-
return refId;
|
|
10471
|
-
}
|
|
10472
|
-
return envelopeId;
|
|
10473
|
-
}
|
|
10474
|
-
catch (error) {
|
|
10475
|
-
logger$_.debug('broadcast_channel_ack_dedup_parse_failed', {
|
|
10476
|
-
channel: this.channelName,
|
|
10477
|
-
connector_id: this.connectorId,
|
|
10478
|
-
error: error instanceof Error ? error.message : String(error),
|
|
10479
|
-
});
|
|
10480
|
-
return null;
|
|
10481
|
-
}
|
|
10482
|
-
}
|
|
10483
10310
|
};
|
|
10484
10311
|
|
|
10485
10312
|
const ERROR_MESSAGE = 'BroadcastChannelConnector is browser-only and requires BroadcastChannel support';
|