@resolveio/server-lib 20.9.11 → 20.10.0

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.
@@ -11,9 +11,12 @@ export declare class WebSocketManager {
11
11
  private _maxMessageSize;
12
12
  private _messageDelay;
13
13
  private _webSockets;
14
+ private _chunkThresholdBytes;
15
+ private _chunkSizeBytes;
16
+ private readonly _chunkMetaFlag;
14
17
  constructor();
15
- static create(mainServer: any, maxMessageSize?: number, messageDelay?: number): WebSocketManager;
16
- initialize(mainServer: any, maxMessageSize?: number, messageDelay?: number): void;
18
+ static create(mainServer: any, maxMessageSize?: number, messageDelay?: number, chunkThresholdBytes?: number, chunkSizeBytes?: number): WebSocketManager;
19
+ initialize(mainServer: any, maxMessageSize?: number, messageDelay?: number, chunkThresholdBytes?: number, chunkSizeBytes?: number): void;
17
20
  addWebSocket(ws: WebSocket): void;
18
21
  removeWebSocket(ws: WebSocket): void;
19
22
  getWebSocket(id_socket: string): WebSocket | undefined;
@@ -23,5 +26,9 @@ export declare class WebSocketManager {
23
26
  private sendMessagesInChunksBinary;
24
27
  private handleSendError;
25
28
  closeConnection(ws: WebSocket): void;
29
+ private prepareChunkContext;
30
+ private sendChunkSequence;
31
+ private transmitBatch;
32
+ private generateChunkId;
26
33
  }
27
34
  export {};
@@ -12,26 +12,34 @@ var __values = (this && this.__values) || function(o) {
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.WebSocketManager = void 0;
15
+ var crypto_1 = require("crypto");
15
16
  var msgpackr_1 = require("msgpackr");
16
17
  var WebSocketManager = /** @class */ (function () {
17
18
  function WebSocketManager() {
18
19
  this._messageBuffers = new Map();
19
20
  this._batchingTimers = new Map();
20
21
  this._webSockets = new Map();
22
+ this._chunkMetaFlag = '__chunked';
21
23
  }
22
- WebSocketManager.create = function (mainServer, maxMessageSize, messageDelay) {
24
+ WebSocketManager.create = function (mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes) {
23
25
  if (maxMessageSize === void 0) { maxMessageSize = 20480; }
24
26
  if (messageDelay === void 0) { messageDelay = 25; }
27
+ if (chunkThresholdBytes === void 0) { chunkThresholdBytes = 1024 * 1024; }
28
+ if (chunkSizeBytes === void 0) { chunkSizeBytes = 512 * 1024; }
25
29
  var websocketManager = new WebSocketManager();
26
- websocketManager.initialize(mainServer, maxMessageSize, messageDelay);
30
+ websocketManager.initialize(mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes);
27
31
  return websocketManager;
28
32
  };
29
- WebSocketManager.prototype.initialize = function (mainServer, maxMessageSize, messageDelay) {
33
+ WebSocketManager.prototype.initialize = function (mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes) {
30
34
  if (maxMessageSize === void 0) { maxMessageSize = 20480; }
31
35
  if (messageDelay === void 0) { messageDelay = 25; }
36
+ if (chunkThresholdBytes === void 0) { chunkThresholdBytes = 1024 * 1024; }
37
+ if (chunkSizeBytes === void 0) { chunkSizeBytes = 512 * 1024; }
32
38
  this._mainServer = mainServer;
33
39
  this._maxMessageSize = maxMessageSize;
34
40
  this._messageDelay = messageDelay;
41
+ this._chunkThresholdBytes = chunkThresholdBytes;
42
+ this._chunkSizeBytes = chunkSizeBytes;
35
43
  };
36
44
  WebSocketManager.prototype.addWebSocket = function (ws) {
37
45
  var wsId = ws['id_socket'];
@@ -51,11 +59,18 @@ var WebSocketManager = /** @class */ (function () {
51
59
  if (!this._messageBuffers.has(wsId)) {
52
60
  this._messageBuffers.set(wsId, []);
53
61
  }
62
+ var supportsBinary = ws['supportsBinary'] === true;
54
63
  if (typeof data === 'string') {
55
64
  // Handle string messages like 'ping' or 'pong'
56
65
  this._messageBuffers.get(wsId).push({ messageId: null, hasError: false, data: data });
57
66
  }
58
67
  else {
68
+ var chunkContext = this.prepareChunkContext(data, supportsBinary);
69
+ if (chunkContext) {
70
+ this.flushMessages(ws);
71
+ this.sendChunkSequence(ws, data, chunkContext, supportsBinary);
72
+ return;
73
+ }
59
74
  this._messageBuffers.get(wsId).push(data);
60
75
  }
61
76
  if (!this._batchingTimers.has(wsId)) {
@@ -67,41 +82,12 @@ var WebSocketManager = /** @class */ (function () {
67
82
  }
68
83
  };
69
84
  WebSocketManager.prototype.flushMessages = function (ws) {
70
- var _this = this;
71
85
  var wsId = ws['id_socket'];
72
86
  var messages = this._messageBuffers.get(wsId);
87
+ var supportsBinary = ws['supportsBinary'] === true;
73
88
  if (messages && messages.length > 0) {
74
89
  // Combine messages into one payload
75
- var supportsBinary = ws['supportsBinary'] === true;
76
- if (supportsBinary) {
77
- var packedData = (0, msgpackr_1.pack)(messages);
78
- var dataSize = packedData.byteLength;
79
- if (dataSize > this._maxMessageSize) {
80
- this.sendMessagesInChunksBinary(ws, messages);
81
- }
82
- else {
83
- ws.send(packedData, function (error) {
84
- if (error) {
85
- _this.handleSendError(ws, error);
86
- }
87
- });
88
- }
89
- }
90
- else {
91
- var combinedData = JSON.stringify(messages);
92
- var dataSize = Buffer.byteLength(combinedData, 'utf8');
93
- if (dataSize > this._maxMessageSize) {
94
- this.sendMessagesInChunks(ws, messages);
95
- }
96
- else {
97
- ws.send(combinedData, function (error) {
98
- if (error) {
99
- _this.handleSendError(ws, error);
100
- }
101
- });
102
- }
103
- }
104
- // Clear the buffer and timer
90
+ this.transmitBatch(ws, messages, supportsBinary);
105
91
  this._messageBuffers.delete(wsId);
106
92
  clearTimeout(this._batchingTimers.get(wsId));
107
93
  this._batchingTimers.delete(wsId);
@@ -218,6 +204,129 @@ var WebSocketManager = /** @class */ (function () {
218
204
  }
219
205
  });
220
206
  };
207
+ WebSocketManager.prototype.prepareChunkContext = function (message, supportsBinary) {
208
+ var _a;
209
+ if (!message || message.hasError) {
210
+ return null;
211
+ }
212
+ var data = message.data;
213
+ if (data === undefined || data === null) {
214
+ return null;
215
+ }
216
+ try {
217
+ if (supportsBinary) {
218
+ var packed = Buffer.from((0, msgpackr_1.pack)(data));
219
+ if (packed.byteLength > this._chunkThresholdBytes) {
220
+ return { buffer: packed, encoding: 'msgpack' };
221
+ }
222
+ }
223
+ }
224
+ catch (err) {
225
+ // Fall back to JSON chunking if msgpack encoding fails
226
+ if ((_a = this._mainServer.getSubscriptionManager()) === null || _a === void 0 ? void 0 : _a.getEnableDebug()) {
227
+ console.log(new Date(), 'WebSocketManager', 'Chunking pack failed, falling back to JSON', (err === null || err === void 0 ? void 0 : err.message) || err);
228
+ }
229
+ }
230
+ try {
231
+ var jsonString = JSON.stringify(data);
232
+ var jsonBytes = Buffer.byteLength(jsonString, 'utf8');
233
+ if (jsonBytes > this._chunkThresholdBytes) {
234
+ return { buffer: Buffer.from(jsonString, 'utf8'), encoding: 'json' };
235
+ }
236
+ }
237
+ catch (_b) {
238
+ // Ignore JSON stringify errors; fallback to normal send
239
+ }
240
+ return null;
241
+ };
242
+ WebSocketManager.prototype.sendChunkSequence = function (ws, original, chunkContext, supportsBinary) {
243
+ var _a, _b, _c;
244
+ var chunkId = this.generateChunkId();
245
+ var totalChunks = Math.ceil(chunkContext.buffer.byteLength / this._chunkSizeBytes);
246
+ var useBinary = supportsBinary && chunkContext.encoding === 'msgpack';
247
+ var startMessage = {
248
+ messageId: original.messageId,
249
+ hasError: original.hasError,
250
+ data: (_a = {},
251
+ _a[this._chunkMetaFlag] = true,
252
+ _a.chunkId = chunkId,
253
+ _a.chunkStatus = 'start',
254
+ _a.totalChunks = totalChunks,
255
+ _a.totalBytes = chunkContext.buffer.byteLength,
256
+ _a.chunkSize = this._chunkSizeBytes,
257
+ _a.encoding = chunkContext.encoding,
258
+ _a)
259
+ };
260
+ this.transmitBatch(ws, [startMessage], useBinary);
261
+ for (var index = 0; index < totalChunks; index++) {
262
+ var start = index * this._chunkSizeBytes;
263
+ var end = Math.min(chunkContext.buffer.byteLength, start + this._chunkSizeBytes);
264
+ var slice = chunkContext.buffer.subarray(start, end);
265
+ var chunkPayload = chunkContext.encoding === 'msgpack' ? slice : slice.toString('base64');
266
+ var chunkMessage = {
267
+ messageId: original.messageId,
268
+ hasError: original.hasError,
269
+ data: (_b = {},
270
+ _b[this._chunkMetaFlag] = true,
271
+ _b.chunkId = chunkId,
272
+ _b.chunkStatus = 'chunk',
273
+ _b.chunkIndex = index,
274
+ _b.payload = chunkPayload,
275
+ _b.encoding = chunkContext.encoding,
276
+ _b)
277
+ };
278
+ this.transmitBatch(ws, [chunkMessage], useBinary);
279
+ }
280
+ var endMessage = {
281
+ messageId: original.messageId,
282
+ hasError: original.hasError,
283
+ data: (_c = {},
284
+ _c[this._chunkMetaFlag] = true,
285
+ _c.chunkId = chunkId,
286
+ _c.chunkStatus = 'end',
287
+ _c)
288
+ };
289
+ this.transmitBatch(ws, [endMessage], useBinary);
290
+ };
291
+ WebSocketManager.prototype.transmitBatch = function (ws, batch, useBinary) {
292
+ var _this = this;
293
+ var _a;
294
+ if (!batch || !batch.length) {
295
+ return;
296
+ }
297
+ var isChunkEnvelope = batch.length === 1 && ((_a = batch[0]) === null || _a === void 0 ? void 0 : _a.data) && typeof batch[0].data === 'object' && batch[0].data[this._chunkMetaFlag];
298
+ if (useBinary) {
299
+ var packedData = (0, msgpackr_1.pack)(batch);
300
+ var dataSize = packedData.byteLength;
301
+ if (!isChunkEnvelope && dataSize > this._maxMessageSize) {
302
+ this.sendMessagesInChunksBinary(ws, batch);
303
+ }
304
+ else {
305
+ ws.send(packedData, function (error) {
306
+ if (error) {
307
+ _this.handleSendError(ws, error);
308
+ }
309
+ });
310
+ }
311
+ }
312
+ else {
313
+ var combinedData = JSON.stringify(batch);
314
+ var dataSize = Buffer.byteLength(combinedData, 'utf8');
315
+ if (!isChunkEnvelope && dataSize > this._maxMessageSize) {
316
+ this.sendMessagesInChunks(ws, batch);
317
+ }
318
+ else {
319
+ ws.send(combinedData, function (error) {
320
+ if (error) {
321
+ _this.handleSendError(ws, error);
322
+ }
323
+ });
324
+ }
325
+ }
326
+ };
327
+ WebSocketManager.prototype.generateChunkId = function () {
328
+ return (0, crypto_1.randomBytes)(8).toString('hex');
329
+ };
221
330
  return WebSocketManager;
222
331
  }());
223
332
  exports.WebSocketManager = WebSocketManager;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/managers/websocket.manager.ts"],"names":[],"mappings":"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","file":"websocket.manager.js","sourcesContent":["import { WebSocket } from 'ws';\nimport { pack } from 'msgpackr';\n\ninterface ServerResponseModel {\n\tmessageId: number;\n\thasError: boolean;\n\tdata: any;\n}\n\nexport class WebSocketManager {\n\tprivate _mainServer;\n\tprivate _messageBuffers: Map<string, ServerResponseModel[]> = new Map();\n\tprivate _batchingTimers: Map<string, NodeJS.Timeout> = new Map();\n\tprivate _maxMessageSize: number;\n\tprivate _messageDelay: number;\n\tprivate _webSockets: Map<string, WebSocket> = new Map();\n\n\tconstructor() {}\n\t\n\tstatic create(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25) {\n\t\tconst websocketManager = new WebSocketManager();\n\t\twebsocketManager.initialize(mainServer, maxMessageSize, messageDelay);\n\t\treturn websocketManager;\n\t}\n\n\tpublic initialize(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25) {\n\t\tthis._mainServer = mainServer;\n\t\tthis._maxMessageSize = maxMessageSize;\n\t\tthis._messageDelay = messageDelay;\n\t}\n\n\tpublic addWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.set(wsId, ws);\n\t}\n\n\tpublic removeWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.delete(wsId);\n\t\tthis.closeConnection(ws);\n\t}\n\n\tpublic getWebSocket(id_socket: string): WebSocket | undefined {\n\t\treturn this._webSockets.get(id_socket);\n\t}\n\n\tpublic send(ws: WebSocket, data: ServerResponseModel | string): void {\n\t\tconst wsId = ws['id_socket'];\n\n\t\tif (!this._messageBuffers.has(wsId)) {\n\t\t\tthis._messageBuffers.set(wsId, []);\n\t\t}\n\n\t\tif (typeof data === 'string') {\n\t\t\t// Handle string messages like 'ping' or 'pong'\n\t\t\tthis._messageBuffers.get(wsId).push({ messageId: null, hasError: false, data: data });\n\t\t}\n\t\telse {\n\t\t\tthis._messageBuffers.get(wsId).push(data);\n\t\t}\n\n\t\tif (!this._batchingTimers.has(wsId)) {\n\t\t\t// Set a timer to send the batch after a short delay\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t}, this._messageDelay);\n\t\t\tthis._batchingTimers.set(wsId, timer);\n\t\t}\n\t}\n\n\tprivate flushMessages(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tconst messages = this._messageBuffers.get(wsId);\n\n\t\tif (messages && messages.length > 0) {\n\t\t\t// Combine messages into one payload\n\t\t\tconst supportsBinary = ws['supportsBinary'] === true;\n\n\t\t\tif (supportsBinary) {\n\t\t\t\tconst packedData = pack(messages);\n\t\t\t\tconst dataSize = packedData.byteLength;\n\n\t\t\t\tif (dataSize > this._maxMessageSize) {\n\t\t\t\t\tthis.sendMessagesInChunksBinary(ws, messages);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tws.send(packedData, (error) => {\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst combinedData = JSON.stringify(messages);\n\t\t\t\tconst dataSize = Buffer.byteLength(combinedData, 'utf8');\n\n\t\t\t\tif (dataSize > this._maxMessageSize) {\n\t\t\t\t\tthis.sendMessagesInChunks(ws, messages);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tws.send(combinedData, (error) => {\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Clear the buffer and timer\n\t\t\tthis._messageBuffers.delete(wsId);\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n\t}\n\n\tprivate sendMessagesInChunks(ws: WebSocket, messages: ServerResponseModel[]): void {\n\t\tlet chunk: ServerResponseModel[] = [];\n\t\tlet chunkSize = 0;\n\n\t\tfor (const message of messages) {\n\t\t\tconst messageData = JSON.stringify([message]); // Wrap message in array for consistency\n\t\t\tconst messageSize = Buffer.byteLength(messageData, 'utf8');\n\n\t\t\tif (chunkSize + messageSize > this._maxMessageSize) {\n\t\t\t\t// Send current chunk\n\t\t\t\tws.send(JSON.stringify(chunk), (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Start new chunk\n\t\t\t\tchunk = [message];\n\t\t\t\tchunkSize = messageSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchunk.push(message);\n\t\t\t\tchunkSize += messageSize;\n\t\t\t}\n\t\t}\n\n\t\t// Send any remaining messages\n\t\tif (chunk.length > 0) {\n\t\t\tws.send(JSON.stringify(chunk), (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate sendMessagesInChunksBinary(ws: WebSocket, messages: ServerResponseModel[]): void {\n\t\tlet chunk: ServerResponseModel[] = [];\n\t\tlet chunkSize = 0;\n\n\t\tfor (const message of messages) {\n\t\t\tconst packedMessage = pack([message]);\n\t\t\tconst messageSize = packedMessage.byteLength;\n\n\t\t\tif (chunkSize + messageSize > this._maxMessageSize) {\n\t\t\t\tconst packedChunk = pack(chunk);\n\t\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tchunk = [message];\n\t\t\t\tchunkSize = messageSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchunk.push(message);\n\t\t\t\tchunkSize += messageSize;\n\t\t\t}\n\t\t}\n\n\t\tif (chunk.length > 0) {\n\t\t\tconst packedChunk = pack(chunk);\n\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleSendError(ws: WebSocket, error: Error): void {\n\t\tif (this._mainServer.getSubscriptionManager()) {\n\t\t\t// Handle send error, e.g., unsubscribe, close connection\n\t\t\tif (this._mainServer.getSubscriptionManager().getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Unsub WS', ws['user'], ws['id_socket'], error);\n\t\t\t}\n\t\t\tthis._mainServer.getSubscriptionManager().unsubscribeAll(ws);\n\t\t\tthis.removeWebSocket(ws);\n\t\t}\n\t}\n\n\tpublic closeConnection(ws: WebSocket): void {\n\t\tws.close();\n\t\tconst wsId = ws['id_socket'];\n\t\t// Clean up buffers and timers\n\t\tthis._messageBuffers.delete(wsId);\n\t\tif (this._batchingTimers.has(wsId)) {\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n \n process.nextTick(() => {\n if ([ws.OPEN, ws.CLOSING].includes(<any>ws.readyState)) {\n // Socket still hangs, hard close\n ws.terminate();\n }\n });\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../../src/managers/websocket.manager.ts"],"names":[],"mappings":"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","file":"websocket.manager.js","sourcesContent":["import { randomBytes } from 'crypto';\nimport { pack } from 'msgpackr';\nimport { WebSocket } from 'ws';\n\ninterface ServerResponseModel {\n\tmessageId: number;\n\thasError: boolean;\n\tdata: any;\n}\n\nexport class WebSocketManager {\n\tprivate _mainServer;\n\tprivate _messageBuffers: Map<string, ServerResponseModel[]> = new Map();\n\tprivate _batchingTimers: Map<string, NodeJS.Timeout> = new Map();\n\tprivate _maxMessageSize: number;\n\tprivate _messageDelay: number;\n\tprivate _webSockets: Map<string, WebSocket> = new Map();\n\tprivate _chunkThresholdBytes: number;\n\tprivate _chunkSizeBytes: number;\n\tprivate readonly _chunkMetaFlag = '__chunked';\n\n\tconstructor() {}\n\t\n\tstatic create(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25, chunkThresholdBytes: number = 1024 * 1024, chunkSizeBytes: number = 512 * 1024) {\n\t\tconst websocketManager = new WebSocketManager();\n\t\twebsocketManager.initialize(mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes);\n\t\treturn websocketManager;\n\t}\n\n\tpublic initialize(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25, chunkThresholdBytes: number = 1024 * 1024, chunkSizeBytes: number = 512 * 1024) {\n\t\tthis._mainServer = mainServer;\n\t\tthis._maxMessageSize = maxMessageSize;\n\t\tthis._messageDelay = messageDelay;\n\t\tthis._chunkThresholdBytes = chunkThresholdBytes;\n\t\tthis._chunkSizeBytes = chunkSizeBytes;\n\t}\n\n\tpublic addWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.set(wsId, ws);\n\t}\n\n\tpublic removeWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.delete(wsId);\n\t\tthis.closeConnection(ws);\n\t}\n\n\tpublic getWebSocket(id_socket: string): WebSocket | undefined {\n\t\treturn this._webSockets.get(id_socket);\n\t}\n\n\tpublic send(ws: WebSocket, data: ServerResponseModel | string): void {\n\t\tconst wsId = ws['id_socket'];\n\n\t\tif (!this._messageBuffers.has(wsId)) {\n\t\t\tthis._messageBuffers.set(wsId, []);\n\t\t}\n\n\t\tconst supportsBinary = ws['supportsBinary'] === true;\n\n\t\tif (typeof data === 'string') {\n\t\t\t// Handle string messages like 'ping' or 'pong'\n\t\t\tthis._messageBuffers.get(wsId).push({ messageId: null, hasError: false, data: data });\n\t\t}\n\t\telse {\n\t\t\tconst chunkContext = this.prepareChunkContext(data, supportsBinary);\n\t\t\tif (chunkContext) {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t\tthis.sendChunkSequence(ws, data, chunkContext, supportsBinary);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._messageBuffers.get(wsId).push(data);\n\t\t}\n\n\t\tif (!this._batchingTimers.has(wsId)) {\n\t\t\t// Set a timer to send the batch after a short delay\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t}, this._messageDelay);\n\t\t\tthis._batchingTimers.set(wsId, timer);\n\t\t}\n\t}\n\n\tprivate flushMessages(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tconst messages = this._messageBuffers.get(wsId);\n\t\tconst supportsBinary = ws['supportsBinary'] === true;\n\n\t\tif (messages && messages.length > 0) {\n\t\t\t// Combine messages into one payload\n\t\t\tthis.transmitBatch(ws, messages, supportsBinary);\n\n\t\t\tthis._messageBuffers.delete(wsId);\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n\t}\n\n\tprivate sendMessagesInChunks(ws: WebSocket, messages: ServerResponseModel[]): void {\n\t\tlet chunk: ServerResponseModel[] = [];\n\t\tlet chunkSize = 0;\n\n\t\tfor (const message of messages) {\n\t\t\tconst messageData = JSON.stringify([message]); // Wrap message in array for consistency\n\t\t\tconst messageSize = Buffer.byteLength(messageData, 'utf8');\n\n\t\t\tif (chunkSize + messageSize > this._maxMessageSize) {\n\t\t\t\t// Send current chunk\n\t\t\t\tws.send(JSON.stringify(chunk), (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Start new chunk\n\t\t\t\tchunk = [message];\n\t\t\t\tchunkSize = messageSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchunk.push(message);\n\t\t\t\tchunkSize += messageSize;\n\t\t\t}\n\t\t}\n\n\t\t// Send any remaining messages\n\t\tif (chunk.length > 0) {\n\t\t\tws.send(JSON.stringify(chunk), (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate sendMessagesInChunksBinary(ws: WebSocket, messages: ServerResponseModel[]): void {\n\t\tlet chunk: ServerResponseModel[] = [];\n\t\tlet chunkSize = 0;\n\n\t\tfor (const message of messages) {\n\t\t\tconst packedMessage = pack([message]);\n\t\t\tconst messageSize = packedMessage.byteLength;\n\n\t\t\tif (chunkSize + messageSize > this._maxMessageSize) {\n\t\t\t\tconst packedChunk = pack(chunk);\n\t\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tchunk = [message];\n\t\t\t\tchunkSize = messageSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchunk.push(message);\n\t\t\t\tchunkSize += messageSize;\n\t\t\t}\n\t\t}\n\n\t\tif (chunk.length > 0) {\n\t\t\tconst packedChunk = pack(chunk);\n\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleSendError(ws: WebSocket, error: Error): void {\n\t\tif (this._mainServer.getSubscriptionManager()) {\n\t\t\t// Handle send error, e.g., unsubscribe, close connection\n\t\t\tif (this._mainServer.getSubscriptionManager().getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Unsub WS', ws['user'], ws['id_socket'], error);\n\t\t\t}\n\t\t\tthis._mainServer.getSubscriptionManager().unsubscribeAll(ws);\n\t\t\tthis.removeWebSocket(ws);\n\t\t}\n\t}\n\n\tpublic closeConnection(ws: WebSocket): void {\n\t\tws.close();\n\t\tconst wsId = ws['id_socket'];\n\t\t// Clean up buffers and timers\n\t\tthis._messageBuffers.delete(wsId);\n\t\tif (this._batchingTimers.has(wsId)) {\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n \n process.nextTick(() => {\n if ([ws.OPEN, ws.CLOSING].includes(<any>ws.readyState)) {\n // Socket still hangs, hard close\n ws.terminate();\n }\n });\n\t}\n\n\tprivate prepareChunkContext(message: ServerResponseModel, supportsBinary: boolean): { buffer: Buffer, encoding: 'msgpack' | 'json' } | null {\n\t\tif (!message || message.hasError) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = message.data;\n\t\tif (data === undefined || data === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tif (supportsBinary) {\n\t\t\t\tconst packed = Buffer.from(<any>pack(data));\n\t\t\t\tif (packed.byteLength > this._chunkThresholdBytes) {\n\t\t\t\t\treturn { buffer: packed, encoding: 'msgpack' };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (err) {\n\t\t\t// Fall back to JSON chunking if msgpack encoding fails\n\t\t\tif (this._mainServer.getSubscriptionManager()?.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Chunking pack failed, falling back to JSON', err?.message || err);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst jsonString = JSON.stringify(data);\n\t\t\tconst jsonBytes = Buffer.byteLength(jsonString, 'utf8');\n\n\t\t\tif (jsonBytes > this._chunkThresholdBytes) {\n\t\t\t\treturn { buffer: Buffer.from(jsonString, 'utf8'), encoding: 'json' };\n\t\t\t}\n\t\t}\n\t\tcatch {\n\t\t\t// Ignore JSON stringify errors; fallback to normal send\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate sendChunkSequence(ws: WebSocket, original: ServerResponseModel, chunkContext: { buffer: Buffer, encoding: 'msgpack' | 'json' }, supportsBinary: boolean): void {\n\t\tconst chunkId = this.generateChunkId();\n\t\tconst totalChunks = Math.ceil(chunkContext.buffer.byteLength / this._chunkSizeBytes);\n\t\tconst useBinary = supportsBinary && chunkContext.encoding === 'msgpack';\n\n\t\tconst startMessage: ServerResponseModel = {\n\t\t\tmessageId: original.messageId,\n\t\t\thasError: original.hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'start',\n\t\t\t\ttotalChunks: totalChunks,\n\t\t\t\ttotalBytes: chunkContext.buffer.byteLength,\n\t\t\t\tchunkSize: this._chunkSizeBytes,\n\t\t\t\tencoding: chunkContext.encoding\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [startMessage], useBinary);\n\n\t\tfor (let index = 0; index < totalChunks; index++) {\n\t\t\tconst start = index * this._chunkSizeBytes;\n\t\t\tconst end = Math.min(chunkContext.buffer.byteLength, start + this._chunkSizeBytes);\n\t\t\tconst slice = chunkContext.buffer.subarray(start, end);\n\t\t\tconst chunkPayload = chunkContext.encoding === 'msgpack' ? slice : slice.toString('base64');\n\n\t\t\tconst chunkMessage: ServerResponseModel = {\n\t\t\t\tmessageId: original.messageId,\n\t\t\t\thasError: original.hasError,\n\t\t\t\tdata: {\n\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\tchunkStatus: 'chunk',\n\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\tpayload: chunkPayload,\n\t\t\t\t\tencoding: chunkContext.encoding\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.transmitBatch(ws, [chunkMessage], useBinary);\n\t\t}\n\n\t\tconst endMessage: ServerResponseModel = {\n\t\t\tmessageId: original.messageId,\n\t\t\thasError: original.hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'end'\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [endMessage], useBinary);\n\t}\n\n\tprivate transmitBatch(ws: WebSocket, batch: ServerResponseModel[], useBinary: boolean): void {\n\t\tif (!batch || !batch.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isChunkEnvelope = batch.length === 1 && batch[0]?.data && typeof batch[0].data === 'object' && batch[0].data[this._chunkMetaFlag];\n\n\t\tif (useBinary) {\n\t\t\tconst packedData = pack(batch);\n\t\t\tconst dataSize = packedData.byteLength;\n\n\t\t\tif (!isChunkEnvelope && dataSize > this._maxMessageSize) {\n\t\t\t\tthis.sendMessagesInChunksBinary(ws, batch);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tws.send(packedData, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tconst combinedData = JSON.stringify(batch);\n\t\t\tconst dataSize = Buffer.byteLength(combinedData, 'utf8');\n\n\t\t\tif (!isChunkEnvelope && dataSize > this._maxMessageSize) {\n\t\t\t\tthis.sendMessagesInChunks(ws, batch);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tws.send(combinedData, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate generateChunkId(): string {\n\t\treturn randomBytes(8).toString('hex');\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resolveio/server-lib",
3
- "version": "20.9.11",
3
+ "version": "20.10.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "package": "./build_package.sh",
package/server-app.d.ts CHANGED
@@ -36,6 +36,9 @@ export declare class ResolveIOMainServer {
36
36
  private _isWorkersEnabled;
37
37
  private _isWorkerInstance;
38
38
  private _safeShutdown;
39
+ private readonly _clientHeartbeatIntervalMs;
40
+ private readonly _clientHeartbeatInitialDelayMs;
41
+ private readonly _clientHeartbeatBackpressureBytes;
39
42
  constructor();
40
43
  static create(): Promise<ResolveIOMainServer>;
41
44
  private initialize;
@@ -61,6 +64,8 @@ export declare class ResolveIOMainServer {
61
64
  private decodeBufferPayload;
62
65
  private parseTextFallback;
63
66
  private looksLikeTextPayload;
67
+ private triggerClientHeartbeat;
68
+ private shouldDeferHeartbeat;
64
69
  private handleClientMessage;
65
70
  /**
66
71
  * callMethodLocally is your old approach for invoking the method in-process.