@naylence/runtime 0.3.5-test.934 → 0.3.5-test.937
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 +109 -16
- package/dist/browser/index.mjs +109 -16
- package/dist/cjs/naylence/fame/connector/base-async-connector.js +48 -6
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +50 -8
- package/dist/cjs/naylence/fame/node/upstream-session-manager.js +10 -0
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/base-async-connector.js +48 -6
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +50 -8
- package/dist/esm/naylence/fame/node/upstream-session-manager.js +11 -1
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +109 -16
- package/dist/node/index.mjs +109 -16
- package/dist/node/node.cjs +109 -16
- package/dist/node/node.mjs +109 -16
- package/dist/types/naylence/fame/connector/base-async-connector.d.ts +8 -0
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +5 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +2 -2
|
@@ -5,6 +5,7 @@ const base_async_connector_js_1 = require("./base-async-connector.js");
|
|
|
5
5
|
const errors_js_1 = require("../errors/errors.js");
|
|
6
6
|
const logging_js_1 = require("../util/logging.js");
|
|
7
7
|
const bounded_async_queue_js_1 = require("../util/bounded-async-queue.js");
|
|
8
|
+
const core_1 = require("@naylence/core");
|
|
8
9
|
const logger = (0, logging_js_1.getLogger)('naylence.fame.connector.broadcast_channel_connector');
|
|
9
10
|
exports.BROADCAST_CHANNEL_CONNECTOR_TYPE = 'broadcast-channel-connector';
|
|
10
11
|
const DEFAULT_CHANNEL = 'naylence-fabric';
|
|
@@ -70,7 +71,7 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
70
71
|
this.inbox = new bounded_async_queue_js_1.BoundedAsyncQueue(preferredCapacity);
|
|
71
72
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
72
73
|
this.channel = new BroadcastChannel(this.channelName);
|
|
73
|
-
logger.
|
|
74
|
+
logger.debug('broadcast_channel_connector_created', {
|
|
74
75
|
channel: this.channelName,
|
|
75
76
|
connector_id: this.connectorId,
|
|
76
77
|
inbox_capacity: preferredCapacity,
|
|
@@ -151,18 +152,37 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
151
152
|
// Setup visibility change monitoring
|
|
152
153
|
this.visibilityChangeHandler = () => {
|
|
153
154
|
const isHidden = document.hidden;
|
|
154
|
-
logger.
|
|
155
|
+
logger.debug('broadcast_channel_visibility_changed', {
|
|
155
156
|
channel: this.channelName,
|
|
156
157
|
connector_id: this.connectorId,
|
|
157
158
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
158
159
|
timestamp: new Date().toISOString(),
|
|
159
160
|
});
|
|
161
|
+
// Pause/resume connector based on visibility
|
|
162
|
+
if (isHidden && this.state === core_1.ConnectorState.STARTED) {
|
|
163
|
+
this.pause().catch((err) => {
|
|
164
|
+
logger.warning('broadcast_channel_pause_failed', {
|
|
165
|
+
channel: this.channelName,
|
|
166
|
+
connector_id: this.connectorId,
|
|
167
|
+
error: err instanceof Error ? err.message : String(err),
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else if (!isHidden && this.state === core_1.ConnectorState.PAUSED) {
|
|
172
|
+
this.resume().catch((err) => {
|
|
173
|
+
logger.warning('broadcast_channel_resume_failed', {
|
|
174
|
+
channel: this.channelName,
|
|
175
|
+
connector_id: this.connectorId,
|
|
176
|
+
error: err instanceof Error ? err.message : String(err),
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
160
180
|
};
|
|
161
181
|
if (typeof document !== 'undefined') {
|
|
162
182
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
163
183
|
this.visibilityChangeListenerRegistered = true;
|
|
164
184
|
// Log initial state
|
|
165
|
-
logger.
|
|
185
|
+
logger.debug('broadcast_channel_initial_visibility', {
|
|
166
186
|
channel: this.channelName,
|
|
167
187
|
connector_id: this.connectorId,
|
|
168
188
|
visibility: document.hidden ? 'hidden' : 'visible',
|
|
@@ -212,7 +232,7 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
212
232
|
return await this.inbox.dequeue();
|
|
213
233
|
}
|
|
214
234
|
async _transportClose(code, reason) {
|
|
215
|
-
logger.
|
|
235
|
+
logger.debug('broadcast_channel_transport_closing', {
|
|
216
236
|
channel: this.channelName,
|
|
217
237
|
connector_id: this.connectorId,
|
|
218
238
|
code,
|
|
@@ -221,14 +241,14 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
221
241
|
timestamp: new Date().toISOString(),
|
|
222
242
|
});
|
|
223
243
|
if (this.listenerRegistered) {
|
|
224
|
-
logger.
|
|
244
|
+
logger.debug('broadcast_channel_removing_listener', {
|
|
225
245
|
channel: this.channelName,
|
|
226
246
|
connector_id: this.connectorId,
|
|
227
247
|
timestamp: new Date().toISOString(),
|
|
228
248
|
});
|
|
229
249
|
this.channel.removeEventListener('message', this.onMsg);
|
|
230
250
|
this.listenerRegistered = false;
|
|
231
|
-
logger.
|
|
251
|
+
logger.debug('broadcast_channel_listener_removed', {
|
|
232
252
|
channel: this.channelName,
|
|
233
253
|
connector_id: this.connectorId,
|
|
234
254
|
timestamp: new Date().toISOString(),
|
|
@@ -239,13 +259,13 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
239
259
|
this.visibilityChangeListenerRegistered = false;
|
|
240
260
|
this.visibilityChangeHandler = undefined;
|
|
241
261
|
}
|
|
242
|
-
logger.
|
|
262
|
+
logger.debug('broadcast_channel_closing', {
|
|
243
263
|
channel: this.channelName,
|
|
244
264
|
connector_id: this.connectorId,
|
|
245
265
|
timestamp: new Date().toISOString(),
|
|
246
266
|
});
|
|
247
267
|
this.channel.close();
|
|
248
|
-
logger.
|
|
268
|
+
logger.debug('broadcast_channel_closed', {
|
|
249
269
|
channel: this.channelName,
|
|
250
270
|
connector_id: this.connectorId,
|
|
251
271
|
timestamp: new Date().toISOString(),
|
|
@@ -336,6 +356,28 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
336
356
|
}
|
|
337
357
|
return undefined;
|
|
338
358
|
}
|
|
359
|
+
/**
|
|
360
|
+
* Override start() to check initial visibility state
|
|
361
|
+
*/
|
|
362
|
+
async start(inboundHandler) {
|
|
363
|
+
await super.start(inboundHandler);
|
|
364
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
365
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
366
|
+
logger.debug('broadcast_channel_start_in_hidden_tab', {
|
|
367
|
+
channel: this.channelName,
|
|
368
|
+
connector_id: this.connectorId,
|
|
369
|
+
timestamp: new Date().toISOString(),
|
|
370
|
+
});
|
|
371
|
+
// Immediately pause if tab is hidden at start time
|
|
372
|
+
await this.pause().catch((err) => {
|
|
373
|
+
logger.warning('broadcast_channel_initial_pause_failed', {
|
|
374
|
+
channel: this.channelName,
|
|
375
|
+
connector_id: this.connectorId,
|
|
376
|
+
error: err instanceof Error ? err.message : String(err),
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
339
381
|
_trimSeenAcks(now) {
|
|
340
382
|
while (this.seenAckOrder.length > 0) {
|
|
341
383
|
const candidate = this.seenAckOrder[0];
|
|
@@ -536,6 +536,15 @@ class UpstreamSessionManager extends task_spawner_js_1.TaskSpawner {
|
|
|
536
536
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
537
537
|
break;
|
|
538
538
|
}
|
|
539
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
540
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
541
|
+
if (connector.state === core_1.ConnectorState.PAUSED) {
|
|
542
|
+
logger.debug('skipping_heartbeat_connector_paused', {
|
|
543
|
+
connector_state: connector.state,
|
|
544
|
+
});
|
|
545
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
539
548
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
540
549
|
logger.debug('sending_heartbeat', {
|
|
541
550
|
hb_corr_id: envelope.corrId,
|
|
@@ -557,6 +566,7 @@ class UpstreamSessionManager extends task_spawner_js_1.TaskSpawner {
|
|
|
557
566
|
throw error;
|
|
558
567
|
}
|
|
559
568
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
569
|
+
// Don't check heartbeat timeout when paused
|
|
560
570
|
if (this.lastHeartbeatAckTime !== null &&
|
|
561
571
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
562
572
|
throw new errors_js_1.FameConnectError('missed heartbeat acknowledgement');
|
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.937
|
|
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.937';
|
|
@@ -165,6 +165,48 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
165
165
|
connector_id: this._connectorFlowId,
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
170
|
+
*/
|
|
171
|
+
async pause() {
|
|
172
|
+
logger.debug('pausing_connector', {
|
|
173
|
+
current_state: this._state,
|
|
174
|
+
connector_id: this._connectorFlowId,
|
|
175
|
+
});
|
|
176
|
+
if (this._state !== ConnectorState.STARTED) {
|
|
177
|
+
logger.debug('connector_pause_invalid_state', {
|
|
178
|
+
current_state: this._state,
|
|
179
|
+
connector_id: this._connectorFlowId,
|
|
180
|
+
});
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this._setState(ConnectorState.PAUSED);
|
|
184
|
+
logger.debug('connector_paused', {
|
|
185
|
+
current_state: this._state,
|
|
186
|
+
connector_id: this._connectorFlowId,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Resume the connector from paused state
|
|
191
|
+
*/
|
|
192
|
+
async resume() {
|
|
193
|
+
logger.debug('resuming_connector', {
|
|
194
|
+
current_state: this._state,
|
|
195
|
+
connector_id: this._connectorFlowId,
|
|
196
|
+
});
|
|
197
|
+
if (this._state !== ConnectorState.PAUSED) {
|
|
198
|
+
logger.debug('connector_resume_invalid_state', {
|
|
199
|
+
current_state: this._state,
|
|
200
|
+
connector_id: this._connectorFlowId,
|
|
201
|
+
});
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
this._setState(ConnectorState.STARTED);
|
|
205
|
+
logger.debug('connector_resumed', {
|
|
206
|
+
current_state: this._state,
|
|
207
|
+
connector_id: this._connectorFlowId,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
168
210
|
/**
|
|
169
211
|
* Close the connector with optional code and reason
|
|
170
212
|
*/
|
|
@@ -500,7 +542,7 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
500
542
|
});
|
|
501
543
|
return;
|
|
502
544
|
}
|
|
503
|
-
logger.
|
|
545
|
+
logger.debug('connector_shutdown_starting', {
|
|
504
546
|
connector_id: this._connectorFlowId,
|
|
505
547
|
connector_type: this.constructor.name,
|
|
506
548
|
code,
|
|
@@ -530,19 +572,19 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
530
572
|
this._sendPromiseResolve = undefined;
|
|
531
573
|
}
|
|
532
574
|
// Close transport
|
|
533
|
-
logger.
|
|
575
|
+
logger.debug('connector_closing_transport', {
|
|
534
576
|
connector_id: this._connectorFlowId,
|
|
535
577
|
connector_type: this.constructor.name,
|
|
536
578
|
timestamp: new Date().toISOString(),
|
|
537
579
|
});
|
|
538
580
|
await this._transportClose(code, reason);
|
|
539
|
-
logger.
|
|
581
|
+
logger.debug('connector_transport_closed', {
|
|
540
582
|
connector_id: this._connectorFlowId,
|
|
541
583
|
connector_type: this.constructor.name,
|
|
542
584
|
timestamp: new Date().toISOString(),
|
|
543
585
|
});
|
|
544
586
|
// Shutdown spawned tasks
|
|
545
|
-
logger.
|
|
587
|
+
logger.debug('connector_shutting_down_tasks', {
|
|
546
588
|
connector_id: this._connectorFlowId,
|
|
547
589
|
connector_type: this.constructor.name,
|
|
548
590
|
grace_period_ms: effectiveGracePeriod * 1000,
|
|
@@ -554,7 +596,7 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
554
596
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
555
597
|
joinTimeout: this._shutdownJoinTimeout,
|
|
556
598
|
});
|
|
557
|
-
logger.
|
|
599
|
+
logger.debug('connector_tasks_shutdown_complete', {
|
|
558
600
|
connector_id: this._connectorFlowId,
|
|
559
601
|
connector_type: this.constructor.name,
|
|
560
602
|
timestamp: new Date().toISOString(),
|
|
@@ -574,7 +616,7 @@ export class BaseAsyncConnector extends TaskSpawner {
|
|
|
574
616
|
if (this._closeResolver) {
|
|
575
617
|
this._closeResolver();
|
|
576
618
|
}
|
|
577
|
-
logger.
|
|
619
|
+
logger.debug('connector_shutdown_complete', {
|
|
578
620
|
connector_id: this._connectorFlowId,
|
|
579
621
|
connector_type: this.constructor.name,
|
|
580
622
|
final_state: this._state,
|
|
@@ -2,6 +2,7 @@ import { BaseAsyncConnector, } from './base-async-connector.js';
|
|
|
2
2
|
import { FameTransportClose } from '../errors/errors.js';
|
|
3
3
|
import { getLogger } from '../util/logging.js';
|
|
4
4
|
import { BoundedAsyncQueue, QueueFullError, } from '../util/bounded-async-queue.js';
|
|
5
|
+
import { ConnectorState } from '@naylence/core';
|
|
5
6
|
const logger = getLogger('naylence.fame.connector.broadcast_channel_connector');
|
|
6
7
|
export const BROADCAST_CHANNEL_CONNECTOR_TYPE = 'broadcast-channel-connector';
|
|
7
8
|
const DEFAULT_CHANNEL = 'naylence-fabric';
|
|
@@ -67,7 +68,7 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
67
68
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
68
69
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
69
70
|
this.channel = new BroadcastChannel(this.channelName);
|
|
70
|
-
logger.
|
|
71
|
+
logger.debug('broadcast_channel_connector_created', {
|
|
71
72
|
channel: this.channelName,
|
|
72
73
|
connector_id: this.connectorId,
|
|
73
74
|
inbox_capacity: preferredCapacity,
|
|
@@ -148,18 +149,37 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
148
149
|
// Setup visibility change monitoring
|
|
149
150
|
this.visibilityChangeHandler = () => {
|
|
150
151
|
const isHidden = document.hidden;
|
|
151
|
-
logger.
|
|
152
|
+
logger.debug('broadcast_channel_visibility_changed', {
|
|
152
153
|
channel: this.channelName,
|
|
153
154
|
connector_id: this.connectorId,
|
|
154
155
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
155
156
|
timestamp: new Date().toISOString(),
|
|
156
157
|
});
|
|
158
|
+
// Pause/resume connector based on visibility
|
|
159
|
+
if (isHidden && this.state === ConnectorState.STARTED) {
|
|
160
|
+
this.pause().catch((err) => {
|
|
161
|
+
logger.warning('broadcast_channel_pause_failed', {
|
|
162
|
+
channel: this.channelName,
|
|
163
|
+
connector_id: this.connectorId,
|
|
164
|
+
error: err instanceof Error ? err.message : String(err),
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else if (!isHidden && this.state === ConnectorState.PAUSED) {
|
|
169
|
+
this.resume().catch((err) => {
|
|
170
|
+
logger.warning('broadcast_channel_resume_failed', {
|
|
171
|
+
channel: this.channelName,
|
|
172
|
+
connector_id: this.connectorId,
|
|
173
|
+
error: err instanceof Error ? err.message : String(err),
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}
|
|
157
177
|
};
|
|
158
178
|
if (typeof document !== 'undefined') {
|
|
159
179
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
160
180
|
this.visibilityChangeListenerRegistered = true;
|
|
161
181
|
// Log initial state
|
|
162
|
-
logger.
|
|
182
|
+
logger.debug('broadcast_channel_initial_visibility', {
|
|
163
183
|
channel: this.channelName,
|
|
164
184
|
connector_id: this.connectorId,
|
|
165
185
|
visibility: document.hidden ? 'hidden' : 'visible',
|
|
@@ -209,7 +229,7 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
209
229
|
return await this.inbox.dequeue();
|
|
210
230
|
}
|
|
211
231
|
async _transportClose(code, reason) {
|
|
212
|
-
logger.
|
|
232
|
+
logger.debug('broadcast_channel_transport_closing', {
|
|
213
233
|
channel: this.channelName,
|
|
214
234
|
connector_id: this.connectorId,
|
|
215
235
|
code,
|
|
@@ -218,14 +238,14 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
218
238
|
timestamp: new Date().toISOString(),
|
|
219
239
|
});
|
|
220
240
|
if (this.listenerRegistered) {
|
|
221
|
-
logger.
|
|
241
|
+
logger.debug('broadcast_channel_removing_listener', {
|
|
222
242
|
channel: this.channelName,
|
|
223
243
|
connector_id: this.connectorId,
|
|
224
244
|
timestamp: new Date().toISOString(),
|
|
225
245
|
});
|
|
226
246
|
this.channel.removeEventListener('message', this.onMsg);
|
|
227
247
|
this.listenerRegistered = false;
|
|
228
|
-
logger.
|
|
248
|
+
logger.debug('broadcast_channel_listener_removed', {
|
|
229
249
|
channel: this.channelName,
|
|
230
250
|
connector_id: this.connectorId,
|
|
231
251
|
timestamp: new Date().toISOString(),
|
|
@@ -236,13 +256,13 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
236
256
|
this.visibilityChangeListenerRegistered = false;
|
|
237
257
|
this.visibilityChangeHandler = undefined;
|
|
238
258
|
}
|
|
239
|
-
logger.
|
|
259
|
+
logger.debug('broadcast_channel_closing', {
|
|
240
260
|
channel: this.channelName,
|
|
241
261
|
connector_id: this.connectorId,
|
|
242
262
|
timestamp: new Date().toISOString(),
|
|
243
263
|
});
|
|
244
264
|
this.channel.close();
|
|
245
|
-
logger.
|
|
265
|
+
logger.debug('broadcast_channel_closed', {
|
|
246
266
|
channel: this.channelName,
|
|
247
267
|
connector_id: this.connectorId,
|
|
248
268
|
timestamp: new Date().toISOString(),
|
|
@@ -333,6 +353,28 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
333
353
|
}
|
|
334
354
|
return undefined;
|
|
335
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Override start() to check initial visibility state
|
|
358
|
+
*/
|
|
359
|
+
async start(inboundHandler) {
|
|
360
|
+
await super.start(inboundHandler);
|
|
361
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
362
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
363
|
+
logger.debug('broadcast_channel_start_in_hidden_tab', {
|
|
364
|
+
channel: this.channelName,
|
|
365
|
+
connector_id: this.connectorId,
|
|
366
|
+
timestamp: new Date().toISOString(),
|
|
367
|
+
});
|
|
368
|
+
// Immediately pause if tab is hidden at start time
|
|
369
|
+
await this.pause().catch((err) => {
|
|
370
|
+
logger.warning('broadcast_channel_initial_pause_failed', {
|
|
371
|
+
channel: this.channelName,
|
|
372
|
+
connector_id: this.connectorId,
|
|
373
|
+
error: err instanceof Error ? err.message : String(err),
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
336
378
|
_trimSeenAcks(now) {
|
|
337
379
|
while (this.seenAckOrder.length > 0) {
|
|
338
380
|
const candidate = this.seenAckOrder[0];
|
|
@@ -2,7 +2,7 @@ import { ConnectorFactory } from '../connector/connector-factory.js';
|
|
|
2
2
|
import { TaskSpawner } from '../util/task-spawner.js';
|
|
3
3
|
import { AsyncEvent } from '../util/async-event.js';
|
|
4
4
|
import { getLogger } from '../util/logging.js';
|
|
5
|
-
import { DeliveryOriginType, FameFabric, generateId, } from '@naylence/core';
|
|
5
|
+
import { ConnectorState, DeliveryOriginType, FameFabric, generateId, } from '@naylence/core';
|
|
6
6
|
import { FameConnectError, FameMessageTooLarge, FameTransportClose, } from '../errors/errors.js';
|
|
7
7
|
import { TaskCancelledError } from '../util/task-types.js';
|
|
8
8
|
import { FameResponseType } from '@naylence/core';
|
|
@@ -533,6 +533,15 @@ export class UpstreamSessionManager extends TaskSpawner {
|
|
|
533
533
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
534
534
|
break;
|
|
535
535
|
}
|
|
536
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
537
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
538
|
+
if (connector.state === ConnectorState.PAUSED) {
|
|
539
|
+
logger.debug('skipping_heartbeat_connector_paused', {
|
|
540
|
+
connector_state: connector.state,
|
|
541
|
+
});
|
|
542
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
536
545
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
537
546
|
logger.debug('sending_heartbeat', {
|
|
538
547
|
hb_corr_id: envelope.corrId,
|
|
@@ -554,6 +563,7 @@ export class UpstreamSessionManager extends TaskSpawner {
|
|
|
554
563
|
throw error;
|
|
555
564
|
}
|
|
556
565
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
566
|
+
// Don't check heartbeat timeout when paused
|
|
557
567
|
if (this.lastHeartbeatAckTime !== null &&
|
|
558
568
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
559
569
|
throw new FameConnectError('missed heartbeat acknowledgement');
|
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.937
|
|
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.937';
|