@naylence/runtime 0.3.5-test.933 → 0.3.5-test.936
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 +178 -4
- package/dist/browser/index.mjs +178 -4
- package/dist/cjs/naylence/fame/connector/base-async-connector.js +92 -0
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +59 -1
- package/dist/cjs/naylence/fame/node/upstream-session-manager.js +26 -1
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/base-async-connector.js +92 -0
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +59 -1
- package/dist/esm/naylence/fame/node/upstream-session-manager.js +27 -2
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +178 -4
- package/dist/node/index.mjs +178 -4
- package/dist/node/node.cjs +178 -4
- package/dist/node/node.mjs +178 -4
- package/dist/types/naylence/fame/connector/base-async-connector.d.ts +8 -0
- 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.936
|
|
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.936';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9186,6 +9186,10 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9186
9186
|
* Stop the connector gracefully
|
|
9187
9187
|
*/
|
|
9188
9188
|
async stop() {
|
|
9189
|
+
logger$$.debug('stopping_connector', {
|
|
9190
|
+
current_state: this._state,
|
|
9191
|
+
connector_id: this._connectorFlowId,
|
|
9192
|
+
});
|
|
9189
9193
|
if (!core.ConnectorStateUtils.canStop(this._state)) {
|
|
9190
9194
|
logger$$.debug('connector_stop_already_stopped', {
|
|
9191
9195
|
current_state: this._state,
|
|
@@ -9198,6 +9202,52 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9198
9202
|
if (this._lastError) {
|
|
9199
9203
|
throw this._lastError;
|
|
9200
9204
|
}
|
|
9205
|
+
logger$$.debug('connector_stopped', {
|
|
9206
|
+
current_state: this._state,
|
|
9207
|
+
connector_id: this._connectorFlowId,
|
|
9208
|
+
});
|
|
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
|
+
});
|
|
9201
9251
|
}
|
|
9202
9252
|
/**
|
|
9203
9253
|
* Close the connector with optional code and reason
|
|
@@ -9528,8 +9578,21 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9528
9578
|
*/
|
|
9529
9579
|
async _shutdown(code, reason, gracePeriod, exc) {
|
|
9530
9580
|
if (this._closed) {
|
|
9581
|
+
logger$$.debug('shutdown_already_closed', {
|
|
9582
|
+
connector_id: this._connectorFlowId,
|
|
9583
|
+
current_state: this._state,
|
|
9584
|
+
});
|
|
9531
9585
|
return;
|
|
9532
9586
|
}
|
|
9587
|
+
logger$$.info('connector_shutdown_starting', {
|
|
9588
|
+
connector_id: this._connectorFlowId,
|
|
9589
|
+
connector_type: this.constructor.name,
|
|
9590
|
+
code,
|
|
9591
|
+
reason,
|
|
9592
|
+
current_state: this._state,
|
|
9593
|
+
has_error: !!exc,
|
|
9594
|
+
timestamp: new Date().toISOString(),
|
|
9595
|
+
});
|
|
9533
9596
|
this._closed = true;
|
|
9534
9597
|
this._closeCode = code;
|
|
9535
9598
|
this._closeReason = reason;
|
|
@@ -9551,16 +9614,39 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9551
9614
|
this._sendPromiseResolve = undefined;
|
|
9552
9615
|
}
|
|
9553
9616
|
// Close transport
|
|
9617
|
+
logger$$.info('connector_closing_transport', {
|
|
9618
|
+
connector_id: this._connectorFlowId,
|
|
9619
|
+
connector_type: this.constructor.name,
|
|
9620
|
+
timestamp: new Date().toISOString(),
|
|
9621
|
+
});
|
|
9554
9622
|
await this._transportClose(code, reason);
|
|
9623
|
+
logger$$.info('connector_transport_closed', {
|
|
9624
|
+
connector_id: this._connectorFlowId,
|
|
9625
|
+
connector_type: this.constructor.name,
|
|
9626
|
+
timestamp: new Date().toISOString(),
|
|
9627
|
+
});
|
|
9555
9628
|
// Shutdown spawned tasks
|
|
9629
|
+
logger$$.info('connector_shutting_down_tasks', {
|
|
9630
|
+
connector_id: this._connectorFlowId,
|
|
9631
|
+
connector_type: this.constructor.name,
|
|
9632
|
+
grace_period_ms: effectiveGracePeriod * 1000,
|
|
9633
|
+
join_timeout_ms: this._shutdownJoinTimeout,
|
|
9634
|
+
timestamp: new Date().toISOString(),
|
|
9635
|
+
});
|
|
9556
9636
|
try {
|
|
9557
9637
|
await this.shutdownTasks({
|
|
9558
9638
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
9559
9639
|
joinTimeout: this._shutdownJoinTimeout,
|
|
9560
9640
|
});
|
|
9641
|
+
logger$$.info('connector_tasks_shutdown_complete', {
|
|
9642
|
+
connector_id: this._connectorFlowId,
|
|
9643
|
+
connector_type: this.constructor.name,
|
|
9644
|
+
timestamp: new Date().toISOString(),
|
|
9645
|
+
});
|
|
9561
9646
|
}
|
|
9562
9647
|
catch (error) {
|
|
9563
9648
|
logger$$.warning('task_shutdown_error', {
|
|
9649
|
+
connector_id: this._connectorFlowId,
|
|
9564
9650
|
error: error instanceof Error ? error.message : String(error),
|
|
9565
9651
|
});
|
|
9566
9652
|
}
|
|
@@ -9572,6 +9658,12 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9572
9658
|
if (this._closeResolver) {
|
|
9573
9659
|
this._closeResolver();
|
|
9574
9660
|
}
|
|
9661
|
+
logger$$.info('connector_shutdown_complete', {
|
|
9662
|
+
connector_id: this._connectorFlowId,
|
|
9663
|
+
connector_type: this.constructor.name,
|
|
9664
|
+
final_state: this._state,
|
|
9665
|
+
timestamp: new Date().toISOString(),
|
|
9666
|
+
});
|
|
9575
9667
|
}
|
|
9576
9668
|
/**
|
|
9577
9669
|
* Close the underlying transport
|
|
@@ -9707,12 +9799,22 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9707
9799
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9708
9800
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9709
9801
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9710
|
-
logger$_.
|
|
9802
|
+
logger$_.info('broadcast_channel_connector_created', {
|
|
9711
9803
|
channel: this.channelName,
|
|
9712
9804
|
connector_id: this.connectorId,
|
|
9713
9805
|
inbox_capacity: preferredCapacity,
|
|
9806
|
+
timestamp: new Date().toISOString(),
|
|
9714
9807
|
});
|
|
9715
9808
|
this.onMsg = (event) => {
|
|
9809
|
+
// Guard: Don't process if listener was unregistered
|
|
9810
|
+
if (!this.listenerRegistered) {
|
|
9811
|
+
logger$_.warning('broadcast_channel_message_after_unregister', {
|
|
9812
|
+
channel: this.channelName,
|
|
9813
|
+
connector_id: this.connectorId,
|
|
9814
|
+
timestamp: new Date().toISOString(),
|
|
9815
|
+
});
|
|
9816
|
+
return;
|
|
9817
|
+
}
|
|
9716
9818
|
const message = event.data;
|
|
9717
9819
|
logger$_.debug('broadcast_channel_raw_event', {
|
|
9718
9820
|
channel: this.channelName,
|
|
@@ -9784,6 +9886,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9784
9886
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
9785
9887
|
timestamp: new Date().toISOString(),
|
|
9786
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
|
+
}
|
|
9787
9908
|
};
|
|
9788
9909
|
if (typeof document !== 'undefined') {
|
|
9789
9910
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
@@ -9839,16 +9960,44 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9839
9960
|
return await this.inbox.dequeue();
|
|
9840
9961
|
}
|
|
9841
9962
|
async _transportClose(code, reason) {
|
|
9963
|
+
logger$_.info('broadcast_channel_transport_closing', {
|
|
9964
|
+
channel: this.channelName,
|
|
9965
|
+
connector_id: this.connectorId,
|
|
9966
|
+
code,
|
|
9967
|
+
reason,
|
|
9968
|
+
listener_registered: this.listenerRegistered,
|
|
9969
|
+
timestamp: new Date().toISOString(),
|
|
9970
|
+
});
|
|
9842
9971
|
if (this.listenerRegistered) {
|
|
9972
|
+
logger$_.info('broadcast_channel_removing_listener', {
|
|
9973
|
+
channel: this.channelName,
|
|
9974
|
+
connector_id: this.connectorId,
|
|
9975
|
+
timestamp: new Date().toISOString(),
|
|
9976
|
+
});
|
|
9843
9977
|
this.channel.removeEventListener('message', this.onMsg);
|
|
9844
9978
|
this.listenerRegistered = false;
|
|
9979
|
+
logger$_.info('broadcast_channel_listener_removed', {
|
|
9980
|
+
channel: this.channelName,
|
|
9981
|
+
connector_id: this.connectorId,
|
|
9982
|
+
timestamp: new Date().toISOString(),
|
|
9983
|
+
});
|
|
9845
9984
|
}
|
|
9846
9985
|
if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
9847
9986
|
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
9848
9987
|
this.visibilityChangeListenerRegistered = false;
|
|
9849
9988
|
this.visibilityChangeHandler = undefined;
|
|
9850
9989
|
}
|
|
9990
|
+
logger$_.info('broadcast_channel_closing', {
|
|
9991
|
+
channel: this.channelName,
|
|
9992
|
+
connector_id: this.connectorId,
|
|
9993
|
+
timestamp: new Date().toISOString(),
|
|
9994
|
+
});
|
|
9851
9995
|
this.channel.close();
|
|
9996
|
+
logger$_.info('broadcast_channel_closed', {
|
|
9997
|
+
channel: this.channelName,
|
|
9998
|
+
connector_id: this.connectorId,
|
|
9999
|
+
timestamp: new Date().toISOString(),
|
|
10000
|
+
});
|
|
9852
10001
|
const closeCode = typeof code === 'number' ? code : 1000;
|
|
9853
10002
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
9854
10003
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
@@ -10496,7 +10645,22 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10496
10645
|
this.currentStopSubtasks = null;
|
|
10497
10646
|
await Promise.allSettled(tasks.map((task) => task.promise));
|
|
10498
10647
|
if (this.connector) {
|
|
10499
|
-
|
|
10648
|
+
logger$Z.info('upstream_stopping_old_connector', {
|
|
10649
|
+
connect_epoch: this.connectEpoch,
|
|
10650
|
+
target_system_id: this.targetSystemId,
|
|
10651
|
+
timestamp: new Date().toISOString(),
|
|
10652
|
+
});
|
|
10653
|
+
await this.connector.stop().catch((err) => {
|
|
10654
|
+
logger$Z.warning('upstream_connector_stop_error', {
|
|
10655
|
+
connect_epoch: this.connectEpoch,
|
|
10656
|
+
error: err instanceof Error ? err.message : String(err),
|
|
10657
|
+
});
|
|
10658
|
+
});
|
|
10659
|
+
logger$Z.info('upstream_old_connector_stopped', {
|
|
10660
|
+
connect_epoch: this.connectEpoch,
|
|
10661
|
+
target_system_id: this.targetSystemId,
|
|
10662
|
+
timestamp: new Date().toISOString(),
|
|
10663
|
+
});
|
|
10500
10664
|
this.connector = null;
|
|
10501
10665
|
}
|
|
10502
10666
|
}
|
|
@@ -10630,6 +10794,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10630
10794
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
10631
10795
|
break;
|
|
10632
10796
|
}
|
|
10797
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
10798
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
10799
|
+
if (connector.state === core.ConnectorState.PAUSED) {
|
|
10800
|
+
logger$Z.debug('skipping_heartbeat_connector_paused', {
|
|
10801
|
+
connector_state: connector.state,
|
|
10802
|
+
});
|
|
10803
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
10804
|
+
continue;
|
|
10805
|
+
}
|
|
10633
10806
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
10634
10807
|
logger$Z.debug('sending_heartbeat', {
|
|
10635
10808
|
hb_corr_id: envelope.corrId,
|
|
@@ -10651,6 +10824,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10651
10824
|
throw error;
|
|
10652
10825
|
}
|
|
10653
10826
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
10827
|
+
// Don't check heartbeat timeout when paused
|
|
10654
10828
|
if (this.lastHeartbeatAckTime !== null &&
|
|
10655
10829
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
10656
10830
|
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.936
|
|
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.936';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9185,6 +9185,10 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9185
9185
|
* Stop the connector gracefully
|
|
9186
9186
|
*/
|
|
9187
9187
|
async stop() {
|
|
9188
|
+
logger$$.debug('stopping_connector', {
|
|
9189
|
+
current_state: this._state,
|
|
9190
|
+
connector_id: this._connectorFlowId,
|
|
9191
|
+
});
|
|
9188
9192
|
if (!ConnectorStateUtils.canStop(this._state)) {
|
|
9189
9193
|
logger$$.debug('connector_stop_already_stopped', {
|
|
9190
9194
|
current_state: this._state,
|
|
@@ -9197,6 +9201,52 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9197
9201
|
if (this._lastError) {
|
|
9198
9202
|
throw this._lastError;
|
|
9199
9203
|
}
|
|
9204
|
+
logger$$.debug('connector_stopped', {
|
|
9205
|
+
current_state: this._state,
|
|
9206
|
+
connector_id: this._connectorFlowId,
|
|
9207
|
+
});
|
|
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
|
+
});
|
|
9200
9250
|
}
|
|
9201
9251
|
/**
|
|
9202
9252
|
* Close the connector with optional code and reason
|
|
@@ -9527,8 +9577,21 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9527
9577
|
*/
|
|
9528
9578
|
async _shutdown(code, reason, gracePeriod, exc) {
|
|
9529
9579
|
if (this._closed) {
|
|
9580
|
+
logger$$.debug('shutdown_already_closed', {
|
|
9581
|
+
connector_id: this._connectorFlowId,
|
|
9582
|
+
current_state: this._state,
|
|
9583
|
+
});
|
|
9530
9584
|
return;
|
|
9531
9585
|
}
|
|
9586
|
+
logger$$.info('connector_shutdown_starting', {
|
|
9587
|
+
connector_id: this._connectorFlowId,
|
|
9588
|
+
connector_type: this.constructor.name,
|
|
9589
|
+
code,
|
|
9590
|
+
reason,
|
|
9591
|
+
current_state: this._state,
|
|
9592
|
+
has_error: !!exc,
|
|
9593
|
+
timestamp: new Date().toISOString(),
|
|
9594
|
+
});
|
|
9532
9595
|
this._closed = true;
|
|
9533
9596
|
this._closeCode = code;
|
|
9534
9597
|
this._closeReason = reason;
|
|
@@ -9550,16 +9613,39 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9550
9613
|
this._sendPromiseResolve = undefined;
|
|
9551
9614
|
}
|
|
9552
9615
|
// Close transport
|
|
9616
|
+
logger$$.info('connector_closing_transport', {
|
|
9617
|
+
connector_id: this._connectorFlowId,
|
|
9618
|
+
connector_type: this.constructor.name,
|
|
9619
|
+
timestamp: new Date().toISOString(),
|
|
9620
|
+
});
|
|
9553
9621
|
await this._transportClose(code, reason);
|
|
9622
|
+
logger$$.info('connector_transport_closed', {
|
|
9623
|
+
connector_id: this._connectorFlowId,
|
|
9624
|
+
connector_type: this.constructor.name,
|
|
9625
|
+
timestamp: new Date().toISOString(),
|
|
9626
|
+
});
|
|
9554
9627
|
// Shutdown spawned tasks
|
|
9628
|
+
logger$$.info('connector_shutting_down_tasks', {
|
|
9629
|
+
connector_id: this._connectorFlowId,
|
|
9630
|
+
connector_type: this.constructor.name,
|
|
9631
|
+
grace_period_ms: effectiveGracePeriod * 1000,
|
|
9632
|
+
join_timeout_ms: this._shutdownJoinTimeout,
|
|
9633
|
+
timestamp: new Date().toISOString(),
|
|
9634
|
+
});
|
|
9555
9635
|
try {
|
|
9556
9636
|
await this.shutdownTasks({
|
|
9557
9637
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
9558
9638
|
joinTimeout: this._shutdownJoinTimeout,
|
|
9559
9639
|
});
|
|
9640
|
+
logger$$.info('connector_tasks_shutdown_complete', {
|
|
9641
|
+
connector_id: this._connectorFlowId,
|
|
9642
|
+
connector_type: this.constructor.name,
|
|
9643
|
+
timestamp: new Date().toISOString(),
|
|
9644
|
+
});
|
|
9560
9645
|
}
|
|
9561
9646
|
catch (error) {
|
|
9562
9647
|
logger$$.warning('task_shutdown_error', {
|
|
9648
|
+
connector_id: this._connectorFlowId,
|
|
9563
9649
|
error: error instanceof Error ? error.message : String(error),
|
|
9564
9650
|
});
|
|
9565
9651
|
}
|
|
@@ -9571,6 +9657,12 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9571
9657
|
if (this._closeResolver) {
|
|
9572
9658
|
this._closeResolver();
|
|
9573
9659
|
}
|
|
9660
|
+
logger$$.info('connector_shutdown_complete', {
|
|
9661
|
+
connector_id: this._connectorFlowId,
|
|
9662
|
+
connector_type: this.constructor.name,
|
|
9663
|
+
final_state: this._state,
|
|
9664
|
+
timestamp: new Date().toISOString(),
|
|
9665
|
+
});
|
|
9574
9666
|
}
|
|
9575
9667
|
/**
|
|
9576
9668
|
* Close the underlying transport
|
|
@@ -9706,12 +9798,22 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9706
9798
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9707
9799
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9708
9800
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9709
|
-
logger$_.
|
|
9801
|
+
logger$_.info('broadcast_channel_connector_created', {
|
|
9710
9802
|
channel: this.channelName,
|
|
9711
9803
|
connector_id: this.connectorId,
|
|
9712
9804
|
inbox_capacity: preferredCapacity,
|
|
9805
|
+
timestamp: new Date().toISOString(),
|
|
9713
9806
|
});
|
|
9714
9807
|
this.onMsg = (event) => {
|
|
9808
|
+
// Guard: Don't process if listener was unregistered
|
|
9809
|
+
if (!this.listenerRegistered) {
|
|
9810
|
+
logger$_.warning('broadcast_channel_message_after_unregister', {
|
|
9811
|
+
channel: this.channelName,
|
|
9812
|
+
connector_id: this.connectorId,
|
|
9813
|
+
timestamp: new Date().toISOString(),
|
|
9814
|
+
});
|
|
9815
|
+
return;
|
|
9816
|
+
}
|
|
9715
9817
|
const message = event.data;
|
|
9716
9818
|
logger$_.debug('broadcast_channel_raw_event', {
|
|
9717
9819
|
channel: this.channelName,
|
|
@@ -9783,6 +9885,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9783
9885
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
9784
9886
|
timestamp: new Date().toISOString(),
|
|
9785
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
|
+
}
|
|
9786
9907
|
};
|
|
9787
9908
|
if (typeof document !== 'undefined') {
|
|
9788
9909
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
@@ -9838,16 +9959,44 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9838
9959
|
return await this.inbox.dequeue();
|
|
9839
9960
|
}
|
|
9840
9961
|
async _transportClose(code, reason) {
|
|
9962
|
+
logger$_.info('broadcast_channel_transport_closing', {
|
|
9963
|
+
channel: this.channelName,
|
|
9964
|
+
connector_id: this.connectorId,
|
|
9965
|
+
code,
|
|
9966
|
+
reason,
|
|
9967
|
+
listener_registered: this.listenerRegistered,
|
|
9968
|
+
timestamp: new Date().toISOString(),
|
|
9969
|
+
});
|
|
9841
9970
|
if (this.listenerRegistered) {
|
|
9971
|
+
logger$_.info('broadcast_channel_removing_listener', {
|
|
9972
|
+
channel: this.channelName,
|
|
9973
|
+
connector_id: this.connectorId,
|
|
9974
|
+
timestamp: new Date().toISOString(),
|
|
9975
|
+
});
|
|
9842
9976
|
this.channel.removeEventListener('message', this.onMsg);
|
|
9843
9977
|
this.listenerRegistered = false;
|
|
9978
|
+
logger$_.info('broadcast_channel_listener_removed', {
|
|
9979
|
+
channel: this.channelName,
|
|
9980
|
+
connector_id: this.connectorId,
|
|
9981
|
+
timestamp: new Date().toISOString(),
|
|
9982
|
+
});
|
|
9844
9983
|
}
|
|
9845
9984
|
if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
9846
9985
|
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
9847
9986
|
this.visibilityChangeListenerRegistered = false;
|
|
9848
9987
|
this.visibilityChangeHandler = undefined;
|
|
9849
9988
|
}
|
|
9989
|
+
logger$_.info('broadcast_channel_closing', {
|
|
9990
|
+
channel: this.channelName,
|
|
9991
|
+
connector_id: this.connectorId,
|
|
9992
|
+
timestamp: new Date().toISOString(),
|
|
9993
|
+
});
|
|
9850
9994
|
this.channel.close();
|
|
9995
|
+
logger$_.info('broadcast_channel_closed', {
|
|
9996
|
+
channel: this.channelName,
|
|
9997
|
+
connector_id: this.connectorId,
|
|
9998
|
+
timestamp: new Date().toISOString(),
|
|
9999
|
+
});
|
|
9851
10000
|
const closeCode = typeof code === 'number' ? code : 1000;
|
|
9852
10001
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
9853
10002
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
@@ -10495,7 +10644,22 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10495
10644
|
this.currentStopSubtasks = null;
|
|
10496
10645
|
await Promise.allSettled(tasks.map((task) => task.promise));
|
|
10497
10646
|
if (this.connector) {
|
|
10498
|
-
|
|
10647
|
+
logger$Z.info('upstream_stopping_old_connector', {
|
|
10648
|
+
connect_epoch: this.connectEpoch,
|
|
10649
|
+
target_system_id: this.targetSystemId,
|
|
10650
|
+
timestamp: new Date().toISOString(),
|
|
10651
|
+
});
|
|
10652
|
+
await this.connector.stop().catch((err) => {
|
|
10653
|
+
logger$Z.warning('upstream_connector_stop_error', {
|
|
10654
|
+
connect_epoch: this.connectEpoch,
|
|
10655
|
+
error: err instanceof Error ? err.message : String(err),
|
|
10656
|
+
});
|
|
10657
|
+
});
|
|
10658
|
+
logger$Z.info('upstream_old_connector_stopped', {
|
|
10659
|
+
connect_epoch: this.connectEpoch,
|
|
10660
|
+
target_system_id: this.targetSystemId,
|
|
10661
|
+
timestamp: new Date().toISOString(),
|
|
10662
|
+
});
|
|
10499
10663
|
this.connector = null;
|
|
10500
10664
|
}
|
|
10501
10665
|
}
|
|
@@ -10629,6 +10793,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10629
10793
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
10630
10794
|
break;
|
|
10631
10795
|
}
|
|
10796
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
10797
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
10798
|
+
if (connector.state === ConnectorState.PAUSED) {
|
|
10799
|
+
logger$Z.debug('skipping_heartbeat_connector_paused', {
|
|
10800
|
+
connector_state: connector.state,
|
|
10801
|
+
});
|
|
10802
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
10803
|
+
continue;
|
|
10804
|
+
}
|
|
10632
10805
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
10633
10806
|
logger$Z.debug('sending_heartbeat', {
|
|
10634
10807
|
hb_corr_id: envelope.corrId,
|
|
@@ -10650,6 +10823,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10650
10823
|
throw error;
|
|
10651
10824
|
}
|
|
10652
10825
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
10826
|
+
// Don't check heartbeat timeout when paused
|
|
10653
10827
|
if (this.lastHeartbeatAckTime !== null &&
|
|
10654
10828
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
10655
10829
|
throw new FameConnectError('missed heartbeat acknowledgement');
|