@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
package/dist/node/node.cjs
CHANGED
|
@@ -2137,6 +2137,48 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2137
2137
|
connector_id: this._connectorFlowId,
|
|
2138
2138
|
});
|
|
2139
2139
|
}
|
|
2140
|
+
/**
|
|
2141
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
2142
|
+
*/
|
|
2143
|
+
async pause() {
|
|
2144
|
+
logger$1f.debug('pausing_connector', {
|
|
2145
|
+
current_state: this._state,
|
|
2146
|
+
connector_id: this._connectorFlowId,
|
|
2147
|
+
});
|
|
2148
|
+
if (this._state !== core.ConnectorState.STARTED) {
|
|
2149
|
+
logger$1f.debug('connector_pause_invalid_state', {
|
|
2150
|
+
current_state: this._state,
|
|
2151
|
+
connector_id: this._connectorFlowId,
|
|
2152
|
+
});
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
this._setState(core.ConnectorState.PAUSED);
|
|
2156
|
+
logger$1f.debug('connector_paused', {
|
|
2157
|
+
current_state: this._state,
|
|
2158
|
+
connector_id: this._connectorFlowId,
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* Resume the connector from paused state
|
|
2163
|
+
*/
|
|
2164
|
+
async resume() {
|
|
2165
|
+
logger$1f.debug('resuming_connector', {
|
|
2166
|
+
current_state: this._state,
|
|
2167
|
+
connector_id: this._connectorFlowId,
|
|
2168
|
+
});
|
|
2169
|
+
if (this._state !== core.ConnectorState.PAUSED) {
|
|
2170
|
+
logger$1f.debug('connector_resume_invalid_state', {
|
|
2171
|
+
current_state: this._state,
|
|
2172
|
+
connector_id: this._connectorFlowId,
|
|
2173
|
+
});
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2176
|
+
this._setState(core.ConnectorState.STARTED);
|
|
2177
|
+
logger$1f.debug('connector_resumed', {
|
|
2178
|
+
current_state: this._state,
|
|
2179
|
+
connector_id: this._connectorFlowId,
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2140
2182
|
/**
|
|
2141
2183
|
* Close the connector with optional code and reason
|
|
2142
2184
|
*/
|
|
@@ -2472,7 +2514,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2472
2514
|
});
|
|
2473
2515
|
return;
|
|
2474
2516
|
}
|
|
2475
|
-
logger$1f.
|
|
2517
|
+
logger$1f.debug('connector_shutdown_starting', {
|
|
2476
2518
|
connector_id: this._connectorFlowId,
|
|
2477
2519
|
connector_type: this.constructor.name,
|
|
2478
2520
|
code,
|
|
@@ -2502,19 +2544,19 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2502
2544
|
this._sendPromiseResolve = undefined;
|
|
2503
2545
|
}
|
|
2504
2546
|
// Close transport
|
|
2505
|
-
logger$1f.
|
|
2547
|
+
logger$1f.debug('connector_closing_transport', {
|
|
2506
2548
|
connector_id: this._connectorFlowId,
|
|
2507
2549
|
connector_type: this.constructor.name,
|
|
2508
2550
|
timestamp: new Date().toISOString(),
|
|
2509
2551
|
});
|
|
2510
2552
|
await this._transportClose(code, reason);
|
|
2511
|
-
logger$1f.
|
|
2553
|
+
logger$1f.debug('connector_transport_closed', {
|
|
2512
2554
|
connector_id: this._connectorFlowId,
|
|
2513
2555
|
connector_type: this.constructor.name,
|
|
2514
2556
|
timestamp: new Date().toISOString(),
|
|
2515
2557
|
});
|
|
2516
2558
|
// Shutdown spawned tasks
|
|
2517
|
-
logger$1f.
|
|
2559
|
+
logger$1f.debug('connector_shutting_down_tasks', {
|
|
2518
2560
|
connector_id: this._connectorFlowId,
|
|
2519
2561
|
connector_type: this.constructor.name,
|
|
2520
2562
|
grace_period_ms: effectiveGracePeriod * 1000,
|
|
@@ -2526,7 +2568,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2526
2568
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
2527
2569
|
joinTimeout: this._shutdownJoinTimeout,
|
|
2528
2570
|
});
|
|
2529
|
-
logger$1f.
|
|
2571
|
+
logger$1f.debug('connector_tasks_shutdown_complete', {
|
|
2530
2572
|
connector_id: this._connectorFlowId,
|
|
2531
2573
|
connector_type: this.constructor.name,
|
|
2532
2574
|
timestamp: new Date().toISOString(),
|
|
@@ -2546,7 +2588,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2546
2588
|
if (this._closeResolver) {
|
|
2547
2589
|
this._closeResolver();
|
|
2548
2590
|
}
|
|
2549
|
-
logger$1f.
|
|
2591
|
+
logger$1f.debug('connector_shutdown_complete', {
|
|
2550
2592
|
connector_id: this._connectorFlowId,
|
|
2551
2593
|
connector_type: this.constructor.name,
|
|
2552
2594
|
final_state: this._state,
|
|
@@ -5436,12 +5478,12 @@ for (const [name, config] of Object.entries(SQLITE_PROFILES)) {
|
|
|
5436
5478
|
}
|
|
5437
5479
|
|
|
5438
5480
|
// This file is auto-generated during build - do not edit manually
|
|
5439
|
-
// Generated from package.json version: 0.3.5-test.
|
|
5481
|
+
// Generated from package.json version: 0.3.5-test.937
|
|
5440
5482
|
/**
|
|
5441
5483
|
* The package version, injected at build time.
|
|
5442
5484
|
* @internal
|
|
5443
5485
|
*/
|
|
5444
|
-
const VERSION = '0.3.5-test.
|
|
5486
|
+
const VERSION = '0.3.5-test.937';
|
|
5445
5487
|
|
|
5446
5488
|
/**
|
|
5447
5489
|
* Fame errors module - Fame protocol specific error classes
|
|
@@ -11494,7 +11536,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11494
11536
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
11495
11537
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
11496
11538
|
this.channel = new BroadcastChannel(this.channelName);
|
|
11497
|
-
logger$10.
|
|
11539
|
+
logger$10.debug('broadcast_channel_connector_created', {
|
|
11498
11540
|
channel: this.channelName,
|
|
11499
11541
|
connector_id: this.connectorId,
|
|
11500
11542
|
inbox_capacity: preferredCapacity,
|
|
@@ -11575,18 +11617,37 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11575
11617
|
// Setup visibility change monitoring
|
|
11576
11618
|
this.visibilityChangeHandler = () => {
|
|
11577
11619
|
const isHidden = document.hidden;
|
|
11578
|
-
logger$10.
|
|
11620
|
+
logger$10.debug('broadcast_channel_visibility_changed', {
|
|
11579
11621
|
channel: this.channelName,
|
|
11580
11622
|
connector_id: this.connectorId,
|
|
11581
11623
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
11582
11624
|
timestamp: new Date().toISOString(),
|
|
11583
11625
|
});
|
|
11626
|
+
// Pause/resume connector based on visibility
|
|
11627
|
+
if (isHidden && this.state === core.ConnectorState.STARTED) {
|
|
11628
|
+
this.pause().catch((err) => {
|
|
11629
|
+
logger$10.warning('broadcast_channel_pause_failed', {
|
|
11630
|
+
channel: this.channelName,
|
|
11631
|
+
connector_id: this.connectorId,
|
|
11632
|
+
error: err instanceof Error ? err.message : String(err),
|
|
11633
|
+
});
|
|
11634
|
+
});
|
|
11635
|
+
}
|
|
11636
|
+
else if (!isHidden && this.state === core.ConnectorState.PAUSED) {
|
|
11637
|
+
this.resume().catch((err) => {
|
|
11638
|
+
logger$10.warning('broadcast_channel_resume_failed', {
|
|
11639
|
+
channel: this.channelName,
|
|
11640
|
+
connector_id: this.connectorId,
|
|
11641
|
+
error: err instanceof Error ? err.message : String(err),
|
|
11642
|
+
});
|
|
11643
|
+
});
|
|
11644
|
+
}
|
|
11584
11645
|
};
|
|
11585
11646
|
if (typeof document !== 'undefined') {
|
|
11586
11647
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
11587
11648
|
this.visibilityChangeListenerRegistered = true;
|
|
11588
11649
|
// Log initial state
|
|
11589
|
-
logger$10.
|
|
11650
|
+
logger$10.debug('broadcast_channel_initial_visibility', {
|
|
11590
11651
|
channel: this.channelName,
|
|
11591
11652
|
connector_id: this.connectorId,
|
|
11592
11653
|
visibility: document.hidden ? 'hidden' : 'visible',
|
|
@@ -11636,7 +11697,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11636
11697
|
return await this.inbox.dequeue();
|
|
11637
11698
|
}
|
|
11638
11699
|
async _transportClose(code, reason) {
|
|
11639
|
-
logger$10.
|
|
11700
|
+
logger$10.debug('broadcast_channel_transport_closing', {
|
|
11640
11701
|
channel: this.channelName,
|
|
11641
11702
|
connector_id: this.connectorId,
|
|
11642
11703
|
code,
|
|
@@ -11645,14 +11706,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11645
11706
|
timestamp: new Date().toISOString(),
|
|
11646
11707
|
});
|
|
11647
11708
|
if (this.listenerRegistered) {
|
|
11648
|
-
logger$10.
|
|
11709
|
+
logger$10.debug('broadcast_channel_removing_listener', {
|
|
11649
11710
|
channel: this.channelName,
|
|
11650
11711
|
connector_id: this.connectorId,
|
|
11651
11712
|
timestamp: new Date().toISOString(),
|
|
11652
11713
|
});
|
|
11653
11714
|
this.channel.removeEventListener('message', this.onMsg);
|
|
11654
11715
|
this.listenerRegistered = false;
|
|
11655
|
-
logger$10.
|
|
11716
|
+
logger$10.debug('broadcast_channel_listener_removed', {
|
|
11656
11717
|
channel: this.channelName,
|
|
11657
11718
|
connector_id: this.connectorId,
|
|
11658
11719
|
timestamp: new Date().toISOString(),
|
|
@@ -11663,13 +11724,13 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11663
11724
|
this.visibilityChangeListenerRegistered = false;
|
|
11664
11725
|
this.visibilityChangeHandler = undefined;
|
|
11665
11726
|
}
|
|
11666
|
-
logger$10.
|
|
11727
|
+
logger$10.debug('broadcast_channel_closing', {
|
|
11667
11728
|
channel: this.channelName,
|
|
11668
11729
|
connector_id: this.connectorId,
|
|
11669
11730
|
timestamp: new Date().toISOString(),
|
|
11670
11731
|
});
|
|
11671
11732
|
this.channel.close();
|
|
11672
|
-
logger$10.
|
|
11733
|
+
logger$10.debug('broadcast_channel_closed', {
|
|
11673
11734
|
channel: this.channelName,
|
|
11674
11735
|
connector_id: this.connectorId,
|
|
11675
11736
|
timestamp: new Date().toISOString(),
|
|
@@ -11760,6 +11821,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11760
11821
|
}
|
|
11761
11822
|
return undefined;
|
|
11762
11823
|
}
|
|
11824
|
+
/**
|
|
11825
|
+
* Override start() to check initial visibility state
|
|
11826
|
+
*/
|
|
11827
|
+
async start(inboundHandler) {
|
|
11828
|
+
await super.start(inboundHandler);
|
|
11829
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
11830
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
11831
|
+
logger$10.debug('broadcast_channel_start_in_hidden_tab', {
|
|
11832
|
+
channel: this.channelName,
|
|
11833
|
+
connector_id: this.connectorId,
|
|
11834
|
+
timestamp: new Date().toISOString(),
|
|
11835
|
+
});
|
|
11836
|
+
// Immediately pause if tab is hidden at start time
|
|
11837
|
+
await this.pause().catch((err) => {
|
|
11838
|
+
logger$10.warning('broadcast_channel_initial_pause_failed', {
|
|
11839
|
+
channel: this.channelName,
|
|
11840
|
+
connector_id: this.connectorId,
|
|
11841
|
+
error: err instanceof Error ? err.message : String(err),
|
|
11842
|
+
});
|
|
11843
|
+
});
|
|
11844
|
+
}
|
|
11845
|
+
}
|
|
11763
11846
|
_trimSeenAcks(now) {
|
|
11764
11847
|
while (this.seenAckOrder.length > 0) {
|
|
11765
11848
|
const candidate = this.seenAckOrder[0];
|
|
@@ -12425,6 +12508,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
12425
12508
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
12426
12509
|
break;
|
|
12427
12510
|
}
|
|
12511
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
12512
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
12513
|
+
if (connector.state === core.ConnectorState.PAUSED) {
|
|
12514
|
+
logger$$.debug('skipping_heartbeat_connector_paused', {
|
|
12515
|
+
connector_state: connector.state,
|
|
12516
|
+
});
|
|
12517
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
12518
|
+
continue;
|
|
12519
|
+
}
|
|
12428
12520
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
12429
12521
|
logger$$.debug('sending_heartbeat', {
|
|
12430
12522
|
hb_corr_id: envelope.corrId,
|
|
@@ -12446,6 +12538,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
12446
12538
|
throw error;
|
|
12447
12539
|
}
|
|
12448
12540
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
12541
|
+
// Don't check heartbeat timeout when paused
|
|
12449
12542
|
if (this.lastHeartbeatAckTime !== null &&
|
|
12450
12543
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
12451
12544
|
throw new FameConnectError('missed heartbeat acknowledgement');
|
package/dist/node/node.mjs
CHANGED
|
@@ -2136,6 +2136,48 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2136
2136
|
connector_id: this._connectorFlowId,
|
|
2137
2137
|
});
|
|
2138
2138
|
}
|
|
2139
|
+
/**
|
|
2140
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
2141
|
+
*/
|
|
2142
|
+
async pause() {
|
|
2143
|
+
logger$1f.debug('pausing_connector', {
|
|
2144
|
+
current_state: this._state,
|
|
2145
|
+
connector_id: this._connectorFlowId,
|
|
2146
|
+
});
|
|
2147
|
+
if (this._state !== ConnectorState.STARTED) {
|
|
2148
|
+
logger$1f.debug('connector_pause_invalid_state', {
|
|
2149
|
+
current_state: this._state,
|
|
2150
|
+
connector_id: this._connectorFlowId,
|
|
2151
|
+
});
|
|
2152
|
+
return;
|
|
2153
|
+
}
|
|
2154
|
+
this._setState(ConnectorState.PAUSED);
|
|
2155
|
+
logger$1f.debug('connector_paused', {
|
|
2156
|
+
current_state: this._state,
|
|
2157
|
+
connector_id: this._connectorFlowId,
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* Resume the connector from paused state
|
|
2162
|
+
*/
|
|
2163
|
+
async resume() {
|
|
2164
|
+
logger$1f.debug('resuming_connector', {
|
|
2165
|
+
current_state: this._state,
|
|
2166
|
+
connector_id: this._connectorFlowId,
|
|
2167
|
+
});
|
|
2168
|
+
if (this._state !== ConnectorState.PAUSED) {
|
|
2169
|
+
logger$1f.debug('connector_resume_invalid_state', {
|
|
2170
|
+
current_state: this._state,
|
|
2171
|
+
connector_id: this._connectorFlowId,
|
|
2172
|
+
});
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
this._setState(ConnectorState.STARTED);
|
|
2176
|
+
logger$1f.debug('connector_resumed', {
|
|
2177
|
+
current_state: this._state,
|
|
2178
|
+
connector_id: this._connectorFlowId,
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2139
2181
|
/**
|
|
2140
2182
|
* Close the connector with optional code and reason
|
|
2141
2183
|
*/
|
|
@@ -2471,7 +2513,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2471
2513
|
});
|
|
2472
2514
|
return;
|
|
2473
2515
|
}
|
|
2474
|
-
logger$1f.
|
|
2516
|
+
logger$1f.debug('connector_shutdown_starting', {
|
|
2475
2517
|
connector_id: this._connectorFlowId,
|
|
2476
2518
|
connector_type: this.constructor.name,
|
|
2477
2519
|
code,
|
|
@@ -2501,19 +2543,19 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2501
2543
|
this._sendPromiseResolve = undefined;
|
|
2502
2544
|
}
|
|
2503
2545
|
// Close transport
|
|
2504
|
-
logger$1f.
|
|
2546
|
+
logger$1f.debug('connector_closing_transport', {
|
|
2505
2547
|
connector_id: this._connectorFlowId,
|
|
2506
2548
|
connector_type: this.constructor.name,
|
|
2507
2549
|
timestamp: new Date().toISOString(),
|
|
2508
2550
|
});
|
|
2509
2551
|
await this._transportClose(code, reason);
|
|
2510
|
-
logger$1f.
|
|
2552
|
+
logger$1f.debug('connector_transport_closed', {
|
|
2511
2553
|
connector_id: this._connectorFlowId,
|
|
2512
2554
|
connector_type: this.constructor.name,
|
|
2513
2555
|
timestamp: new Date().toISOString(),
|
|
2514
2556
|
});
|
|
2515
2557
|
// Shutdown spawned tasks
|
|
2516
|
-
logger$1f.
|
|
2558
|
+
logger$1f.debug('connector_shutting_down_tasks', {
|
|
2517
2559
|
connector_id: this._connectorFlowId,
|
|
2518
2560
|
connector_type: this.constructor.name,
|
|
2519
2561
|
grace_period_ms: effectiveGracePeriod * 1000,
|
|
@@ -2525,7 +2567,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2525
2567
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
2526
2568
|
joinTimeout: this._shutdownJoinTimeout,
|
|
2527
2569
|
});
|
|
2528
|
-
logger$1f.
|
|
2570
|
+
logger$1f.debug('connector_tasks_shutdown_complete', {
|
|
2529
2571
|
connector_id: this._connectorFlowId,
|
|
2530
2572
|
connector_type: this.constructor.name,
|
|
2531
2573
|
timestamp: new Date().toISOString(),
|
|
@@ -2545,7 +2587,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
2545
2587
|
if (this._closeResolver) {
|
|
2546
2588
|
this._closeResolver();
|
|
2547
2589
|
}
|
|
2548
|
-
logger$1f.
|
|
2590
|
+
logger$1f.debug('connector_shutdown_complete', {
|
|
2549
2591
|
connector_id: this._connectorFlowId,
|
|
2550
2592
|
connector_type: this.constructor.name,
|
|
2551
2593
|
final_state: this._state,
|
|
@@ -5435,12 +5477,12 @@ for (const [name, config] of Object.entries(SQLITE_PROFILES)) {
|
|
|
5435
5477
|
}
|
|
5436
5478
|
|
|
5437
5479
|
// This file is auto-generated during build - do not edit manually
|
|
5438
|
-
// Generated from package.json version: 0.3.5-test.
|
|
5480
|
+
// Generated from package.json version: 0.3.5-test.937
|
|
5439
5481
|
/**
|
|
5440
5482
|
* The package version, injected at build time.
|
|
5441
5483
|
* @internal
|
|
5442
5484
|
*/
|
|
5443
|
-
const VERSION = '0.3.5-test.
|
|
5485
|
+
const VERSION = '0.3.5-test.937';
|
|
5444
5486
|
|
|
5445
5487
|
/**
|
|
5446
5488
|
* Fame errors module - Fame protocol specific error classes
|
|
@@ -11493,7 +11535,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11493
11535
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
11494
11536
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
11495
11537
|
this.channel = new BroadcastChannel(this.channelName);
|
|
11496
|
-
logger$10.
|
|
11538
|
+
logger$10.debug('broadcast_channel_connector_created', {
|
|
11497
11539
|
channel: this.channelName,
|
|
11498
11540
|
connector_id: this.connectorId,
|
|
11499
11541
|
inbox_capacity: preferredCapacity,
|
|
@@ -11574,18 +11616,37 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11574
11616
|
// Setup visibility change monitoring
|
|
11575
11617
|
this.visibilityChangeHandler = () => {
|
|
11576
11618
|
const isHidden = document.hidden;
|
|
11577
|
-
logger$10.
|
|
11619
|
+
logger$10.debug('broadcast_channel_visibility_changed', {
|
|
11578
11620
|
channel: this.channelName,
|
|
11579
11621
|
connector_id: this.connectorId,
|
|
11580
11622
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
11581
11623
|
timestamp: new Date().toISOString(),
|
|
11582
11624
|
});
|
|
11625
|
+
// Pause/resume connector based on visibility
|
|
11626
|
+
if (isHidden && this.state === ConnectorState.STARTED) {
|
|
11627
|
+
this.pause().catch((err) => {
|
|
11628
|
+
logger$10.warning('broadcast_channel_pause_failed', {
|
|
11629
|
+
channel: this.channelName,
|
|
11630
|
+
connector_id: this.connectorId,
|
|
11631
|
+
error: err instanceof Error ? err.message : String(err),
|
|
11632
|
+
});
|
|
11633
|
+
});
|
|
11634
|
+
}
|
|
11635
|
+
else if (!isHidden && this.state === ConnectorState.PAUSED) {
|
|
11636
|
+
this.resume().catch((err) => {
|
|
11637
|
+
logger$10.warning('broadcast_channel_resume_failed', {
|
|
11638
|
+
channel: this.channelName,
|
|
11639
|
+
connector_id: this.connectorId,
|
|
11640
|
+
error: err instanceof Error ? err.message : String(err),
|
|
11641
|
+
});
|
|
11642
|
+
});
|
|
11643
|
+
}
|
|
11583
11644
|
};
|
|
11584
11645
|
if (typeof document !== 'undefined') {
|
|
11585
11646
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
11586
11647
|
this.visibilityChangeListenerRegistered = true;
|
|
11587
11648
|
// Log initial state
|
|
11588
|
-
logger$10.
|
|
11649
|
+
logger$10.debug('broadcast_channel_initial_visibility', {
|
|
11589
11650
|
channel: this.channelName,
|
|
11590
11651
|
connector_id: this.connectorId,
|
|
11591
11652
|
visibility: document.hidden ? 'hidden' : 'visible',
|
|
@@ -11635,7 +11696,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11635
11696
|
return await this.inbox.dequeue();
|
|
11636
11697
|
}
|
|
11637
11698
|
async _transportClose(code, reason) {
|
|
11638
|
-
logger$10.
|
|
11699
|
+
logger$10.debug('broadcast_channel_transport_closing', {
|
|
11639
11700
|
channel: this.channelName,
|
|
11640
11701
|
connector_id: this.connectorId,
|
|
11641
11702
|
code,
|
|
@@ -11644,14 +11705,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11644
11705
|
timestamp: new Date().toISOString(),
|
|
11645
11706
|
});
|
|
11646
11707
|
if (this.listenerRegistered) {
|
|
11647
|
-
logger$10.
|
|
11708
|
+
logger$10.debug('broadcast_channel_removing_listener', {
|
|
11648
11709
|
channel: this.channelName,
|
|
11649
11710
|
connector_id: this.connectorId,
|
|
11650
11711
|
timestamp: new Date().toISOString(),
|
|
11651
11712
|
});
|
|
11652
11713
|
this.channel.removeEventListener('message', this.onMsg);
|
|
11653
11714
|
this.listenerRegistered = false;
|
|
11654
|
-
logger$10.
|
|
11715
|
+
logger$10.debug('broadcast_channel_listener_removed', {
|
|
11655
11716
|
channel: this.channelName,
|
|
11656
11717
|
connector_id: this.connectorId,
|
|
11657
11718
|
timestamp: new Date().toISOString(),
|
|
@@ -11662,13 +11723,13 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11662
11723
|
this.visibilityChangeListenerRegistered = false;
|
|
11663
11724
|
this.visibilityChangeHandler = undefined;
|
|
11664
11725
|
}
|
|
11665
|
-
logger$10.
|
|
11726
|
+
logger$10.debug('broadcast_channel_closing', {
|
|
11666
11727
|
channel: this.channelName,
|
|
11667
11728
|
connector_id: this.connectorId,
|
|
11668
11729
|
timestamp: new Date().toISOString(),
|
|
11669
11730
|
});
|
|
11670
11731
|
this.channel.close();
|
|
11671
|
-
logger$10.
|
|
11732
|
+
logger$10.debug('broadcast_channel_closed', {
|
|
11672
11733
|
channel: this.channelName,
|
|
11673
11734
|
connector_id: this.connectorId,
|
|
11674
11735
|
timestamp: new Date().toISOString(),
|
|
@@ -11759,6 +11820,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
11759
11820
|
}
|
|
11760
11821
|
return undefined;
|
|
11761
11822
|
}
|
|
11823
|
+
/**
|
|
11824
|
+
* Override start() to check initial visibility state
|
|
11825
|
+
*/
|
|
11826
|
+
async start(inboundHandler) {
|
|
11827
|
+
await super.start(inboundHandler);
|
|
11828
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
11829
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
11830
|
+
logger$10.debug('broadcast_channel_start_in_hidden_tab', {
|
|
11831
|
+
channel: this.channelName,
|
|
11832
|
+
connector_id: this.connectorId,
|
|
11833
|
+
timestamp: new Date().toISOString(),
|
|
11834
|
+
});
|
|
11835
|
+
// Immediately pause if tab is hidden at start time
|
|
11836
|
+
await this.pause().catch((err) => {
|
|
11837
|
+
logger$10.warning('broadcast_channel_initial_pause_failed', {
|
|
11838
|
+
channel: this.channelName,
|
|
11839
|
+
connector_id: this.connectorId,
|
|
11840
|
+
error: err instanceof Error ? err.message : String(err),
|
|
11841
|
+
});
|
|
11842
|
+
});
|
|
11843
|
+
}
|
|
11844
|
+
}
|
|
11762
11845
|
_trimSeenAcks(now) {
|
|
11763
11846
|
while (this.seenAckOrder.length > 0) {
|
|
11764
11847
|
const candidate = this.seenAckOrder[0];
|
|
@@ -12424,6 +12507,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
12424
12507
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
12425
12508
|
break;
|
|
12426
12509
|
}
|
|
12510
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
12511
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
12512
|
+
if (connector.state === ConnectorState.PAUSED) {
|
|
12513
|
+
logger$$.debug('skipping_heartbeat_connector_paused', {
|
|
12514
|
+
connector_state: connector.state,
|
|
12515
|
+
});
|
|
12516
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
12517
|
+
continue;
|
|
12518
|
+
}
|
|
12427
12519
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
12428
12520
|
logger$$.debug('sending_heartbeat', {
|
|
12429
12521
|
hb_corr_id: envelope.corrId,
|
|
@@ -12445,6 +12537,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
12445
12537
|
throw error;
|
|
12446
12538
|
}
|
|
12447
12539
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
12540
|
+
// Don't check heartbeat timeout when paused
|
|
12448
12541
|
if (this.lastHeartbeatAckTime !== null &&
|
|
12449
12542
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
12450
12543
|
throw new FameConnectError('missed heartbeat acknowledgement');
|
|
@@ -103,6 +103,14 @@ export declare abstract class BaseAsyncConnector extends TaskSpawner implements
|
|
|
103
103
|
* Stop the connector gracefully
|
|
104
104
|
*/
|
|
105
105
|
stop(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
108
|
+
*/
|
|
109
|
+
pause(): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Resume the connector from paused state
|
|
112
|
+
*/
|
|
113
|
+
resume(): Promise<void>;
|
|
106
114
|
/**
|
|
107
115
|
* Close the connector with optional code and reason
|
|
108
116
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseAsyncConnector, type BaseAsyncConnectorConfig } from './base-async-connector.js';
|
|
2
2
|
import type { ConnectorConfig } from './connector-config.js';
|
|
3
|
-
import type { FameEnvelope, FameChannelMessage } from '@naylence/core';
|
|
3
|
+
import type { FameEnvelope, FameChannelMessage, FameEnvelopeHandler } from '@naylence/core';
|
|
4
4
|
export declare const BROADCAST_CHANNEL_CONNECTOR_TYPE: "broadcast-channel-connector";
|
|
5
5
|
export interface BroadcastChannelConnectorConfig extends ConnectorConfig {
|
|
6
6
|
type: typeof BROADCAST_CHANNEL_CONNECTOR_TYPE;
|
|
@@ -35,6 +35,10 @@ export declare class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
35
35
|
private _checkDuplicateAck;
|
|
36
36
|
private _extractEnvelopeFromInboxItem;
|
|
37
37
|
private _extractSenderIdFromInboxItem;
|
|
38
|
+
/**
|
|
39
|
+
* Override start() to check initial visibility state
|
|
40
|
+
*/
|
|
41
|
+
start(inboundHandler: FameEnvelopeHandler): Promise<void>;
|
|
38
42
|
private _trimSeenAcks;
|
|
39
43
|
private _extractAckDedupKey;
|
|
40
44
|
}
|
package/dist/types/version.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naylence/runtime",
|
|
3
|
-
"version": "0.3.5-test.
|
|
3
|
+
"version": "0.3.5-test.937",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Naylence Runtime - Complete TypeScript runtime",
|
|
6
6
|
"author": "Naylence Dev <naylencedev@gmail.com>",
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
"dependencies": {
|
|
177
177
|
"@fastify/formbody": "^8.0.2",
|
|
178
178
|
"@fastify/websocket": "^11.2.0",
|
|
179
|
-
"@naylence/core": "^0.3.
|
|
179
|
+
"@naylence/core": "^0.3.5",
|
|
180
180
|
"@noble/ciphers": "^2.0.1",
|
|
181
181
|
"@noble/curves": "^2.0.1",
|
|
182
182
|
"@noble/ed25519": "^3.0.0",
|