@naylence/runtime 0.3.5-test.958 → 0.3.5-test.960
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 +76 -25
- package/dist/browser/index.mjs +76 -25
- package/dist/cjs/naylence/fame/connector/base-async-connector.js +40 -2
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +26 -0
- package/dist/cjs/naylence/fame/connector/websocket-connector.js +0 -3
- package/dist/cjs/naylence/fame/util/lock.js +8 -18
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/base-async-connector.js +40 -2
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +26 -0
- package/dist/esm/naylence/fame/connector/websocket-connector.js +0 -3
- package/dist/esm/naylence/fame/util/lock.js +8 -18
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +76 -25
- package/dist/node/index.mjs +76 -25
- package/dist/node/node.cjs +76 -25
- package/dist/node/node.mjs +76 -25
- package/dist/types/naylence/fame/util/lock.d.ts +2 -3
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/browser/index.cjs
CHANGED
|
@@ -98,12 +98,12 @@ installProcessEnvShim();
|
|
|
98
98
|
// --- END ENV SHIM ---
|
|
99
99
|
|
|
100
100
|
// This file is auto-generated during build - do not edit manually
|
|
101
|
-
// Generated from package.json version: 0.3.5-test.
|
|
101
|
+
// Generated from package.json version: 0.3.5-test.960
|
|
102
102
|
/**
|
|
103
103
|
* The package version, injected at build time.
|
|
104
104
|
* @internal
|
|
105
105
|
*/
|
|
106
|
-
const VERSION = '0.3.5-test.
|
|
106
|
+
const VERSION = '0.3.5-test.960';
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -1358,38 +1358,28 @@ class TaskSpawner {
|
|
|
1358
1358
|
}
|
|
1359
1359
|
}
|
|
1360
1360
|
|
|
1361
|
-
// import { getLogger } from './logging.js';
|
|
1362
|
-
// const logger = getLogger('naylence.fame.util.lock');
|
|
1363
1361
|
class AsyncLock {
|
|
1364
1362
|
constructor() {
|
|
1365
|
-
this.
|
|
1363
|
+
this.tail = Promise.resolve();
|
|
1366
1364
|
}
|
|
1367
|
-
async
|
|
1368
|
-
const currentQueue = this.queue;
|
|
1365
|
+
async runExclusive(operation) {
|
|
1369
1366
|
let release;
|
|
1370
|
-
const
|
|
1367
|
+
const next = new Promise((resolve) => {
|
|
1371
1368
|
release = resolve;
|
|
1372
1369
|
});
|
|
1373
|
-
|
|
1374
|
-
this.
|
|
1375
|
-
|
|
1376
|
-
// logger.debug('waiting_for_lock');
|
|
1377
|
-
await currentQueue;
|
|
1378
|
-
// logger.debug('lock_acquired');
|
|
1370
|
+
const previous = this.tail;
|
|
1371
|
+
this.tail = previous.then(() => next, () => next);
|
|
1372
|
+
await previous;
|
|
1379
1373
|
try {
|
|
1380
|
-
return await
|
|
1374
|
+
return await operation();
|
|
1381
1375
|
}
|
|
1382
1376
|
finally {
|
|
1383
1377
|
release();
|
|
1384
|
-
// logger.debug('lock_released');
|
|
1385
1378
|
}
|
|
1386
1379
|
}
|
|
1387
|
-
async runExclusive(task) {
|
|
1388
|
-
return this.acquire(task);
|
|
1389
|
-
}
|
|
1390
1380
|
}
|
|
1391
1381
|
async function withLock(lock, operation) {
|
|
1392
|
-
return await lock.
|
|
1382
|
+
return await lock.runExclusive(operation);
|
|
1393
1383
|
}
|
|
1394
1384
|
|
|
1395
1385
|
/**
|
|
@@ -9686,11 +9676,31 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9686
9676
|
* Emit credit update if flow control needs refill
|
|
9687
9677
|
*/
|
|
9688
9678
|
async _maybeEmitCredit(flowId, traceId) {
|
|
9689
|
-
|
|
9679
|
+
const remainingCredits = this._flowCtrl.getCredits(flowId);
|
|
9680
|
+
const needsRefill = this._flowCtrl.needsRefill(flowId);
|
|
9681
|
+
logger$$.debug('maybe_emit_credit_check', {
|
|
9682
|
+
connector_id: this._connectorFlowId,
|
|
9683
|
+
flow_id: flowId,
|
|
9684
|
+
trace_id: traceId ?? null,
|
|
9685
|
+
remaining_credits: remainingCredits,
|
|
9686
|
+
low_watermark: this._flowCtrl instanceof FlowController
|
|
9687
|
+
? this._flowCtrl.lowWatermark
|
|
9688
|
+
: null,
|
|
9689
|
+
initial_window: this._initialWindow,
|
|
9690
|
+
needs_refill: needsRefill,
|
|
9691
|
+
});
|
|
9692
|
+
if (!needsRefill) {
|
|
9690
9693
|
return;
|
|
9691
9694
|
}
|
|
9692
9695
|
const delta = this._initialWindow;
|
|
9693
9696
|
this._flowCtrl.addCredits(flowId, delta);
|
|
9697
|
+
logger$$.debug('maybe_emit_credit_emit', {
|
|
9698
|
+
connector_id: this._connectorFlowId,
|
|
9699
|
+
flow_id: flowId,
|
|
9700
|
+
trace_id: traceId ?? null,
|
|
9701
|
+
emitted_credits: delta,
|
|
9702
|
+
post_emit_balance: this._flowCtrl.getCredits(flowId),
|
|
9703
|
+
});
|
|
9694
9704
|
const ackEnv = core.createFameEnvelope({
|
|
9695
9705
|
...(traceId && { traceId }),
|
|
9696
9706
|
flowId,
|
|
@@ -9702,7 +9712,25 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9702
9712
|
},
|
|
9703
9713
|
flags: core.FlowFlags.ACK,
|
|
9704
9714
|
});
|
|
9705
|
-
|
|
9715
|
+
try {
|
|
9716
|
+
await this.send(ackEnv);
|
|
9717
|
+
logger$$.debug('maybe_emit_credit_sent', {
|
|
9718
|
+
connector_id: this._connectorFlowId,
|
|
9719
|
+
flow_id: flowId,
|
|
9720
|
+
trace_id: traceId ?? null,
|
|
9721
|
+
credits_acknowledged: delta,
|
|
9722
|
+
});
|
|
9723
|
+
}
|
|
9724
|
+
catch (error) {
|
|
9725
|
+
logger$$.error('maybe_emit_credit_send_failed', {
|
|
9726
|
+
connector_id: this._connectorFlowId,
|
|
9727
|
+
flow_id: flowId,
|
|
9728
|
+
trace_id: traceId ?? null,
|
|
9729
|
+
credits_attempted: delta,
|
|
9730
|
+
error: error instanceof Error ? error.message : String(error),
|
|
9731
|
+
});
|
|
9732
|
+
throw error;
|
|
9733
|
+
}
|
|
9706
9734
|
}
|
|
9707
9735
|
// ---------------------------------------------------------------------
|
|
9708
9736
|
// Shutdown Management
|
|
@@ -10233,6 +10261,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10233
10261
|
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
10234
10262
|
? senderId
|
|
10235
10263
|
: undefined;
|
|
10264
|
+
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10265
|
+
channel: this.channelName,
|
|
10266
|
+
connector_id: this.connectorId,
|
|
10267
|
+
sender_id: normalizedSenderId ?? null,
|
|
10268
|
+
dedup_key: dedupKey,
|
|
10269
|
+
source: 'listener',
|
|
10270
|
+
cache_entries: this.seenAckKeys.size,
|
|
10271
|
+
});
|
|
10236
10272
|
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
10237
10273
|
}
|
|
10238
10274
|
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
@@ -10255,6 +10291,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10255
10291
|
return false;
|
|
10256
10292
|
}
|
|
10257
10293
|
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
10294
|
+
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10295
|
+
channel: this.channelName,
|
|
10296
|
+
connector_id: this.connectorId,
|
|
10297
|
+
sender_id: senderId ?? null,
|
|
10298
|
+
dedup_key: dedupKey,
|
|
10299
|
+
source: 'inbox_item',
|
|
10300
|
+
cache_entries: this.seenAckKeys.size,
|
|
10301
|
+
});
|
|
10258
10302
|
return this._checkDuplicateAck(dedupKey, senderId);
|
|
10259
10303
|
}
|
|
10260
10304
|
_checkDuplicateAck(dedupKey, senderId) {
|
|
@@ -10266,11 +10310,21 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10266
10310
|
connector_id: this.connectorId,
|
|
10267
10311
|
sender_id: senderId ?? null,
|
|
10268
10312
|
dedup_key: dedupKey,
|
|
10313
|
+
age_ms: now - lastSeen,
|
|
10314
|
+
ttl_ms: this.ackDedupTtlMs,
|
|
10315
|
+
cache_entries: this.seenAckKeys.size,
|
|
10269
10316
|
});
|
|
10270
10317
|
return true;
|
|
10271
10318
|
}
|
|
10272
10319
|
this.seenAckKeys.set(dedupKey, now);
|
|
10273
10320
|
this.seenAckOrder.push(dedupKey);
|
|
10321
|
+
logger$_.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
10322
|
+
channel: this.channelName,
|
|
10323
|
+
connector_id: this.connectorId,
|
|
10324
|
+
sender_id: senderId ?? null,
|
|
10325
|
+
dedup_key: dedupKey,
|
|
10326
|
+
cache_entries: this.seenAckKeys.size,
|
|
10327
|
+
});
|
|
10274
10328
|
this._trimSeenAcks(now);
|
|
10275
10329
|
return false;
|
|
10276
10330
|
}
|
|
@@ -19981,9 +20035,6 @@ class WebSocketConnector extends BaseAsyncConnector {
|
|
|
19981
20035
|
// Browser WebSocket or Node.js ws client
|
|
19982
20036
|
this._websocket.send(data);
|
|
19983
20037
|
}
|
|
19984
|
-
logger$H.debug('websocket_sent_bytes', {
|
|
19985
|
-
byte_length: data.length,
|
|
19986
|
-
});
|
|
19987
20038
|
}
|
|
19988
20039
|
catch (error) {
|
|
19989
20040
|
// Handle WebSocket disconnection errors
|
package/dist/browser/index.mjs
CHANGED
|
@@ -96,12 +96,12 @@ installProcessEnvShim();
|
|
|
96
96
|
// --- END ENV SHIM ---
|
|
97
97
|
|
|
98
98
|
// This file is auto-generated during build - do not edit manually
|
|
99
|
-
// Generated from package.json version: 0.3.5-test.
|
|
99
|
+
// Generated from package.json version: 0.3.5-test.960
|
|
100
100
|
/**
|
|
101
101
|
* The package version, injected at build time.
|
|
102
102
|
* @internal
|
|
103
103
|
*/
|
|
104
|
-
const VERSION = '0.3.5-test.
|
|
104
|
+
const VERSION = '0.3.5-test.960';
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -1356,38 +1356,28 @@ class TaskSpawner {
|
|
|
1356
1356
|
}
|
|
1357
1357
|
}
|
|
1358
1358
|
|
|
1359
|
-
// import { getLogger } from './logging.js';
|
|
1360
|
-
// const logger = getLogger('naylence.fame.util.lock');
|
|
1361
1359
|
class AsyncLock {
|
|
1362
1360
|
constructor() {
|
|
1363
|
-
this.
|
|
1361
|
+
this.tail = Promise.resolve();
|
|
1364
1362
|
}
|
|
1365
|
-
async
|
|
1366
|
-
const currentQueue = this.queue;
|
|
1363
|
+
async runExclusive(operation) {
|
|
1367
1364
|
let release;
|
|
1368
|
-
const
|
|
1365
|
+
const next = new Promise((resolve) => {
|
|
1369
1366
|
release = resolve;
|
|
1370
1367
|
});
|
|
1371
|
-
|
|
1372
|
-
this.
|
|
1373
|
-
|
|
1374
|
-
// logger.debug('waiting_for_lock');
|
|
1375
|
-
await currentQueue;
|
|
1376
|
-
// logger.debug('lock_acquired');
|
|
1368
|
+
const previous = this.tail;
|
|
1369
|
+
this.tail = previous.then(() => next, () => next);
|
|
1370
|
+
await previous;
|
|
1377
1371
|
try {
|
|
1378
|
-
return await
|
|
1372
|
+
return await operation();
|
|
1379
1373
|
}
|
|
1380
1374
|
finally {
|
|
1381
1375
|
release();
|
|
1382
|
-
// logger.debug('lock_released');
|
|
1383
1376
|
}
|
|
1384
1377
|
}
|
|
1385
|
-
async runExclusive(task) {
|
|
1386
|
-
return this.acquire(task);
|
|
1387
|
-
}
|
|
1388
1378
|
}
|
|
1389
1379
|
async function withLock(lock, operation) {
|
|
1390
|
-
return await lock.
|
|
1380
|
+
return await lock.runExclusive(operation);
|
|
1391
1381
|
}
|
|
1392
1382
|
|
|
1393
1383
|
/**
|
|
@@ -9684,11 +9674,31 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9684
9674
|
* Emit credit update if flow control needs refill
|
|
9685
9675
|
*/
|
|
9686
9676
|
async _maybeEmitCredit(flowId, traceId) {
|
|
9687
|
-
|
|
9677
|
+
const remainingCredits = this._flowCtrl.getCredits(flowId);
|
|
9678
|
+
const needsRefill = this._flowCtrl.needsRefill(flowId);
|
|
9679
|
+
logger$$.debug('maybe_emit_credit_check', {
|
|
9680
|
+
connector_id: this._connectorFlowId,
|
|
9681
|
+
flow_id: flowId,
|
|
9682
|
+
trace_id: traceId ?? null,
|
|
9683
|
+
remaining_credits: remainingCredits,
|
|
9684
|
+
low_watermark: this._flowCtrl instanceof FlowController
|
|
9685
|
+
? this._flowCtrl.lowWatermark
|
|
9686
|
+
: null,
|
|
9687
|
+
initial_window: this._initialWindow,
|
|
9688
|
+
needs_refill: needsRefill,
|
|
9689
|
+
});
|
|
9690
|
+
if (!needsRefill) {
|
|
9688
9691
|
return;
|
|
9689
9692
|
}
|
|
9690
9693
|
const delta = this._initialWindow;
|
|
9691
9694
|
this._flowCtrl.addCredits(flowId, delta);
|
|
9695
|
+
logger$$.debug('maybe_emit_credit_emit', {
|
|
9696
|
+
connector_id: this._connectorFlowId,
|
|
9697
|
+
flow_id: flowId,
|
|
9698
|
+
trace_id: traceId ?? null,
|
|
9699
|
+
emitted_credits: delta,
|
|
9700
|
+
post_emit_balance: this._flowCtrl.getCredits(flowId),
|
|
9701
|
+
});
|
|
9692
9702
|
const ackEnv = createFameEnvelope({
|
|
9693
9703
|
...(traceId && { traceId }),
|
|
9694
9704
|
flowId,
|
|
@@ -9700,7 +9710,25 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9700
9710
|
},
|
|
9701
9711
|
flags: FlowFlags.ACK,
|
|
9702
9712
|
});
|
|
9703
|
-
|
|
9713
|
+
try {
|
|
9714
|
+
await this.send(ackEnv);
|
|
9715
|
+
logger$$.debug('maybe_emit_credit_sent', {
|
|
9716
|
+
connector_id: this._connectorFlowId,
|
|
9717
|
+
flow_id: flowId,
|
|
9718
|
+
trace_id: traceId ?? null,
|
|
9719
|
+
credits_acknowledged: delta,
|
|
9720
|
+
});
|
|
9721
|
+
}
|
|
9722
|
+
catch (error) {
|
|
9723
|
+
logger$$.error('maybe_emit_credit_send_failed', {
|
|
9724
|
+
connector_id: this._connectorFlowId,
|
|
9725
|
+
flow_id: flowId,
|
|
9726
|
+
trace_id: traceId ?? null,
|
|
9727
|
+
credits_attempted: delta,
|
|
9728
|
+
error: error instanceof Error ? error.message : String(error),
|
|
9729
|
+
});
|
|
9730
|
+
throw error;
|
|
9731
|
+
}
|
|
9704
9732
|
}
|
|
9705
9733
|
// ---------------------------------------------------------------------
|
|
9706
9734
|
// Shutdown Management
|
|
@@ -10231,6 +10259,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10231
10259
|
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
10232
10260
|
? senderId
|
|
10233
10261
|
: undefined;
|
|
10262
|
+
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10263
|
+
channel: this.channelName,
|
|
10264
|
+
connector_id: this.connectorId,
|
|
10265
|
+
sender_id: normalizedSenderId ?? null,
|
|
10266
|
+
dedup_key: dedupKey,
|
|
10267
|
+
source: 'listener',
|
|
10268
|
+
cache_entries: this.seenAckKeys.size,
|
|
10269
|
+
});
|
|
10234
10270
|
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
10235
10271
|
}
|
|
10236
10272
|
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
@@ -10253,6 +10289,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10253
10289
|
return false;
|
|
10254
10290
|
}
|
|
10255
10291
|
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
10292
|
+
logger$_.debug('broadcast_channel_duplicate_ack_check', {
|
|
10293
|
+
channel: this.channelName,
|
|
10294
|
+
connector_id: this.connectorId,
|
|
10295
|
+
sender_id: senderId ?? null,
|
|
10296
|
+
dedup_key: dedupKey,
|
|
10297
|
+
source: 'inbox_item',
|
|
10298
|
+
cache_entries: this.seenAckKeys.size,
|
|
10299
|
+
});
|
|
10256
10300
|
return this._checkDuplicateAck(dedupKey, senderId);
|
|
10257
10301
|
}
|
|
10258
10302
|
_checkDuplicateAck(dedupKey, senderId) {
|
|
@@ -10264,11 +10308,21 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10264
10308
|
connector_id: this.connectorId,
|
|
10265
10309
|
sender_id: senderId ?? null,
|
|
10266
10310
|
dedup_key: dedupKey,
|
|
10311
|
+
age_ms: now - lastSeen,
|
|
10312
|
+
ttl_ms: this.ackDedupTtlMs,
|
|
10313
|
+
cache_entries: this.seenAckKeys.size,
|
|
10267
10314
|
});
|
|
10268
10315
|
return true;
|
|
10269
10316
|
}
|
|
10270
10317
|
this.seenAckKeys.set(dedupKey, now);
|
|
10271
10318
|
this.seenAckOrder.push(dedupKey);
|
|
10319
|
+
logger$_.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
10320
|
+
channel: this.channelName,
|
|
10321
|
+
connector_id: this.connectorId,
|
|
10322
|
+
sender_id: senderId ?? null,
|
|
10323
|
+
dedup_key: dedupKey,
|
|
10324
|
+
cache_entries: this.seenAckKeys.size,
|
|
10325
|
+
});
|
|
10272
10326
|
this._trimSeenAcks(now);
|
|
10273
10327
|
return false;
|
|
10274
10328
|
}
|
|
@@ -19979,9 +20033,6 @@ class WebSocketConnector extends BaseAsyncConnector {
|
|
|
19979
20033
|
// Browser WebSocket or Node.js ws client
|
|
19980
20034
|
this._websocket.send(data);
|
|
19981
20035
|
}
|
|
19982
|
-
logger$H.debug('websocket_sent_bytes', {
|
|
19983
|
-
byte_length: data.length,
|
|
19984
|
-
});
|
|
19985
20036
|
}
|
|
19986
20037
|
catch (error) {
|
|
19987
20038
|
// Handle WebSocket disconnection errors
|
|
@@ -509,11 +509,31 @@ class BaseAsyncConnector extends task_spawner_js_1.TaskSpawner {
|
|
|
509
509
|
* Emit credit update if flow control needs refill
|
|
510
510
|
*/
|
|
511
511
|
async _maybeEmitCredit(flowId, traceId) {
|
|
512
|
-
|
|
512
|
+
const remainingCredits = this._flowCtrl.getCredits(flowId);
|
|
513
|
+
const needsRefill = this._flowCtrl.needsRefill(flowId);
|
|
514
|
+
logger.debug('maybe_emit_credit_check', {
|
|
515
|
+
connector_id: this._connectorFlowId,
|
|
516
|
+
flow_id: flowId,
|
|
517
|
+
trace_id: traceId ?? null,
|
|
518
|
+
remaining_credits: remainingCredits,
|
|
519
|
+
low_watermark: this._flowCtrl instanceof flow_controller_js_1.FlowController
|
|
520
|
+
? this._flowCtrl.lowWatermark
|
|
521
|
+
: null,
|
|
522
|
+
initial_window: this._initialWindow,
|
|
523
|
+
needs_refill: needsRefill,
|
|
524
|
+
});
|
|
525
|
+
if (!needsRefill) {
|
|
513
526
|
return;
|
|
514
527
|
}
|
|
515
528
|
const delta = this._initialWindow;
|
|
516
529
|
this._flowCtrl.addCredits(flowId, delta);
|
|
530
|
+
logger.debug('maybe_emit_credit_emit', {
|
|
531
|
+
connector_id: this._connectorFlowId,
|
|
532
|
+
flow_id: flowId,
|
|
533
|
+
trace_id: traceId ?? null,
|
|
534
|
+
emitted_credits: delta,
|
|
535
|
+
post_emit_balance: this._flowCtrl.getCredits(flowId),
|
|
536
|
+
});
|
|
517
537
|
const ackEnv = (0, core_1.createFameEnvelope)({
|
|
518
538
|
...(traceId && { traceId }),
|
|
519
539
|
flowId,
|
|
@@ -525,7 +545,25 @@ class BaseAsyncConnector extends task_spawner_js_1.TaskSpawner {
|
|
|
525
545
|
},
|
|
526
546
|
flags: core_1.FlowFlags.ACK,
|
|
527
547
|
});
|
|
528
|
-
|
|
548
|
+
try {
|
|
549
|
+
await this.send(ackEnv);
|
|
550
|
+
logger.debug('maybe_emit_credit_sent', {
|
|
551
|
+
connector_id: this._connectorFlowId,
|
|
552
|
+
flow_id: flowId,
|
|
553
|
+
trace_id: traceId ?? null,
|
|
554
|
+
credits_acknowledged: delta,
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
catch (error) {
|
|
558
|
+
logger.error('maybe_emit_credit_send_failed', {
|
|
559
|
+
connector_id: this._connectorFlowId,
|
|
560
|
+
flow_id: flowId,
|
|
561
|
+
trace_id: traceId ?? null,
|
|
562
|
+
credits_attempted: delta,
|
|
563
|
+
error: error instanceof Error ? error.message : String(error),
|
|
564
|
+
});
|
|
565
|
+
throw error;
|
|
566
|
+
}
|
|
529
567
|
}
|
|
530
568
|
// ---------------------------------------------------------------------
|
|
531
569
|
// Shutdown Management
|
|
@@ -364,6 +364,14 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
364
364
|
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
365
365
|
? senderId
|
|
366
366
|
: undefined;
|
|
367
|
+
logger.debug('broadcast_channel_duplicate_ack_check', {
|
|
368
|
+
channel: this.channelName,
|
|
369
|
+
connector_id: this.connectorId,
|
|
370
|
+
sender_id: normalizedSenderId ?? null,
|
|
371
|
+
dedup_key: dedupKey,
|
|
372
|
+
source: 'listener',
|
|
373
|
+
cache_entries: this.seenAckKeys.size,
|
|
374
|
+
});
|
|
367
375
|
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
368
376
|
}
|
|
369
377
|
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
@@ -386,6 +394,14 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
386
394
|
return false;
|
|
387
395
|
}
|
|
388
396
|
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
397
|
+
logger.debug('broadcast_channel_duplicate_ack_check', {
|
|
398
|
+
channel: this.channelName,
|
|
399
|
+
connector_id: this.connectorId,
|
|
400
|
+
sender_id: senderId ?? null,
|
|
401
|
+
dedup_key: dedupKey,
|
|
402
|
+
source: 'inbox_item',
|
|
403
|
+
cache_entries: this.seenAckKeys.size,
|
|
404
|
+
});
|
|
389
405
|
return this._checkDuplicateAck(dedupKey, senderId);
|
|
390
406
|
}
|
|
391
407
|
_checkDuplicateAck(dedupKey, senderId) {
|
|
@@ -397,11 +413,21 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
397
413
|
connector_id: this.connectorId,
|
|
398
414
|
sender_id: senderId ?? null,
|
|
399
415
|
dedup_key: dedupKey,
|
|
416
|
+
age_ms: now - lastSeen,
|
|
417
|
+
ttl_ms: this.ackDedupTtlMs,
|
|
418
|
+
cache_entries: this.seenAckKeys.size,
|
|
400
419
|
});
|
|
401
420
|
return true;
|
|
402
421
|
}
|
|
403
422
|
this.seenAckKeys.set(dedupKey, now);
|
|
404
423
|
this.seenAckOrder.push(dedupKey);
|
|
424
|
+
logger.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
425
|
+
channel: this.channelName,
|
|
426
|
+
connector_id: this.connectorId,
|
|
427
|
+
sender_id: senderId ?? null,
|
|
428
|
+
dedup_key: dedupKey,
|
|
429
|
+
cache_entries: this.seenAckKeys.size,
|
|
430
|
+
});
|
|
405
431
|
this._trimSeenAcks(now);
|
|
406
432
|
return false;
|
|
407
433
|
}
|
|
@@ -143,9 +143,6 @@ class WebSocketConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
143
143
|
// Browser WebSocket or Node.js ws client
|
|
144
144
|
this._websocket.send(data);
|
|
145
145
|
}
|
|
146
|
-
logger.debug('websocket_sent_bytes', {
|
|
147
|
-
byte_length: data.length,
|
|
148
|
-
});
|
|
149
146
|
}
|
|
150
147
|
catch (error) {
|
|
151
148
|
// Handle WebSocket disconnection errors
|
|
@@ -1,38 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { getLogger } from './logging.js';
|
|
3
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
3
|
exports.AsyncLock = void 0;
|
|
5
4
|
exports.withLock = withLock;
|
|
6
|
-
// const logger = getLogger('naylence.fame.util.lock');
|
|
7
5
|
class AsyncLock {
|
|
8
6
|
constructor() {
|
|
9
|
-
this.
|
|
7
|
+
this.tail = Promise.resolve();
|
|
10
8
|
}
|
|
11
|
-
async
|
|
12
|
-
const currentQueue = this.queue;
|
|
9
|
+
async runExclusive(operation) {
|
|
13
10
|
let release;
|
|
14
|
-
const
|
|
11
|
+
const next = new Promise((resolve) => {
|
|
15
12
|
release = resolve;
|
|
16
13
|
});
|
|
17
|
-
|
|
18
|
-
this.
|
|
19
|
-
|
|
20
|
-
// logger.debug('waiting_for_lock');
|
|
21
|
-
await currentQueue;
|
|
22
|
-
// logger.debug('lock_acquired');
|
|
14
|
+
const previous = this.tail;
|
|
15
|
+
this.tail = previous.then(() => next, () => next);
|
|
16
|
+
await previous;
|
|
23
17
|
try {
|
|
24
|
-
return await
|
|
18
|
+
return await operation();
|
|
25
19
|
}
|
|
26
20
|
finally {
|
|
27
21
|
release();
|
|
28
|
-
// logger.debug('lock_released');
|
|
29
22
|
}
|
|
30
23
|
}
|
|
31
|
-
async runExclusive(task) {
|
|
32
|
-
return this.acquire(task);
|
|
33
|
-
}
|
|
34
24
|
}
|
|
35
25
|
exports.AsyncLock = AsyncLock;
|
|
36
26
|
async function withLock(lock, operation) {
|
|
37
|
-
return await lock.
|
|
27
|
+
return await lock.runExclusive(operation);
|
|
38
28
|
}
|
package/dist/cjs/version.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// This file is auto-generated during build - do not edit manually
|
|
3
|
-
// Generated from package.json version: 0.3.5-test.
|
|
3
|
+
// Generated from package.json version: 0.3.5-test.960
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.VERSION = void 0;
|
|
6
6
|
/**
|
|
7
7
|
* The package version, injected at build time.
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
exports.VERSION = '0.3.5-test.
|
|
10
|
+
exports.VERSION = '0.3.5-test.960';
|
|
@@ -505,11 +505,31 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
505
505
|
* Emit credit update if flow control needs refill
|
|
506
506
|
*/
|
|
507
507
|
async _maybeEmitCredit(flowId, traceId) {
|
|
508
|
-
|
|
508
|
+
const remainingCredits = this._flowCtrl.getCredits(flowId);
|
|
509
|
+
const needsRefill = this._flowCtrl.needsRefill(flowId);
|
|
510
|
+
logger.debug('maybe_emit_credit_check', {
|
|
511
|
+
connector_id: this._connectorFlowId,
|
|
512
|
+
flow_id: flowId,
|
|
513
|
+
trace_id: traceId ?? null,
|
|
514
|
+
remaining_credits: remainingCredits,
|
|
515
|
+
low_watermark: this._flowCtrl instanceof FlowController
|
|
516
|
+
? this._flowCtrl.lowWatermark
|
|
517
|
+
: null,
|
|
518
|
+
initial_window: this._initialWindow,
|
|
519
|
+
needs_refill: needsRefill,
|
|
520
|
+
});
|
|
521
|
+
if (!needsRefill) {
|
|
509
522
|
return;
|
|
510
523
|
}
|
|
511
524
|
const delta = this._initialWindow;
|
|
512
525
|
this._flowCtrl.addCredits(flowId, delta);
|
|
526
|
+
logger.debug('maybe_emit_credit_emit', {
|
|
527
|
+
connector_id: this._connectorFlowId,
|
|
528
|
+
flow_id: flowId,
|
|
529
|
+
trace_id: traceId ?? null,
|
|
530
|
+
emitted_credits: delta,
|
|
531
|
+
post_emit_balance: this._flowCtrl.getCredits(flowId),
|
|
532
|
+
});
|
|
513
533
|
const ackEnv = createFameEnvelope({
|
|
514
534
|
...(traceId && { traceId }),
|
|
515
535
|
flowId,
|
|
@@ -521,7 +541,25 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
521
541
|
},
|
|
522
542
|
flags: FlowFlags.ACK,
|
|
523
543
|
});
|
|
524
|
-
|
|
544
|
+
try {
|
|
545
|
+
await this.send(ackEnv);
|
|
546
|
+
logger.debug('maybe_emit_credit_sent', {
|
|
547
|
+
connector_id: this._connectorFlowId,
|
|
548
|
+
flow_id: flowId,
|
|
549
|
+
trace_id: traceId ?? null,
|
|
550
|
+
credits_acknowledged: delta,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
logger.error('maybe_emit_credit_send_failed', {
|
|
555
|
+
connector_id: this._connectorFlowId,
|
|
556
|
+
flow_id: flowId,
|
|
557
|
+
trace_id: traceId ?? null,
|
|
558
|
+
credits_attempted: delta,
|
|
559
|
+
error: error instanceof Error ? error.message : String(error),
|
|
560
|
+
});
|
|
561
|
+
throw error;
|
|
562
|
+
}
|
|
525
563
|
}
|
|
526
564
|
// ---------------------------------------------------------------------
|
|
527
565
|
// Shutdown Management
|
|
@@ -361,6 +361,14 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
361
361
|
const normalizedSenderId = typeof senderId === 'string' && senderId.length > 0
|
|
362
362
|
? senderId
|
|
363
363
|
: undefined;
|
|
364
|
+
logger.debug('broadcast_channel_duplicate_ack_check', {
|
|
365
|
+
channel: this.channelName,
|
|
366
|
+
connector_id: this.connectorId,
|
|
367
|
+
sender_id: normalizedSenderId ?? null,
|
|
368
|
+
dedup_key: dedupKey,
|
|
369
|
+
source: 'listener',
|
|
370
|
+
cache_entries: this.seenAckKeys.size,
|
|
371
|
+
});
|
|
364
372
|
return this._checkDuplicateAck(dedupKey, normalizedSenderId);
|
|
365
373
|
}
|
|
366
374
|
_shouldSkipDuplicateAckFromInboxItem(item) {
|
|
@@ -383,6 +391,14 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
383
391
|
return false;
|
|
384
392
|
}
|
|
385
393
|
const senderId = this._extractSenderIdFromInboxItem(item);
|
|
394
|
+
logger.debug('broadcast_channel_duplicate_ack_check', {
|
|
395
|
+
channel: this.channelName,
|
|
396
|
+
connector_id: this.connectorId,
|
|
397
|
+
sender_id: senderId ?? null,
|
|
398
|
+
dedup_key: dedupKey,
|
|
399
|
+
source: 'inbox_item',
|
|
400
|
+
cache_entries: this.seenAckKeys.size,
|
|
401
|
+
});
|
|
386
402
|
return this._checkDuplicateAck(dedupKey, senderId);
|
|
387
403
|
}
|
|
388
404
|
_checkDuplicateAck(dedupKey, senderId) {
|
|
@@ -394,11 +410,21 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
394
410
|
connector_id: this.connectorId,
|
|
395
411
|
sender_id: senderId ?? null,
|
|
396
412
|
dedup_key: dedupKey,
|
|
413
|
+
age_ms: now - lastSeen,
|
|
414
|
+
ttl_ms: this.ackDedupTtlMs,
|
|
415
|
+
cache_entries: this.seenAckKeys.size,
|
|
397
416
|
});
|
|
398
417
|
return true;
|
|
399
418
|
}
|
|
400
419
|
this.seenAckKeys.set(dedupKey, now);
|
|
401
420
|
this.seenAckOrder.push(dedupKey);
|
|
421
|
+
logger.debug('broadcast_channel_duplicate_ack_recorded', {
|
|
422
|
+
channel: this.channelName,
|
|
423
|
+
connector_id: this.connectorId,
|
|
424
|
+
sender_id: senderId ?? null,
|
|
425
|
+
dedup_key: dedupKey,
|
|
426
|
+
cache_entries: this.seenAckKeys.size,
|
|
427
|
+
});
|
|
402
428
|
this._trimSeenAcks(now);
|
|
403
429
|
return false;
|
|
404
430
|
}
|
|
@@ -140,9 +140,6 @@ export class WebSocketConnector extends BaseAsyncConnector {
|
|
|
140
140
|
// Browser WebSocket or Node.js ws client
|
|
141
141
|
this._websocket.send(data);
|
|
142
142
|
}
|
|
143
|
-
logger.debug('websocket_sent_bytes', {
|
|
144
|
-
byte_length: data.length,
|
|
145
|
-
});
|
|
146
143
|
}
|
|
147
144
|
catch (error) {
|
|
148
145
|
// Handle WebSocket disconnection errors
|