@wireapp/api-client 27.94.3 → 27.94.5

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.
@@ -34,6 +34,7 @@ export declare class ReconnectingWebsocket {
34
34
  private readonly stopBackFromSleepHandler?;
35
35
  private isPingingEnabled;
36
36
  private readonly pendingHealthChecks;
37
+ private lastMessageTimestamp;
37
38
  constructor(onReconnect: () => Promise<string>, options?: {
38
39
  pingInterval?: number;
39
40
  });
@@ -49,7 +50,16 @@ export declare class ReconnectingWebsocket {
49
50
  send(message: any): void;
50
51
  getState(): WEBSOCKET_STATE;
51
52
  /**
52
- * Lightweight health probe that sends a single ping and resolves with whether a pong was received in time.
53
+ * Lightweight health probe that intelligently determines connection health.
54
+ *
55
+ * If the WebSocket is actively processing messages (i.e., received a message within the last 5 seconds),
56
+ * it considers the connection healthy without sending a ping, as message processing
57
+ * indicates the connection is working properly.
58
+ *
59
+ * If the WebSocket is idle, it sends a ping and expects a pong within the timeout.
60
+ * This approach prevents false failures during high-load scenarios where pong responses
61
+ * get queued behind many other messages.
62
+ *
53
63
  * Does not close or reconnect the socket; callers can decide how to react to failures.
54
64
  */
55
65
  checkHealth(timeoutMs?: number): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"ReconnectingWebsocket.d.ts","sourceRoot":"","sources":["../../src/tcp/ReconnectingWebsocket.ts"],"names":[],"mappings":"AAoBA,OAAY,EAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAU,MAAM,wBAAwB,CAAC;AAQnF,oBAAY,cAAc;IACxB,cAAc,OAAO;IACrB,UAAU,OAAO;IACjB,cAAc,OAAO;IACrB,gBAAgB,OAAO;CACxB;AAED,oBAAY,eAAe;IACzB,UAAU,IAAI;IACd,IAAI,IAAI;IACR,OAAO,IAAI;IACX,MAAM,IAAI;CACX;AAED,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,qBAAa,qBAAqB;IA8B9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IA7B9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAQ1C;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,MAAM,CAAC,CAAM;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,MAAM,CAAC,CAAyB;IACxC,OAAO,CAAC,SAAS,CAAC,CAAyB;IAC3C,OAAO,CAAC,OAAO,CAAC,CAA8B;IAC9C,OAAO,CAAC,OAAO,CAAC,CAA8B;IAC9C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAa;IAEvD,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA2C;gBAG5D,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EACnD,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,MAAM,CAAC;KAClB;IA+BR,OAAO,CAAC,QAAQ,CAAC,eAAe,CAK9B;IAEF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAchC;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAQ7B;IAEF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAQlC;IAEF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAO9B;IAEF,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAgBvB;IAEK,OAAO,IAAI,IAAI;IAQf,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAIxB,QAAQ,IAAI,eAAe;IAIlC;;;OAGG;IACI,WAAW,CAAC,SAAS,SAAmC,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB3E,UAAU,CAAC,MAAM,SAAqB,GAAG,IAAI;IASpD;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,0BAA0B;IAK3B,SAAS,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI/C,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIrD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI;IAItD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI;IAItD,cAAc,IAAI,IAAI;CAI9B"}
1
+ {"version":3,"file":"ReconnectingWebsocket.d.ts","sourceRoot":"","sources":["../../src/tcp/ReconnectingWebsocket.ts"],"names":[],"mappings":"AAoBA,OAAY,EAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAU,MAAM,wBAAwB,CAAC;AAQnF,oBAAY,cAAc;IACxB,cAAc,OAAO;IACrB,UAAU,OAAO;IACjB,cAAc,OAAO;IACrB,gBAAgB,OAAO;CACxB;AAED,oBAAY,eAAe;IACzB,UAAU,IAAI;IACd,IAAI,IAAI;IACR,OAAO,IAAI;IACX,MAAM,IAAI;CACX;AAED,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,qBAAa,qBAAqB;IA+B9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IA9B9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAQ1C;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,MAAM,CAAC,CAAM;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,MAAM,CAAC,CAAyB;IACxC,OAAO,CAAC,SAAS,CAAC,CAAyB;IAC3C,OAAO,CAAC,OAAO,CAAC,CAA8B;IAC9C,OAAO,CAAC,OAAO,CAAC,CAA8B;IAC9C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAa;IAEvD,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA2C;IAC/E,OAAO,CAAC,oBAAoB,CAAK;gBAGd,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EACnD,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,MAAM,CAAC;KAClB;IA+BR,OAAO,CAAC,QAAQ,CAAC,eAAe,CAK9B;IAEF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAehC;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAQ7B;IAEF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAQlC;IAEF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAO9B;IAEF,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAgBvB;IAEK,OAAO,IAAI,IAAI;IAQf,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAIxB,QAAQ,IAAI,eAAe;IAIlC;;;;;;;;;;;;OAYG;IACI,WAAW,CAAC,SAAS,SAAoC,GAAG,OAAO,CAAC,OAAO,CAAC;IAmC5E,UAAU,CAAC,MAAM,SAAqB,GAAG,IAAI;IASpD;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,0BAA0B;IAK3B,SAAS,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI/C,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIrD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI;IAItD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI;IAItD,cAAc,IAAI,IAAI;CAI9B"}
@@ -96,6 +96,7 @@ class ReconnectingWebsocket {
96
96
  stopBackFromSleepHandler;
97
97
  isPingingEnabled = true;
98
98
  pendingHealthChecks = new Set();
99
+ lastMessageTimestamp = 0;
99
100
  constructor(onReconnect, options = {}) {
100
101
  this.onReconnect = onReconnect;
101
102
  this.logger = commons_1.LogFactory.getLogger('@wireapp/api-client/tcp/ReconnectingWebsocket');
@@ -139,6 +140,7 @@ class ReconnectingWebsocket {
139
140
  this.resolvePendingHealthChecks(true);
140
141
  return;
141
142
  }
143
+ this.lastMessageTimestamp = Date.now();
142
144
  this.onMessage?.(data);
143
145
  };
144
146
  internalOnOpen = (event) => {
@@ -207,16 +209,34 @@ class ReconnectingWebsocket {
207
209
  return this.socket ? this.socket.readyState : WEBSOCKET_STATE.CLOSED;
208
210
  }
209
211
  /**
210
- * Lightweight health probe that sends a single ping and resolves with whether a pong was received in time.
212
+ * Lightweight health probe that intelligently determines connection health.
213
+ *
214
+ * If the WebSocket is actively processing messages (i.e., received a message within the last 5 seconds),
215
+ * it considers the connection healthy without sending a ping, as message processing
216
+ * indicates the connection is working properly.
217
+ *
218
+ * If the WebSocket is idle, it sends a ping and expects a pong within the timeout.
219
+ * This approach prevents false failures during high-load scenarios where pong responses
220
+ * get queued behind many other messages.
221
+ *
211
222
  * Does not close or reconnect the socket; callers can decide how to react to failures.
212
223
  */
213
- checkHealth(timeoutMs = commons_1.TimeUtil.TimeInMillis.SECOND * 5) {
224
+ checkHealth(timeoutMs = commons_1.TimeUtil.TimeInMillis.SECOND * 10) {
214
225
  if (!this.socket || this.getState() !== WEBSOCKET_STATE.OPEN) {
215
226
  return Promise.resolve(false);
216
227
  }
228
+ const now = Date.now();
229
+ const timeSinceLastMessage = now - this.lastMessageTimestamp;
230
+ // If we're actively processing messages during the last 5 seconds, consider the connection healthy
231
+ if (timeSinceLastMessage < commons_1.TimeUtil.TimeInMillis.SECOND * 5) {
232
+ this.logger.debug(`WebSocket is actively processing messages (last: ${timeSinceLastMessage}ms ago), considering healthy`);
233
+ return Promise.resolve(true);
234
+ }
235
+ // If idle, use ping/pong to verify connection
217
236
  return new Promise(resolve => {
218
237
  const timeoutId = setTimeout(() => {
219
238
  this.pendingHealthChecks.delete(resolveHealthCheck);
239
+ this.logger.debug('Health check timeout - no pong received within timeout');
220
240
  resolve(false);
221
241
  }, timeoutMs);
222
242
  const resolveHealthCheck = (isHealthy) => {
@@ -224,6 +244,7 @@ class ReconnectingWebsocket {
224
244
  resolve(isHealthy);
225
245
  };
226
246
  this.pendingHealthChecks.add(resolveHealthCheck);
247
+ this.logger.debug('WebSocket is idle, sending ping for health check');
227
248
  this.send(PingMessage.PING);
228
249
  });
229
250
  }
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@aws-sdk/client-s3": "3.956.0",
17
- "@aws-sdk/lib-storage": "3.940.0",
17
+ "@aws-sdk/lib-storage": "3.956.0",
18
18
  "@wireapp/commons": "^5.4.11",
19
19
  "@wireapp/priority-queue": "^2.1.17",
20
20
  "@wireapp/protocol-messaging": "1.56.0",
@@ -70,6 +70,6 @@
70
70
  "watch": "webpack serve --config webpack.browser.js",
71
71
  "prepare": "yarn dist"
72
72
  },
73
- "version": "27.94.3",
74
- "gitHead": "13a37180822b1a325fc1ff4f8d9fbfb45c4e0b8f"
73
+ "version": "27.94.5",
74
+ "gitHead": "33c5cf3c92492ab2f930c87a4272d75982fc8385"
75
75
  }