@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/browser/index.cjs
CHANGED
|
@@ -98,12 +98,12 @@ installProcessEnvShim();
|
|
|
98
98
|
// --- END ENV SHIM ---
|
|
99
99
|
|
|
100
100
|
// This file is auto-generated during build - do not edit manually
|
|
101
|
-
// Generated from package.json version: 0.3.5-test.
|
|
101
|
+
// Generated from package.json version: 0.3.5-test.936
|
|
102
102
|
/**
|
|
103
103
|
* The package version, injected at build time.
|
|
104
104
|
* @internal
|
|
105
105
|
*/
|
|
106
|
-
const VERSION = '0.3.5-test.
|
|
106
|
+
const VERSION = '0.3.5-test.936';
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9270,6 +9270,10 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9270
9270
|
* Stop the connector gracefully
|
|
9271
9271
|
*/
|
|
9272
9272
|
async stop() {
|
|
9273
|
+
logger$$.debug('stopping_connector', {
|
|
9274
|
+
current_state: this._state,
|
|
9275
|
+
connector_id: this._connectorFlowId,
|
|
9276
|
+
});
|
|
9273
9277
|
if (!core.ConnectorStateUtils.canStop(this._state)) {
|
|
9274
9278
|
logger$$.debug('connector_stop_already_stopped', {
|
|
9275
9279
|
current_state: this._state,
|
|
@@ -9282,6 +9286,52 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9282
9286
|
if (this._lastError) {
|
|
9283
9287
|
throw this._lastError;
|
|
9284
9288
|
}
|
|
9289
|
+
logger$$.debug('connector_stopped', {
|
|
9290
|
+
current_state: this._state,
|
|
9291
|
+
connector_id: this._connectorFlowId,
|
|
9292
|
+
});
|
|
9293
|
+
}
|
|
9294
|
+
/**
|
|
9295
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
9296
|
+
*/
|
|
9297
|
+
async pause() {
|
|
9298
|
+
logger$$.debug('pausing_connector', {
|
|
9299
|
+
current_state: this._state,
|
|
9300
|
+
connector_id: this._connectorFlowId,
|
|
9301
|
+
});
|
|
9302
|
+
if (this._state !== core.ConnectorState.STARTED) {
|
|
9303
|
+
logger$$.debug('connector_pause_invalid_state', {
|
|
9304
|
+
current_state: this._state,
|
|
9305
|
+
connector_id: this._connectorFlowId,
|
|
9306
|
+
});
|
|
9307
|
+
return;
|
|
9308
|
+
}
|
|
9309
|
+
this._setState(core.ConnectorState.PAUSED);
|
|
9310
|
+
logger$$.debug('connector_paused', {
|
|
9311
|
+
current_state: this._state,
|
|
9312
|
+
connector_id: this._connectorFlowId,
|
|
9313
|
+
});
|
|
9314
|
+
}
|
|
9315
|
+
/**
|
|
9316
|
+
* Resume the connector from paused state
|
|
9317
|
+
*/
|
|
9318
|
+
async resume() {
|
|
9319
|
+
logger$$.debug('resuming_connector', {
|
|
9320
|
+
current_state: this._state,
|
|
9321
|
+
connector_id: this._connectorFlowId,
|
|
9322
|
+
});
|
|
9323
|
+
if (this._state !== core.ConnectorState.PAUSED) {
|
|
9324
|
+
logger$$.debug('connector_resume_invalid_state', {
|
|
9325
|
+
current_state: this._state,
|
|
9326
|
+
connector_id: this._connectorFlowId,
|
|
9327
|
+
});
|
|
9328
|
+
return;
|
|
9329
|
+
}
|
|
9330
|
+
this._setState(core.ConnectorState.STARTED);
|
|
9331
|
+
logger$$.debug('connector_resumed', {
|
|
9332
|
+
current_state: this._state,
|
|
9333
|
+
connector_id: this._connectorFlowId,
|
|
9334
|
+
});
|
|
9285
9335
|
}
|
|
9286
9336
|
/**
|
|
9287
9337
|
* Close the connector with optional code and reason
|
|
@@ -9612,8 +9662,21 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9612
9662
|
*/
|
|
9613
9663
|
async _shutdown(code, reason, gracePeriod, exc) {
|
|
9614
9664
|
if (this._closed) {
|
|
9665
|
+
logger$$.debug('shutdown_already_closed', {
|
|
9666
|
+
connector_id: this._connectorFlowId,
|
|
9667
|
+
current_state: this._state,
|
|
9668
|
+
});
|
|
9615
9669
|
return;
|
|
9616
9670
|
}
|
|
9671
|
+
logger$$.info('connector_shutdown_starting', {
|
|
9672
|
+
connector_id: this._connectorFlowId,
|
|
9673
|
+
connector_type: this.constructor.name,
|
|
9674
|
+
code,
|
|
9675
|
+
reason,
|
|
9676
|
+
current_state: this._state,
|
|
9677
|
+
has_error: !!exc,
|
|
9678
|
+
timestamp: new Date().toISOString(),
|
|
9679
|
+
});
|
|
9617
9680
|
this._closed = true;
|
|
9618
9681
|
this._closeCode = code;
|
|
9619
9682
|
this._closeReason = reason;
|
|
@@ -9635,16 +9698,39 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9635
9698
|
this._sendPromiseResolve = undefined;
|
|
9636
9699
|
}
|
|
9637
9700
|
// Close transport
|
|
9701
|
+
logger$$.info('connector_closing_transport', {
|
|
9702
|
+
connector_id: this._connectorFlowId,
|
|
9703
|
+
connector_type: this.constructor.name,
|
|
9704
|
+
timestamp: new Date().toISOString(),
|
|
9705
|
+
});
|
|
9638
9706
|
await this._transportClose(code, reason);
|
|
9707
|
+
logger$$.info('connector_transport_closed', {
|
|
9708
|
+
connector_id: this._connectorFlowId,
|
|
9709
|
+
connector_type: this.constructor.name,
|
|
9710
|
+
timestamp: new Date().toISOString(),
|
|
9711
|
+
});
|
|
9639
9712
|
// Shutdown spawned tasks
|
|
9713
|
+
logger$$.info('connector_shutting_down_tasks', {
|
|
9714
|
+
connector_id: this._connectorFlowId,
|
|
9715
|
+
connector_type: this.constructor.name,
|
|
9716
|
+
grace_period_ms: effectiveGracePeriod * 1000,
|
|
9717
|
+
join_timeout_ms: this._shutdownJoinTimeout,
|
|
9718
|
+
timestamp: new Date().toISOString(),
|
|
9719
|
+
});
|
|
9640
9720
|
try {
|
|
9641
9721
|
await this.shutdownTasks({
|
|
9642
9722
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
9643
9723
|
joinTimeout: this._shutdownJoinTimeout,
|
|
9644
9724
|
});
|
|
9725
|
+
logger$$.info('connector_tasks_shutdown_complete', {
|
|
9726
|
+
connector_id: this._connectorFlowId,
|
|
9727
|
+
connector_type: this.constructor.name,
|
|
9728
|
+
timestamp: new Date().toISOString(),
|
|
9729
|
+
});
|
|
9645
9730
|
}
|
|
9646
9731
|
catch (error) {
|
|
9647
9732
|
logger$$.warning('task_shutdown_error', {
|
|
9733
|
+
connector_id: this._connectorFlowId,
|
|
9648
9734
|
error: error instanceof Error ? error.message : String(error),
|
|
9649
9735
|
});
|
|
9650
9736
|
}
|
|
@@ -9656,6 +9742,12 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9656
9742
|
if (this._closeResolver) {
|
|
9657
9743
|
this._closeResolver();
|
|
9658
9744
|
}
|
|
9745
|
+
logger$$.info('connector_shutdown_complete', {
|
|
9746
|
+
connector_id: this._connectorFlowId,
|
|
9747
|
+
connector_type: this.constructor.name,
|
|
9748
|
+
final_state: this._state,
|
|
9749
|
+
timestamp: new Date().toISOString(),
|
|
9750
|
+
});
|
|
9659
9751
|
}
|
|
9660
9752
|
/**
|
|
9661
9753
|
* Close the underlying transport
|
|
@@ -9791,12 +9883,22 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9791
9883
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9792
9884
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9793
9885
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9794
|
-
logger$_.
|
|
9886
|
+
logger$_.info('broadcast_channel_connector_created', {
|
|
9795
9887
|
channel: this.channelName,
|
|
9796
9888
|
connector_id: this.connectorId,
|
|
9797
9889
|
inbox_capacity: preferredCapacity,
|
|
9890
|
+
timestamp: new Date().toISOString(),
|
|
9798
9891
|
});
|
|
9799
9892
|
this.onMsg = (event) => {
|
|
9893
|
+
// Guard: Don't process if listener was unregistered
|
|
9894
|
+
if (!this.listenerRegistered) {
|
|
9895
|
+
logger$_.warning('broadcast_channel_message_after_unregister', {
|
|
9896
|
+
channel: this.channelName,
|
|
9897
|
+
connector_id: this.connectorId,
|
|
9898
|
+
timestamp: new Date().toISOString(),
|
|
9899
|
+
});
|
|
9900
|
+
return;
|
|
9901
|
+
}
|
|
9800
9902
|
const message = event.data;
|
|
9801
9903
|
logger$_.debug('broadcast_channel_raw_event', {
|
|
9802
9904
|
channel: this.channelName,
|
|
@@ -9868,6 +9970,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9868
9970
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
9869
9971
|
timestamp: new Date().toISOString(),
|
|
9870
9972
|
});
|
|
9973
|
+
// Pause/resume connector based on visibility
|
|
9974
|
+
if (isHidden && this.state === core.ConnectorState.STARTED) {
|
|
9975
|
+
this.pause().catch((err) => {
|
|
9976
|
+
logger$_.warning('broadcast_channel_pause_failed', {
|
|
9977
|
+
channel: this.channelName,
|
|
9978
|
+
connector_id: this.connectorId,
|
|
9979
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9980
|
+
});
|
|
9981
|
+
});
|
|
9982
|
+
}
|
|
9983
|
+
else if (!isHidden && this.state === core.ConnectorState.PAUSED) {
|
|
9984
|
+
this.resume().catch((err) => {
|
|
9985
|
+
logger$_.warning('broadcast_channel_resume_failed', {
|
|
9986
|
+
channel: this.channelName,
|
|
9987
|
+
connector_id: this.connectorId,
|
|
9988
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9989
|
+
});
|
|
9990
|
+
});
|
|
9991
|
+
}
|
|
9871
9992
|
};
|
|
9872
9993
|
if (typeof document !== 'undefined') {
|
|
9873
9994
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
@@ -9923,16 +10044,44 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9923
10044
|
return await this.inbox.dequeue();
|
|
9924
10045
|
}
|
|
9925
10046
|
async _transportClose(code, reason) {
|
|
10047
|
+
logger$_.info('broadcast_channel_transport_closing', {
|
|
10048
|
+
channel: this.channelName,
|
|
10049
|
+
connector_id: this.connectorId,
|
|
10050
|
+
code,
|
|
10051
|
+
reason,
|
|
10052
|
+
listener_registered: this.listenerRegistered,
|
|
10053
|
+
timestamp: new Date().toISOString(),
|
|
10054
|
+
});
|
|
9926
10055
|
if (this.listenerRegistered) {
|
|
10056
|
+
logger$_.info('broadcast_channel_removing_listener', {
|
|
10057
|
+
channel: this.channelName,
|
|
10058
|
+
connector_id: this.connectorId,
|
|
10059
|
+
timestamp: new Date().toISOString(),
|
|
10060
|
+
});
|
|
9927
10061
|
this.channel.removeEventListener('message', this.onMsg);
|
|
9928
10062
|
this.listenerRegistered = false;
|
|
10063
|
+
logger$_.info('broadcast_channel_listener_removed', {
|
|
10064
|
+
channel: this.channelName,
|
|
10065
|
+
connector_id: this.connectorId,
|
|
10066
|
+
timestamp: new Date().toISOString(),
|
|
10067
|
+
});
|
|
9929
10068
|
}
|
|
9930
10069
|
if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
9931
10070
|
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
9932
10071
|
this.visibilityChangeListenerRegistered = false;
|
|
9933
10072
|
this.visibilityChangeHandler = undefined;
|
|
9934
10073
|
}
|
|
10074
|
+
logger$_.info('broadcast_channel_closing', {
|
|
10075
|
+
channel: this.channelName,
|
|
10076
|
+
connector_id: this.connectorId,
|
|
10077
|
+
timestamp: new Date().toISOString(),
|
|
10078
|
+
});
|
|
9935
10079
|
this.channel.close();
|
|
10080
|
+
logger$_.info('broadcast_channel_closed', {
|
|
10081
|
+
channel: this.channelName,
|
|
10082
|
+
connector_id: this.connectorId,
|
|
10083
|
+
timestamp: new Date().toISOString(),
|
|
10084
|
+
});
|
|
9936
10085
|
const closeCode = typeof code === 'number' ? code : 1000;
|
|
9937
10086
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
9938
10087
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
@@ -10580,7 +10729,22 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10580
10729
|
this.currentStopSubtasks = null;
|
|
10581
10730
|
await Promise.allSettled(tasks.map((task) => task.promise));
|
|
10582
10731
|
if (this.connector) {
|
|
10583
|
-
|
|
10732
|
+
logger$Z.info('upstream_stopping_old_connector', {
|
|
10733
|
+
connect_epoch: this.connectEpoch,
|
|
10734
|
+
target_system_id: this.targetSystemId,
|
|
10735
|
+
timestamp: new Date().toISOString(),
|
|
10736
|
+
});
|
|
10737
|
+
await this.connector.stop().catch((err) => {
|
|
10738
|
+
logger$Z.warning('upstream_connector_stop_error', {
|
|
10739
|
+
connect_epoch: this.connectEpoch,
|
|
10740
|
+
error: err instanceof Error ? err.message : String(err),
|
|
10741
|
+
});
|
|
10742
|
+
});
|
|
10743
|
+
logger$Z.info('upstream_old_connector_stopped', {
|
|
10744
|
+
connect_epoch: this.connectEpoch,
|
|
10745
|
+
target_system_id: this.targetSystemId,
|
|
10746
|
+
timestamp: new Date().toISOString(),
|
|
10747
|
+
});
|
|
10584
10748
|
this.connector = null;
|
|
10585
10749
|
}
|
|
10586
10750
|
}
|
|
@@ -10714,6 +10878,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10714
10878
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
10715
10879
|
break;
|
|
10716
10880
|
}
|
|
10881
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
10882
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
10883
|
+
if (connector.state === core.ConnectorState.PAUSED) {
|
|
10884
|
+
logger$Z.debug('skipping_heartbeat_connector_paused', {
|
|
10885
|
+
connector_state: connector.state,
|
|
10886
|
+
});
|
|
10887
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
10888
|
+
continue;
|
|
10889
|
+
}
|
|
10717
10890
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
10718
10891
|
logger$Z.debug('sending_heartbeat', {
|
|
10719
10892
|
hb_corr_id: envelope.corrId,
|
|
@@ -10735,6 +10908,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10735
10908
|
throw error;
|
|
10736
10909
|
}
|
|
10737
10910
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
10911
|
+
// Don't check heartbeat timeout when paused
|
|
10738
10912
|
if (this.lastHeartbeatAckTime !== null &&
|
|
10739
10913
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
10740
10914
|
throw new FameConnectError('missed heartbeat acknowledgement');
|
package/dist/browser/index.mjs
CHANGED
|
@@ -96,12 +96,12 @@ installProcessEnvShim();
|
|
|
96
96
|
// --- END ENV SHIM ---
|
|
97
97
|
|
|
98
98
|
// This file is auto-generated during build - do not edit manually
|
|
99
|
-
// Generated from package.json version: 0.3.5-test.
|
|
99
|
+
// Generated from package.json version: 0.3.5-test.936
|
|
100
100
|
/**
|
|
101
101
|
* The package version, injected at build time.
|
|
102
102
|
* @internal
|
|
103
103
|
*/
|
|
104
|
-
const VERSION = '0.3.5-test.
|
|
104
|
+
const VERSION = '0.3.5-test.936';
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9268,6 +9268,10 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9268
9268
|
* Stop the connector gracefully
|
|
9269
9269
|
*/
|
|
9270
9270
|
async stop() {
|
|
9271
|
+
logger$$.debug('stopping_connector', {
|
|
9272
|
+
current_state: this._state,
|
|
9273
|
+
connector_id: this._connectorFlowId,
|
|
9274
|
+
});
|
|
9271
9275
|
if (!ConnectorStateUtils.canStop(this._state)) {
|
|
9272
9276
|
logger$$.debug('connector_stop_already_stopped', {
|
|
9273
9277
|
current_state: this._state,
|
|
@@ -9280,6 +9284,52 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9280
9284
|
if (this._lastError) {
|
|
9281
9285
|
throw this._lastError;
|
|
9282
9286
|
}
|
|
9287
|
+
logger$$.debug('connector_stopped', {
|
|
9288
|
+
current_state: this._state,
|
|
9289
|
+
connector_id: this._connectorFlowId,
|
|
9290
|
+
});
|
|
9291
|
+
}
|
|
9292
|
+
/**
|
|
9293
|
+
* Pause the connector (suspends heartbeat and housekeeping, but keeps connection alive)
|
|
9294
|
+
*/
|
|
9295
|
+
async pause() {
|
|
9296
|
+
logger$$.debug('pausing_connector', {
|
|
9297
|
+
current_state: this._state,
|
|
9298
|
+
connector_id: this._connectorFlowId,
|
|
9299
|
+
});
|
|
9300
|
+
if (this._state !== ConnectorState.STARTED) {
|
|
9301
|
+
logger$$.debug('connector_pause_invalid_state', {
|
|
9302
|
+
current_state: this._state,
|
|
9303
|
+
connector_id: this._connectorFlowId,
|
|
9304
|
+
});
|
|
9305
|
+
return;
|
|
9306
|
+
}
|
|
9307
|
+
this._setState(ConnectorState.PAUSED);
|
|
9308
|
+
logger$$.debug('connector_paused', {
|
|
9309
|
+
current_state: this._state,
|
|
9310
|
+
connector_id: this._connectorFlowId,
|
|
9311
|
+
});
|
|
9312
|
+
}
|
|
9313
|
+
/**
|
|
9314
|
+
* Resume the connector from paused state
|
|
9315
|
+
*/
|
|
9316
|
+
async resume() {
|
|
9317
|
+
logger$$.debug('resuming_connector', {
|
|
9318
|
+
current_state: this._state,
|
|
9319
|
+
connector_id: this._connectorFlowId,
|
|
9320
|
+
});
|
|
9321
|
+
if (this._state !== ConnectorState.PAUSED) {
|
|
9322
|
+
logger$$.debug('connector_resume_invalid_state', {
|
|
9323
|
+
current_state: this._state,
|
|
9324
|
+
connector_id: this._connectorFlowId,
|
|
9325
|
+
});
|
|
9326
|
+
return;
|
|
9327
|
+
}
|
|
9328
|
+
this._setState(ConnectorState.STARTED);
|
|
9329
|
+
logger$$.debug('connector_resumed', {
|
|
9330
|
+
current_state: this._state,
|
|
9331
|
+
connector_id: this._connectorFlowId,
|
|
9332
|
+
});
|
|
9283
9333
|
}
|
|
9284
9334
|
/**
|
|
9285
9335
|
* Close the connector with optional code and reason
|
|
@@ -9610,8 +9660,21 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9610
9660
|
*/
|
|
9611
9661
|
async _shutdown(code, reason, gracePeriod, exc) {
|
|
9612
9662
|
if (this._closed) {
|
|
9663
|
+
logger$$.debug('shutdown_already_closed', {
|
|
9664
|
+
connector_id: this._connectorFlowId,
|
|
9665
|
+
current_state: this._state,
|
|
9666
|
+
});
|
|
9613
9667
|
return;
|
|
9614
9668
|
}
|
|
9669
|
+
logger$$.info('connector_shutdown_starting', {
|
|
9670
|
+
connector_id: this._connectorFlowId,
|
|
9671
|
+
connector_type: this.constructor.name,
|
|
9672
|
+
code,
|
|
9673
|
+
reason,
|
|
9674
|
+
current_state: this._state,
|
|
9675
|
+
has_error: !!exc,
|
|
9676
|
+
timestamp: new Date().toISOString(),
|
|
9677
|
+
});
|
|
9615
9678
|
this._closed = true;
|
|
9616
9679
|
this._closeCode = code;
|
|
9617
9680
|
this._closeReason = reason;
|
|
@@ -9633,16 +9696,39 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9633
9696
|
this._sendPromiseResolve = undefined;
|
|
9634
9697
|
}
|
|
9635
9698
|
// Close transport
|
|
9699
|
+
logger$$.info('connector_closing_transport', {
|
|
9700
|
+
connector_id: this._connectorFlowId,
|
|
9701
|
+
connector_type: this.constructor.name,
|
|
9702
|
+
timestamp: new Date().toISOString(),
|
|
9703
|
+
});
|
|
9636
9704
|
await this._transportClose(code, reason);
|
|
9705
|
+
logger$$.info('connector_transport_closed', {
|
|
9706
|
+
connector_id: this._connectorFlowId,
|
|
9707
|
+
connector_type: this.constructor.name,
|
|
9708
|
+
timestamp: new Date().toISOString(),
|
|
9709
|
+
});
|
|
9637
9710
|
// Shutdown spawned tasks
|
|
9711
|
+
logger$$.info('connector_shutting_down_tasks', {
|
|
9712
|
+
connector_id: this._connectorFlowId,
|
|
9713
|
+
connector_type: this.constructor.name,
|
|
9714
|
+
grace_period_ms: effectiveGracePeriod * 1000,
|
|
9715
|
+
join_timeout_ms: this._shutdownJoinTimeout,
|
|
9716
|
+
timestamp: new Date().toISOString(),
|
|
9717
|
+
});
|
|
9638
9718
|
try {
|
|
9639
9719
|
await this.shutdownTasks({
|
|
9640
9720
|
gracePeriod: effectiveGracePeriod * 1000, // Convert to milliseconds
|
|
9641
9721
|
joinTimeout: this._shutdownJoinTimeout,
|
|
9642
9722
|
});
|
|
9723
|
+
logger$$.info('connector_tasks_shutdown_complete', {
|
|
9724
|
+
connector_id: this._connectorFlowId,
|
|
9725
|
+
connector_type: this.constructor.name,
|
|
9726
|
+
timestamp: new Date().toISOString(),
|
|
9727
|
+
});
|
|
9643
9728
|
}
|
|
9644
9729
|
catch (error) {
|
|
9645
9730
|
logger$$.warning('task_shutdown_error', {
|
|
9731
|
+
connector_id: this._connectorFlowId,
|
|
9646
9732
|
error: error instanceof Error ? error.message : String(error),
|
|
9647
9733
|
});
|
|
9648
9734
|
}
|
|
@@ -9654,6 +9740,12 @@ class BaseAsyncConnector extends TaskSpawner {
|
|
|
9654
9740
|
if (this._closeResolver) {
|
|
9655
9741
|
this._closeResolver();
|
|
9656
9742
|
}
|
|
9743
|
+
logger$$.info('connector_shutdown_complete', {
|
|
9744
|
+
connector_id: this._connectorFlowId,
|
|
9745
|
+
connector_type: this.constructor.name,
|
|
9746
|
+
final_state: this._state,
|
|
9747
|
+
timestamp: new Date().toISOString(),
|
|
9748
|
+
});
|
|
9657
9749
|
}
|
|
9658
9750
|
/**
|
|
9659
9751
|
* Close the underlying transport
|
|
@@ -9789,12 +9881,22 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9789
9881
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9790
9882
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9791
9883
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9792
|
-
logger$_.
|
|
9884
|
+
logger$_.info('broadcast_channel_connector_created', {
|
|
9793
9885
|
channel: this.channelName,
|
|
9794
9886
|
connector_id: this.connectorId,
|
|
9795
9887
|
inbox_capacity: preferredCapacity,
|
|
9888
|
+
timestamp: new Date().toISOString(),
|
|
9796
9889
|
});
|
|
9797
9890
|
this.onMsg = (event) => {
|
|
9891
|
+
// Guard: Don't process if listener was unregistered
|
|
9892
|
+
if (!this.listenerRegistered) {
|
|
9893
|
+
logger$_.warning('broadcast_channel_message_after_unregister', {
|
|
9894
|
+
channel: this.channelName,
|
|
9895
|
+
connector_id: this.connectorId,
|
|
9896
|
+
timestamp: new Date().toISOString(),
|
|
9897
|
+
});
|
|
9898
|
+
return;
|
|
9899
|
+
}
|
|
9798
9900
|
const message = event.data;
|
|
9799
9901
|
logger$_.debug('broadcast_channel_raw_event', {
|
|
9800
9902
|
channel: this.channelName,
|
|
@@ -9866,6 +9968,25 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9866
9968
|
visibility: isHidden ? 'hidden' : 'visible',
|
|
9867
9969
|
timestamp: new Date().toISOString(),
|
|
9868
9970
|
});
|
|
9971
|
+
// Pause/resume connector based on visibility
|
|
9972
|
+
if (isHidden && this.state === ConnectorState.STARTED) {
|
|
9973
|
+
this.pause().catch((err) => {
|
|
9974
|
+
logger$_.warning('broadcast_channel_pause_failed', {
|
|
9975
|
+
channel: this.channelName,
|
|
9976
|
+
connector_id: this.connectorId,
|
|
9977
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9978
|
+
});
|
|
9979
|
+
});
|
|
9980
|
+
}
|
|
9981
|
+
else if (!isHidden && this.state === ConnectorState.PAUSED) {
|
|
9982
|
+
this.resume().catch((err) => {
|
|
9983
|
+
logger$_.warning('broadcast_channel_resume_failed', {
|
|
9984
|
+
channel: this.channelName,
|
|
9985
|
+
connector_id: this.connectorId,
|
|
9986
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9987
|
+
});
|
|
9988
|
+
});
|
|
9989
|
+
}
|
|
9869
9990
|
};
|
|
9870
9991
|
if (typeof document !== 'undefined') {
|
|
9871
9992
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
@@ -9921,16 +10042,44 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9921
10042
|
return await this.inbox.dequeue();
|
|
9922
10043
|
}
|
|
9923
10044
|
async _transportClose(code, reason) {
|
|
10045
|
+
logger$_.info('broadcast_channel_transport_closing', {
|
|
10046
|
+
channel: this.channelName,
|
|
10047
|
+
connector_id: this.connectorId,
|
|
10048
|
+
code,
|
|
10049
|
+
reason,
|
|
10050
|
+
listener_registered: this.listenerRegistered,
|
|
10051
|
+
timestamp: new Date().toISOString(),
|
|
10052
|
+
});
|
|
9924
10053
|
if (this.listenerRegistered) {
|
|
10054
|
+
logger$_.info('broadcast_channel_removing_listener', {
|
|
10055
|
+
channel: this.channelName,
|
|
10056
|
+
connector_id: this.connectorId,
|
|
10057
|
+
timestamp: new Date().toISOString(),
|
|
10058
|
+
});
|
|
9925
10059
|
this.channel.removeEventListener('message', this.onMsg);
|
|
9926
10060
|
this.listenerRegistered = false;
|
|
10061
|
+
logger$_.info('broadcast_channel_listener_removed', {
|
|
10062
|
+
channel: this.channelName,
|
|
10063
|
+
connector_id: this.connectorId,
|
|
10064
|
+
timestamp: new Date().toISOString(),
|
|
10065
|
+
});
|
|
9927
10066
|
}
|
|
9928
10067
|
if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
9929
10068
|
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
9930
10069
|
this.visibilityChangeListenerRegistered = false;
|
|
9931
10070
|
this.visibilityChangeHandler = undefined;
|
|
9932
10071
|
}
|
|
10072
|
+
logger$_.info('broadcast_channel_closing', {
|
|
10073
|
+
channel: this.channelName,
|
|
10074
|
+
connector_id: this.connectorId,
|
|
10075
|
+
timestamp: new Date().toISOString(),
|
|
10076
|
+
});
|
|
9933
10077
|
this.channel.close();
|
|
10078
|
+
logger$_.info('broadcast_channel_closed', {
|
|
10079
|
+
channel: this.channelName,
|
|
10080
|
+
connector_id: this.connectorId,
|
|
10081
|
+
timestamp: new Date().toISOString(),
|
|
10082
|
+
});
|
|
9934
10083
|
const closeCode = typeof code === 'number' ? code : 1000;
|
|
9935
10084
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
9936
10085
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
@@ -10578,7 +10727,22 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10578
10727
|
this.currentStopSubtasks = null;
|
|
10579
10728
|
await Promise.allSettled(tasks.map((task) => task.promise));
|
|
10580
10729
|
if (this.connector) {
|
|
10581
|
-
|
|
10730
|
+
logger$Z.info('upstream_stopping_old_connector', {
|
|
10731
|
+
connect_epoch: this.connectEpoch,
|
|
10732
|
+
target_system_id: this.targetSystemId,
|
|
10733
|
+
timestamp: new Date().toISOString(),
|
|
10734
|
+
});
|
|
10735
|
+
await this.connector.stop().catch((err) => {
|
|
10736
|
+
logger$Z.warning('upstream_connector_stop_error', {
|
|
10737
|
+
connect_epoch: this.connectEpoch,
|
|
10738
|
+
error: err instanceof Error ? err.message : String(err),
|
|
10739
|
+
});
|
|
10740
|
+
});
|
|
10741
|
+
logger$Z.info('upstream_old_connector_stopped', {
|
|
10742
|
+
connect_epoch: this.connectEpoch,
|
|
10743
|
+
target_system_id: this.targetSystemId,
|
|
10744
|
+
timestamp: new Date().toISOString(),
|
|
10745
|
+
});
|
|
10582
10746
|
this.connector = null;
|
|
10583
10747
|
}
|
|
10584
10748
|
}
|
|
@@ -10712,6 +10876,15 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10712
10876
|
if (stopEvt.isSet() || signal?.aborted) {
|
|
10713
10877
|
break;
|
|
10714
10878
|
}
|
|
10879
|
+
// Skip heartbeat if connector is paused (e.g., tab is hidden)
|
|
10880
|
+
// Keep ack time current so we don't timeout immediately after resuming
|
|
10881
|
+
if (connector.state === ConnectorState.PAUSED) {
|
|
10882
|
+
logger$Z.debug('skipping_heartbeat_connector_paused', {
|
|
10883
|
+
connector_state: connector.state,
|
|
10884
|
+
});
|
|
10885
|
+
this.lastHeartbeatAckTime = Date.now();
|
|
10886
|
+
continue;
|
|
10887
|
+
}
|
|
10715
10888
|
const envelope = await this.makeHeartbeatEnvelope();
|
|
10716
10889
|
logger$Z.debug('sending_heartbeat', {
|
|
10717
10890
|
hb_corr_id: envelope.corrId,
|
|
@@ -10733,6 +10906,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10733
10906
|
throw error;
|
|
10734
10907
|
}
|
|
10735
10908
|
await this.node.dispatchEvent('onHeartbeatSent', this.node, envelope);
|
|
10909
|
+
// Don't check heartbeat timeout when paused
|
|
10736
10910
|
if (this.lastHeartbeatAckTime !== null &&
|
|
10737
10911
|
Date.now() - this.lastHeartbeatAckTime > graceMs) {
|
|
10738
10912
|
throw new FameConnectError('missed heartbeat acknowledgement');
|