@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/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.937
|
|
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.937';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9207,6 +9207,48 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9207
9207
|
connector_id: this._connectorFlowId,
|
|
9208
9208
|
});
|
|
9209
9209
|
}
|
|
9210
|
+
/**
|
|
9211
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
9212
|
+
*/
|
|
9213
|
+
async pause() {
|
|
9214
|
+
logger$$.debug('pausing_connector', {
|
|
9215
|
+
current_state: this._state,
|
|
9216
|
+
connector_id: this._connectorFlowId,
|
|
9217
|
+
});
|
|
9218
|
+
if (this._state !== core.ConnectorState.STARTED) {
|
|
9219
|
+
logger$$.debug('connector_pause_invalid_state', {
|
|
9220
|
+
current_state: this._state,
|
|
9221
|
+
connector_id: this._connectorFlowId,
|
|
9222
|
+
});
|
|
9223
|
+
return;
|
|
9224
|
+
}
|
|
9225
|
+
this._setState(core.ConnectorState.PAUSED);
|
|
9226
|
+
logger$$.debug('connector_paused', {
|
|
9227
|
+
current_state: this._state,
|
|
9228
|
+
connector_id: this._connectorFlowId,
|
|
9229
|
+
});
|
|
9230
|
+
}
|
|
9231
|
+
/**
|
|
9232
|
+
* Resume the connector from paused state
|
|
9233
|
+
*/
|
|
9234
|
+
async resume() {
|
|
9235
|
+
logger$$.debug('resuming_connector', {
|
|
9236
|
+
current_state: this._state,
|
|
9237
|
+
connector_id: this._connectorFlowId,
|
|
9238
|
+
});
|
|
9239
|
+
if (this._state !== core.ConnectorState.PAUSED) {
|
|
9240
|
+
logger$$.debug('connector_resume_invalid_state', {
|
|
9241
|
+
current_state: this._state,
|
|
9242
|
+
connector_id: this._connectorFlowId,
|
|
9243
|
+
});
|
|
9244
|
+
return;
|
|
9245
|
+
}
|
|
9246
|
+
this._setState(core.ConnectorState.STARTED);
|
|
9247
|
+
logger$$.debug('connector_resumed', {
|
|
9248
|
+
current_state: this._state,
|
|
9249
|
+
connector_id: this._connectorFlowId,
|
|
9250
|
+
});
|
|
9251
|
+
}
|
|
9210
9252
|
/**
|
|
9211
9253
|
* Close the connector with optional code and reason
|
|
9212
9254
|
*/
|
|
@@ -9542,7 +9584,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9542
9584
|
});
|
|
9543
9585
|
return;
|
|
9544
9586
|
}
|
|
9545
|
-
logger$$.
|
|
9587
|
+
logger$$.debug('connector_shutdown_starting', {
|
|
9546
9588
|
connector_id: this._connectorFlowId,
|
|
9547
9589
|
connector_type: this.constructor.name,
|
|
9548
9590
|
code,
|
|
@@ -9572,19 +9614,19 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9572
9614
|
this._sendPromiseResolve = undefined;
|
|
9573
9615
|
}
|
|
9574
9616
|
// Close transport
|
|
9575
|
-
logger$$.
|
|
9617
|
+
logger$$.debug('connector_closing_transport', {
|
|
9576
9618
|
connector_id: this._connectorFlowId,
|
|
9577
9619
|
connector_type: this.constructor.name,
|
|
9578
9620
|
timestamp: new Date().toISOString(),
|
|
9579
9621
|
});
|
|
9580
9622
|
await this._transportClose(code, reason);
|
|
9581
|
-
logger$$.
|
|
9623
|
+
logger$$.debug('connector_transport_closed', {
|
|
9582
9624
|
connector_id: this._connectorFlowId,
|
|
9583
9625
|
connector_type: this.constructor.name,
|
|
9584
9626
|
timestamp: new Date().toISOString(),
|
|
9585
9627
|
});
|
|
9586
9628
|
// Shutdown spawned tasks
|
|
9587
|
-
logger$$.
|
|
9629
|
+
logger$$.debug('connector_shutting_down_tasks', {
|
|
9588
9630
|
connector_id: this._connectorFlowId,
|
|
9589
9631
|
connector_type: this.constructor.name,
|
|
9590
9632
|
grace_period_ms: effectiveGracePeriod * 1000,
|
|
@@ -9596,7 +9638,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9596
9638
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
9597
9639
|
joinTimeout: this._shutdownJoinTimeout,
|
|
9598
9640
|
});
|
|
9599
|
-
logger$$.
|
|
9641
|
+
logger$$.debug('connector_tasks_shutdown_complete', {
|
|
9600
9642
|
connector_id: this._connectorFlowId,
|
|
9601
9643
|
connector_type: this.constructor.name,
|
|
9602
9644
|
timestamp: new Date().toISOString(),
|
|
@@ -9616,7 +9658,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9616
9658
|
if (this._closeResolver) {
|
|
9617
9659
|
this._closeResolver();
|
|
9618
9660
|
}
|
|
9619
|
-
logger$$.
|
|
9661
|
+
logger$$.debug('connector_shutdown_complete', {
|
|
9620
9662
|
connector_id: this._connectorFlowId,
|
|
9621
9663
|
connector_type: this.constructor.name,
|
|
9622
9664
|
final_state: this._state,
|
|
@@ -9757,7 +9799,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9757
9799
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9758
9800
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9759
9801
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9760
|
-
logger$_.
|
|
9802
|
+
logger$_.debug('broadcast_channel_connector_created', {
|
|
9761
9803
|
channel: this.channelName,
|
|
9762
9804
|
connector_id: this.connectorId,
|
|
9763
9805
|
inbox_capacity: preferredCapacity,
|
|
@@ -9838,18 +9880,37 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9838
9880
|
// Setup visibility change monitoring
|
|
9839
9881
|
this.visibilityChangeHandler = () => {
|
|
9840
9882
|
const isHidden = document.hidden;
|
|
9841
|
-
logger$_.
|
|
9883
|
+
logger$_.debug('broadcast_channel_visibility_changed', {
|
|
9842
9884
|
channel: this.channelName,
|
|
9843
9885
|
connector_id: this.connectorId,
|
|
9844
9886
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
9845
9887
|
timestamp: new Date().toISOString(),
|
|
9846
9888
|
});
|
|
9889
|
+
// Pause/resume connector based on visibility
|
|
9890
|
+
if (isHidden && this.state === core.ConnectorState.STARTED) {
|
|
9891
|
+
this.pause().catch((err) => {
|
|
9892
|
+
logger$_.warning('broadcast_channel_pause_failed', {
|
|
9893
|
+
channel: this.channelName,
|
|
9894
|
+
connector_id: this.connectorId,
|
|
9895
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9896
|
+
});
|
|
9897
|
+
});
|
|
9898
|
+
}
|
|
9899
|
+
else if (!isHidden && this.state === core.ConnectorState.PAUSED) {
|
|
9900
|
+
this.resume().catch((err) => {
|
|
9901
|
+
logger$_.warning('broadcast_channel_resume_failed', {
|
|
9902
|
+
channel: this.channelName,
|
|
9903
|
+
connector_id: this.connectorId,
|
|
9904
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9905
|
+
});
|
|
9906
|
+
});
|
|
9907
|
+
}
|
|
9847
9908
|
};
|
|
9848
9909
|
if (typeof document !== 'undefined') {
|
|
9849
9910
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
9850
9911
|
this.visibilityChangeListenerRegistered = true;
|
|
9851
9912
|
// Log initial state
|
|
9852
|
-
logger$_.
|
|
9913
|
+
logger$_.debug('broadcast_channel_initial_visibility', {
|
|
9853
9914
|
channel: this.channelName,
|
|
9854
9915
|
connector_id: this.connectorId,
|
|
9855
9916
|
visibility: document.hidden ? 'hidden' : 'visible',
|
|
@@ -9899,7 +9960,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9899
9960
|
return await this.inbox.dequeue();
|
|
9900
9961
|
}
|
|
9901
9962
|
async _transportClose(code, reason) {
|
|
9902
|
-
logger$_.
|
|
9963
|
+
logger$_.debug('broadcast_channel_transport_closing', {
|
|
9903
9964
|
channel: this.channelName,
|
|
9904
9965
|
connector_id: this.connectorId,
|
|
9905
9966
|
code,
|
|
@@ -9908,14 +9969,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9908
9969
|
timestamp: new Date().toISOString(),
|
|
9909
9970
|
});
|
|
9910
9971
|
if (this.listenerRegistered) {
|
|
9911
|
-
logger$_.
|
|
9972
|
+
logger$_.debug('broadcast_channel_removing_listener', {
|
|
9912
9973
|
channel: this.channelName,
|
|
9913
9974
|
connector_id: this.connectorId,
|
|
9914
9975
|
timestamp: new Date().toISOString(),
|
|
9915
9976
|
});
|
|
9916
9977
|
this.channel.removeEventListener('message', this.onMsg);
|
|
9917
9978
|
this.listenerRegistered = false;
|
|
9918
|
-
logger$_.
|
|
9979
|
+
logger$_.debug('broadcast_channel_listener_removed', {
|
|
9919
9980
|
channel: this.channelName,
|
|
9920
9981
|
connector_id: this.connectorId,
|
|
9921
9982
|
timestamp: new Date().toISOString(),
|
|
@@ -9926,13 +9987,13 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9926
9987
|
this.visibilityChangeListenerRegistered = false;
|
|
9927
9988
|
this.visibilityChangeHandler = undefined;
|
|
9928
9989
|
}
|
|
9929
|
-
logger$_.
|
|
9990
|
+
logger$_.debug('broadcast_channel_closing', {
|
|
9930
9991
|
channel: this.channelName,
|
|
9931
9992
|
connector_id: this.connectorId,
|
|
9932
9993
|
timestamp: new Date().toISOString(),
|
|
9933
9994
|
});
|
|
9934
9995
|
this.channel.close();
|
|
9935
|
-
logger$_.
|
|
9996
|
+
logger$_.debug('broadcast_channel_closed', {
|
|
9936
9997
|
channel: this.channelName,
|
|
9937
9998
|
connector_id: this.connectorId,
|
|
9938
9999
|
timestamp: new Date().toISOString(),
|
|
@@ -10023,6 +10084,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10023
10084
|
}
|
|
10024
10085
|
return undefined;
|
|
10025
10086
|
}
|
|
10087
|
+
/**
|
|
10088
|
+
* Override start() to check initial visibility state
|
|
10089
|
+
*/
|
|
10090
|
+
async start(inboundHandler) {
|
|
10091
|
+
await super.start(inboundHandler);
|
|
10092
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
10093
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
10094
|
+
logger$_.debug('broadcast_channel_start_in_hidden_tab', {
|
|
10095
|
+
channel: this.channelName,
|
|
10096
|
+
connector_id: this.connectorId,
|
|
10097
|
+
timestamp: new Date().toISOString(),
|
|
10098
|
+
});
|
|
10099
|
+
// Immediately pause if tab is hidden at start time
|
|
10100
|
+
await this.pause().catch((err) => {
|
|
10101
|
+
logger$_.warning('broadcast_channel_initial_pause_failed', {
|
|
10102
|
+
channel: this.channelName,
|
|
10103
|
+
connector_id: this.connectorId,
|
|
10104
|
+
error: err instanceof Error ? err.message : String(err),
|
|
10105
|
+
});
|
|
10106
|
+
});
|
|
10107
|
+
}
|
|
10108
|
+
}
|
|
10026
10109
|
_trimSeenAcks(now) {
|
|
10027
10110
|
while (this.seenAckOrder.length > 0) {
|
|
10028
10111
|
const candidate = this.seenAckOrder[0];
|
|
@@ -10733,6 +10816,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10733
10816
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
10734
10817
|
break;
|
|
10735
10818
|
}
|
|
10819
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
10820
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
10821
|
+
if (connector.state === core.ConnectorState.PAUSED) {
|
|
10822
|
+
logger$Z.debug('skipping_heartbeat_connector_paused', {
|
|
10823
|
+
connector_state: connector.state,
|
|
10824
|
+
});
|
|
10825
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
10826
|
+
continue;
|
|
10827
|
+
}
|
|
10736
10828
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
10737
10829
|
logger$Z.debug('sending_heartbeat', {
|
|
10738
10830
|
hb_corr_id: envelope.corrId,
|
|
@@ -10754,6 +10846,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10754
10846
|
throw error;
|
|
10755
10847
|
}
|
|
10756
10848
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
10849
|
+
// Don't check heartbeat timeout when paused
|
|
10757
10850
|
if (this.lastHeartbeatAckTime !== null &&
|
|
10758
10851
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
10759
10852
|
throw new FameConnectError('missed heartbeat acknowledgement');
|
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.937
|
|
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.937';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9206,6 +9206,48 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9206
9206
|
connector_id: this._connectorFlowId,
|
|
9207
9207
|
});
|
|
9208
9208
|
}
|
|
9209
|
+
/**
|
|
9210
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
9211
|
+
*/
|
|
9212
|
+
async pause() {
|
|
9213
|
+
logger$$.debug('pausing_connector', {
|
|
9214
|
+
current_state: this._state,
|
|
9215
|
+
connector_id: this._connectorFlowId,
|
|
9216
|
+
});
|
|
9217
|
+
if (this._state !== ConnectorState.STARTED) {
|
|
9218
|
+
logger$$.debug('connector_pause_invalid_state', {
|
|
9219
|
+
current_state: this._state,
|
|
9220
|
+
connector_id: this._connectorFlowId,
|
|
9221
|
+
});
|
|
9222
|
+
return;
|
|
9223
|
+
}
|
|
9224
|
+
this._setState(ConnectorState.PAUSED);
|
|
9225
|
+
logger$$.debug('connector_paused', {
|
|
9226
|
+
current_state: this._state,
|
|
9227
|
+
connector_id: this._connectorFlowId,
|
|
9228
|
+
});
|
|
9229
|
+
}
|
|
9230
|
+
/**
|
|
9231
|
+
* Resume the connector from paused state
|
|
9232
|
+
*/
|
|
9233
|
+
async resume() {
|
|
9234
|
+
logger$$.debug('resuming_connector', {
|
|
9235
|
+
current_state: this._state,
|
|
9236
|
+
connector_id: this._connectorFlowId,
|
|
9237
|
+
});
|
|
9238
|
+
if (this._state !== ConnectorState.PAUSED) {
|
|
9239
|
+
logger$$.debug('connector_resume_invalid_state', {
|
|
9240
|
+
current_state: this._state,
|
|
9241
|
+
connector_id: this._connectorFlowId,
|
|
9242
|
+
});
|
|
9243
|
+
return;
|
|
9244
|
+
}
|
|
9245
|
+
this._setState(ConnectorState.STARTED);
|
|
9246
|
+
logger$$.debug('connector_resumed', {
|
|
9247
|
+
current_state: this._state,
|
|
9248
|
+
connector_id: this._connectorFlowId,
|
|
9249
|
+
});
|
|
9250
|
+
}
|
|
9209
9251
|
/**
|
|
9210
9252
|
* Close the connector with optional code and reason
|
|
9211
9253
|
*/
|
|
@@ -9541,7 +9583,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9541
9583
|
});
|
|
9542
9584
|
return;
|
|
9543
9585
|
}
|
|
9544
|
-
logger$$.
|
|
9586
|
+
logger$$.debug('connector_shutdown_starting', {
|
|
9545
9587
|
connector_id: this._connectorFlowId,
|
|
9546
9588
|
connector_type: this.constructor.name,
|
|
9547
9589
|
code,
|
|
@@ -9571,19 +9613,19 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9571
9613
|
this._sendPromiseResolve = undefined;
|
|
9572
9614
|
}
|
|
9573
9615
|
// Close transport
|
|
9574
|
-
logger$$.
|
|
9616
|
+
logger$$.debug('connector_closing_transport', {
|
|
9575
9617
|
connector_id: this._connectorFlowId,
|
|
9576
9618
|
connector_type: this.constructor.name,
|
|
9577
9619
|
timestamp: new Date().toISOString(),
|
|
9578
9620
|
});
|
|
9579
9621
|
await this._transportClose(code, reason);
|
|
9580
|
-
logger$$.
|
|
9622
|
+
logger$$.debug('connector_transport_closed', {
|
|
9581
9623
|
connector_id: this._connectorFlowId,
|
|
9582
9624
|
connector_type: this.constructor.name,
|
|
9583
9625
|
timestamp: new Date().toISOString(),
|
|
9584
9626
|
});
|
|
9585
9627
|
// Shutdown spawned tasks
|
|
9586
|
-
logger$$.
|
|
9628
|
+
logger$$.debug('connector_shutting_down_tasks', {
|
|
9587
9629
|
connector_id: this._connectorFlowId,
|
|
9588
9630
|
connector_type: this.constructor.name,
|
|
9589
9631
|
grace_period_ms: effectiveGracePeriod * 1000,
|
|
@@ -9595,7 +9637,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9595
9637
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
9596
9638
|
joinTimeout: this._shutdownJoinTimeout,
|
|
9597
9639
|
});
|
|
9598
|
-
logger$$.
|
|
9640
|
+
logger$$.debug('connector_tasks_shutdown_complete', {
|
|
9599
9641
|
connector_id: this._connectorFlowId,
|
|
9600
9642
|
connector_type: this.constructor.name,
|
|
9601
9643
|
timestamp: new Date().toISOString(),
|
|
@@ -9615,7 +9657,7 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9615
9657
|
if (this._closeResolver) {
|
|
9616
9658
|
this._closeResolver();
|
|
9617
9659
|
}
|
|
9618
|
-
logger$$.
|
|
9660
|
+
logger$$.debug('connector_shutdown_complete', {
|
|
9619
9661
|
connector_id: this._connectorFlowId,
|
|
9620
9662
|
connector_type: this.constructor.name,
|
|
9621
9663
|
final_state: this._state,
|
|
@@ -9756,7 +9798,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9756
9798
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9757
9799
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9758
9800
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9759
|
-
logger$_.
|
|
9801
|
+
logger$_.debug('broadcast_channel_connector_created', {
|
|
9760
9802
|
channel: this.channelName,
|
|
9761
9803
|
connector_id: this.connectorId,
|
|
9762
9804
|
inbox_capacity: preferredCapacity,
|
|
@@ -9837,18 +9879,37 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9837
9879
|
// Setup visibility change monitoring
|
|
9838
9880
|
this.visibilityChangeHandler = () => {
|
|
9839
9881
|
const isHidden = document.hidden;
|
|
9840
|
-
logger$_.
|
|
9882
|
+
logger$_.debug('broadcast_channel_visibility_changed', {
|
|
9841
9883
|
channel: this.channelName,
|
|
9842
9884
|
connector_id: this.connectorId,
|
|
9843
9885
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
9844
9886
|
timestamp: new Date().toISOString(),
|
|
9845
9887
|
});
|
|
9888
|
+
// Pause/resume connector based on visibility
|
|
9889
|
+
if (isHidden && this.state === ConnectorState.STARTED) {
|
|
9890
|
+
this.pause().catch((err) => {
|
|
9891
|
+
logger$_.warning('broadcast_channel_pause_failed', {
|
|
9892
|
+
channel: this.channelName,
|
|
9893
|
+
connector_id: this.connectorId,
|
|
9894
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9895
|
+
});
|
|
9896
|
+
});
|
|
9897
|
+
}
|
|
9898
|
+
else if (!isHidden && this.state === ConnectorState.PAUSED) {
|
|
9899
|
+
this.resume().catch((err) => {
|
|
9900
|
+
logger$_.warning('broadcast_channel_resume_failed', {
|
|
9901
|
+
channel: this.channelName,
|
|
9902
|
+
connector_id: this.connectorId,
|
|
9903
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9904
|
+
});
|
|
9905
|
+
});
|
|
9906
|
+
}
|
|
9846
9907
|
};
|
|
9847
9908
|
if (typeof document !== 'undefined') {
|
|
9848
9909
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
9849
9910
|
this.visibilityChangeListenerRegistered = true;
|
|
9850
9911
|
// Log initial state
|
|
9851
|
-
logger$_.
|
|
9912
|
+
logger$_.debug('broadcast_channel_initial_visibility', {
|
|
9852
9913
|
channel: this.channelName,
|
|
9853
9914
|
connector_id: this.connectorId,
|
|
9854
9915
|
visibility: document.hidden ? 'hidden' : 'visible',
|
|
@@ -9898,7 +9959,7 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9898
9959
|
return await this.inbox.dequeue();
|
|
9899
9960
|
}
|
|
9900
9961
|
async _transportClose(code, reason) {
|
|
9901
|
-
logger$_.
|
|
9962
|
+
logger$_.debug('broadcast_channel_transport_closing', {
|
|
9902
9963
|
channel: this.channelName,
|
|
9903
9964
|
connector_id: this.connectorId,
|
|
9904
9965
|
code,
|
|
@@ -9907,14 +9968,14 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9907
9968
|
timestamp: new Date().toISOString(),
|
|
9908
9969
|
});
|
|
9909
9970
|
if (this.listenerRegistered) {
|
|
9910
|
-
logger$_.
|
|
9971
|
+
logger$_.debug('broadcast_channel_removing_listener', {
|
|
9911
9972
|
channel: this.channelName,
|
|
9912
9973
|
connector_id: this.connectorId,
|
|
9913
9974
|
timestamp: new Date().toISOString(),
|
|
9914
9975
|
});
|
|
9915
9976
|
this.channel.removeEventListener('message', this.onMsg);
|
|
9916
9977
|
this.listenerRegistered = false;
|
|
9917
|
-
logger$_.
|
|
9978
|
+
logger$_.debug('broadcast_channel_listener_removed', {
|
|
9918
9979
|
channel: this.channelName,
|
|
9919
9980
|
connector_id: this.connectorId,
|
|
9920
9981
|
timestamp: new Date().toISOString(),
|
|
@@ -9925,13 +9986,13 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9925
9986
|
this.visibilityChangeListenerRegistered = false;
|
|
9926
9987
|
this.visibilityChangeHandler = undefined;
|
|
9927
9988
|
}
|
|
9928
|
-
logger$_.
|
|
9989
|
+
logger$_.debug('broadcast_channel_closing', {
|
|
9929
9990
|
channel: this.channelName,
|
|
9930
9991
|
connector_id: this.connectorId,
|
|
9931
9992
|
timestamp: new Date().toISOString(),
|
|
9932
9993
|
});
|
|
9933
9994
|
this.channel.close();
|
|
9934
|
-
logger$_.
|
|
9995
|
+
logger$_.debug('broadcast_channel_closed', {
|
|
9935
9996
|
channel: this.channelName,
|
|
9936
9997
|
connector_id: this.connectorId,
|
|
9937
9998
|
timestamp: new Date().toISOString(),
|
|
@@ -10022,6 +10083,28 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
10022
10083
|
}
|
|
10023
10084
|
return undefined;
|
|
10024
10085
|
}
|
|
10086
|
+
/**
|
|
10087
|
+
* Override start() to check initial visibility state
|
|
10088
|
+
*/
|
|
10089
|
+
async start(inboundHandler) {
|
|
10090
|
+
await super.start(inboundHandler);
|
|
10091
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
10092
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
10093
|
+
logger$_.debug('broadcast_channel_start_in_hidden_tab', {
|
|
10094
|
+
channel: this.channelName,
|
|
10095
|
+
connector_id: this.connectorId,
|
|
10096
|
+
timestamp: new Date().toISOString(),
|
|
10097
|
+
});
|
|
10098
|
+
// Immediately pause if tab is hidden at start time
|
|
10099
|
+
await this.pause().catch((err) => {
|
|
10100
|
+
logger$_.warning('broadcast_channel_initial_pause_failed', {
|
|
10101
|
+
channel: this.channelName,
|
|
10102
|
+
connector_id: this.connectorId,
|
|
10103
|
+
error: err instanceof Error ? err.message : String(err),
|
|
10104
|
+
});
|
|
10105
|
+
});
|
|
10106
|
+
}
|
|
10107
|
+
}
|
|
10025
10108
|
_trimSeenAcks(now) {
|
|
10026
10109
|
while (this.seenAckOrder.length > 0) {
|
|
10027
10110
|
const candidate = this.seenAckOrder[0];
|
|
@@ -10732,6 +10815,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10732
10815
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
10733
10816
|
break;
|
|
10734
10817
|
}
|
|
10818
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
10819
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
10820
|
+
if (connector.state === ConnectorState.PAUSED) {
|
|
10821
|
+
logger$Z.debug('skipping_heartbeat_connector_paused', {
|
|
10822
|
+
connector_state: connector.state,
|
|
10823
|
+
});
|
|
10824
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
10825
|
+
continue;
|
|
10826
|
+
}
|
|
10735
10827
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
10736
10828
|
logger$Z.debug('sending_heartbeat', {
|
|
10737
10829
|
hb_corr_id: envelope.corrId,
|
|
@@ -10753,6 +10845,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10753
10845
|
throw error;
|
|
10754
10846
|
}
|
|
10755
10847
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
10848
|
+
// Don't check heartbeat timeout when paused
|
|
10756
10849
|
if (this.lastHeartbeatAckTime !== null &&
|
|
10757
10850
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
10758
10851
|
throw new FameConnectError('missed heartbeat acknowledgement');
|