@xh/hoist 73.0.0-SNAPSHOT.1747410897684 → 73.0.0-SNAPSHOT.1747414706232
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/CHANGELOG.md
CHANGED
|
@@ -46,8 +46,7 @@
|
|
|
46
46
|
`@bindable` would work even if `makeObservable()` was not called, but this is no longer the case.
|
|
47
47
|
Please ensure you call `makeObservable(this)` in your model's constructor when using `@bindable`!
|
|
48
48
|
* Improved client `WebSocketService` heartbeat to check that it has been receiving inbound messages
|
|
49
|
-
from the server, not just successfully sending outbound heartbeats.
|
|
50
|
-
in a newly throttled/managed manner.
|
|
49
|
+
from the server, not just successfully sending outbound heartbeats.
|
|
51
50
|
|
|
52
51
|
### ⚙️ Technical
|
|
53
52
|
|
|
@@ -27,10 +27,6 @@ export declare class WebSocketService extends HoistService {
|
|
|
27
27
|
readonly HEARTBEAT_TOPIC = "xhHeartbeat";
|
|
28
28
|
/** Check connection and send a new heartbeat (which should be promptly ack'd) every 10s. */
|
|
29
29
|
readonly HEARTBEAT_INTERVAL: number;
|
|
30
|
-
/** If no heartbeat ack (or other msg) received for past 30s, assume we are disconnected. */
|
|
31
|
-
readonly HEARTBEAT_ACK_TIMEOUT: number;
|
|
32
|
-
/** Wait a well-defined interval before trying to reconnect again. */
|
|
33
|
-
readonly HEARTBEAT_RECONNECT_INTERVAL: number;
|
|
34
30
|
readonly REG_SUCCESS_TOPIC = "xhRegistrationSuccess";
|
|
35
31
|
readonly FORCE_APP_SUSPEND_TOPIC = "xhForceAppSuspend";
|
|
36
32
|
readonly REQ_CLIENT_HEALTH_RPT_TOPIC = "xhRequestClientHealthReport";
|
|
@@ -49,7 +45,6 @@ export declare class WebSocketService extends HoistService {
|
|
|
49
45
|
private _timer;
|
|
50
46
|
private _socket;
|
|
51
47
|
private _subsByTopic;
|
|
52
|
-
private _lastHeartbeatReconnectAttempt;
|
|
53
48
|
constructor();
|
|
54
49
|
initAsync(): Promise<void>;
|
|
55
50
|
/**
|
|
@@ -117,7 +112,6 @@ export interface WebSocketTelemetry {
|
|
|
117
112
|
msgSent?: WebSocketEventTelemetry;
|
|
118
113
|
heartbeatReceived?: WebSocketEventTelemetry;
|
|
119
114
|
heartbeatSent?: WebSocketEventTelemetry;
|
|
120
|
-
heartbeatFailed?: WebSocketEventTelemetry;
|
|
121
115
|
heartbeatReconnectAttempt?: WebSocketEventTelemetry;
|
|
122
116
|
instanceChangeReconnectAttempt?: WebSocketEventTelemetry;
|
|
123
117
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "73.0.0-SNAPSHOT.
|
|
3
|
+
"version": "73.0.0-SNAPSHOT.1747414706232",
|
|
4
4
|
"description": "Hoist add-on for building and deploying React Applications.",
|
|
5
5
|
"repository": "github:xh/hoist-react",
|
|
6
6
|
"homepage": "https://xh.io",
|
package/svc/WebSocketService.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {HoistService, PlainObject, XH} from '@xh/hoist/core';
|
|
|
8
8
|
import {withFormattedTimestamps} from '@xh/hoist/format';
|
|
9
9
|
import {action, makeObservable, observable} from '@xh/hoist/mobx';
|
|
10
10
|
import {Timer} from '@xh/hoist/utils/async';
|
|
11
|
-
import {
|
|
11
|
+
import {SECONDS} from '@xh/hoist/utils/datetime';
|
|
12
12
|
import {throwIf} from '@xh/hoist/utils/js';
|
|
13
13
|
import {find, pull} from 'lodash';
|
|
14
14
|
|
|
@@ -41,10 +41,6 @@ export class WebSocketService extends HoistService {
|
|
|
41
41
|
readonly HEARTBEAT_TOPIC = 'xhHeartbeat';
|
|
42
42
|
/** Check connection and send a new heartbeat (which should be promptly ack'd) every 10s. */
|
|
43
43
|
readonly HEARTBEAT_INTERVAL = 10 * SECONDS;
|
|
44
|
-
/** If no heartbeat ack (or other msg) received for past 30s, assume we are disconnected. */
|
|
45
|
-
readonly HEARTBEAT_ACK_TIMEOUT = 30 * SECONDS;
|
|
46
|
-
/** Wait a well-defined interval before trying to reconnect again. */
|
|
47
|
-
readonly HEARTBEAT_RECONNECT_INTERVAL = 30 * SECONDS;
|
|
48
44
|
|
|
49
45
|
readonly REG_SUCCESS_TOPIC = 'xhRegistrationSuccess';
|
|
50
46
|
readonly FORCE_APP_SUSPEND_TOPIC = 'xhForceAppSuspend';
|
|
@@ -73,7 +69,6 @@ export class WebSocketService extends HoistService {
|
|
|
73
69
|
private _timer: Timer;
|
|
74
70
|
private _socket: WebSocket;
|
|
75
71
|
private _subsByTopic: Record<string, WebSocketSubscription[]> = {};
|
|
76
|
-
private _lastHeartbeatReconnectAttempt: Date = null;
|
|
77
72
|
|
|
78
73
|
constructor() {
|
|
79
74
|
super();
|
|
@@ -199,29 +194,10 @@ export class WebSocketService extends HoistService {
|
|
|
199
194
|
|
|
200
195
|
private heartbeatOrReconnect() {
|
|
201
196
|
this.updateConnectedStatus();
|
|
202
|
-
|
|
203
|
-
// 1) Detect 'stale' connection. For some reason, not receiving heartbeat.
|
|
204
|
-
// We have a channel key, so we successfully registered with the server and have not
|
|
205
|
-
// received a disconnect message. We should be receiving at least heartbeat messages,
|
|
206
|
-
// but have observed cases where "something" interrupted connectivity in a surprising
|
|
207
|
-
// way and no new inbound messages were arriving, even with the socket reporting open
|
|
208
|
-
// and accepting outbound messages to send. Detect that case here.
|
|
209
|
-
if (this.connected && olderThan(this.lastMessageTime, this.HEARTBEAT_ACK_TIMEOUT)) {
|
|
210
|
-
this.logWarn('Heartbeat response failing - disconnecting');
|
|
211
|
-
this.noteTelemetryEvent('heartbeatFailed');
|
|
212
|
-
this.disconnect();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// 2) Happy path - connected+receiving. Send a new heartbeat for server to ack.
|
|
216
197
|
if (this.connected) {
|
|
217
198
|
this.sendMessage({topic: this.HEARTBEAT_TOPIC, data: 'ping'});
|
|
218
199
|
this.noteTelemetryEvent('heartbeatSent');
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// 3) Unhappy path -- attempt a (throttled) reconnect.
|
|
223
|
-
if (olderThan(this._lastHeartbeatReconnectAttempt, this.HEARTBEAT_RECONNECT_INTERVAL)) {
|
|
224
|
-
this._lastHeartbeatReconnectAttempt = new Date();
|
|
200
|
+
} else {
|
|
225
201
|
this.logWarn('Heartbeat found websocket not connected - attempting to reconnect...');
|
|
226
202
|
this.noteTelemetryEvent('heartbeatReconnectAttempt');
|
|
227
203
|
this.disconnect();
|
|
@@ -393,7 +369,6 @@ export interface WebSocketTelemetry {
|
|
|
393
369
|
msgSent?: WebSocketEventTelemetry;
|
|
394
370
|
heartbeatReceived?: WebSocketEventTelemetry;
|
|
395
371
|
heartbeatSent?: WebSocketEventTelemetry;
|
|
396
|
-
heartbeatFailed?: WebSocketEventTelemetry;
|
|
397
372
|
heartbeatReconnectAttempt?: WebSocketEventTelemetry;
|
|
398
373
|
instanceChangeReconnectAttempt?: WebSocketEventTelemetry;
|
|
399
374
|
};
|