@juit/pgproxy-server 1.4.40 → 1.5.1
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/server.cjs +39 -10
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.ts +4 -0
- package/dist/server.mjs +39 -10
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
- package/src/server.ts +57 -8
package/dist/server.cjs
CHANGED
|
@@ -52,12 +52,26 @@ var ServerImpl = class {
|
|
|
52
52
|
_backlog;
|
|
53
53
|
_address;
|
|
54
54
|
_port;
|
|
55
|
+
_webSocketPingInterval;
|
|
56
|
+
_longRunningQueryThreshold;
|
|
55
57
|
_started = false;
|
|
56
58
|
_stopped = false;
|
|
57
59
|
constructor(logger, options) {
|
|
58
|
-
const {
|
|
60
|
+
const {
|
|
61
|
+
address,
|
|
62
|
+
port,
|
|
63
|
+
backlog,
|
|
64
|
+
secret,
|
|
65
|
+
healthCheck,
|
|
66
|
+
pool,
|
|
67
|
+
webSocketPingInterval,
|
|
68
|
+
longRunningQueryThreshold,
|
|
69
|
+
...serverOptions
|
|
70
|
+
} = options;
|
|
59
71
|
this.#pool = new import_pgproxy_pool.ConnectionPool(logger, pool);
|
|
60
72
|
this.#secret = secret;
|
|
73
|
+
this._webSocketPingInterval = webSocketPingInterval || 5e3;
|
|
74
|
+
this._longRunningQueryThreshold = longRunningQueryThreshold || 3e4;
|
|
61
75
|
this._healthCheck = healthCheck ? (0, import_node_path.resolve)("/", healthCheck) : null;
|
|
62
76
|
this._backlog = backlog;
|
|
63
77
|
this._address = address;
|
|
@@ -156,6 +170,11 @@ var ServerImpl = class {
|
|
|
156
170
|
/* ======================================================================== *
|
|
157
171
|
* REQUEST HANDLING *
|
|
158
172
|
* ======================================================================== */
|
|
173
|
+
_logLongRunningQuery(query, ms) {
|
|
174
|
+
if (ms <= this._longRunningQueryThreshold) return;
|
|
175
|
+
const normalized = query.replace(/\s+/g, " ").replace(/[\x00-\x1F\x7F]/g, (char) => `\\x${char.charCodeAt(0).toString(16).padStart(2, "0")}`).trim();
|
|
176
|
+
this._logger.warn(`Long running query detected (${ms} ms):`, normalized);
|
|
177
|
+
}
|
|
159
178
|
_sendResponse(object, statusCode, request, response) {
|
|
160
179
|
new Promise((resolve2, reject) => {
|
|
161
180
|
try {
|
|
@@ -198,7 +217,7 @@ var ServerImpl = class {
|
|
|
198
217
|
const latency = Math.floor(Number(queryEnd - start) / 1e4) / 100;
|
|
199
218
|
const connTime = Math.floor(Number(queryStart - start) / 1e4) / 100;
|
|
200
219
|
const queryTime = Math.floor(Number(queryEnd - queryStart) / 1e4) / 100;
|
|
201
|
-
return { ...stats, latency, connTime, queryTime };
|
|
220
|
+
return { ...stats, latency, connTime, queryTime, ...process.memoryUsage() };
|
|
202
221
|
}).then((data) => {
|
|
203
222
|
const { connTime, queryTime, ...stats } = data;
|
|
204
223
|
this._sendResponse(stats, 200, request, response);
|
|
@@ -220,6 +239,7 @@ var ServerImpl = class {
|
|
|
220
239
|
response.statusCode = 415;
|
|
221
240
|
return void response.end();
|
|
222
241
|
}
|
|
242
|
+
let query = "";
|
|
223
243
|
const now = process.hrtime.bigint();
|
|
224
244
|
void Promise.resolve().then(async () => {
|
|
225
245
|
const string = await this._readRequest(request);
|
|
@@ -237,6 +257,7 @@ var ServerImpl = class {
|
|
|
237
257
|
this._logger.error("Error acquiring connection:", error);
|
|
238
258
|
return { id: payload.id, statusCode: 500, error: "Error acquiring connection" };
|
|
239
259
|
}
|
|
260
|
+
query = payload.query;
|
|
240
261
|
try {
|
|
241
262
|
const result = await connection.query(payload.query, payload.params);
|
|
242
263
|
return { ...result, statusCode: 200, id: payload.id };
|
|
@@ -249,6 +270,7 @@ var ServerImpl = class {
|
|
|
249
270
|
this._sendResponse(data, data.statusCode, request, response);
|
|
250
271
|
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 1e4) / 100;
|
|
251
272
|
this._logger.info(`Handled "${data.command}" HTTP request in ${ms} ms`);
|
|
273
|
+
this._logLongRunningQuery(query, ms);
|
|
252
274
|
});
|
|
253
275
|
}
|
|
254
276
|
_upgradeHandler(request, socket, head, wss) {
|
|
@@ -284,22 +306,28 @@ var ServerImpl = class {
|
|
|
284
306
|
}
|
|
285
307
|
});
|
|
286
308
|
};
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
(
|
|
291
|
-
this._logger.
|
|
292
|
-
|
|
309
|
+
let isAlive = 3;
|
|
310
|
+
ws.on("pong", () => isAlive = 3);
|
|
311
|
+
const pingInterval = setInterval(() => {
|
|
312
|
+
if (isAlive <= 0) {
|
|
313
|
+
this._logger.warn("WebSocket did not respond to ping");
|
|
314
|
+
clearInterval(pingInterval);
|
|
315
|
+
ws.terminate();
|
|
316
|
+
} else {
|
|
317
|
+
isAlive--;
|
|
318
|
+
ws.ping();
|
|
293
319
|
}
|
|
294
|
-
);
|
|
320
|
+
}, this._webSocketPingInterval);
|
|
321
|
+
ws.on("error", (error) => this._logger.error("WebSocket error", error));
|
|
295
322
|
ws.on("close", (code, reason) => {
|
|
323
|
+
clearInterval(pingInterval);
|
|
324
|
+
release();
|
|
296
325
|
const extra = reason.toString("utf-8");
|
|
297
326
|
if (extra) {
|
|
298
327
|
this._logger.info(`WebSocket closed (${code}):`, extra);
|
|
299
328
|
} else {
|
|
300
329
|
this._logger.info(`WebSocket closed (${code}):`);
|
|
301
330
|
}
|
|
302
|
-
release();
|
|
303
331
|
});
|
|
304
332
|
ws.on("message", (data) => {
|
|
305
333
|
const now = process.hrtime.bigint();
|
|
@@ -313,6 +341,7 @@ var ServerImpl = class {
|
|
|
313
341
|
const result = await connection.query(payload.query, payload.params);
|
|
314
342
|
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 1e4) / 100;
|
|
315
343
|
this._logger.info(`Handled "${result.command}" WebSocket request in ${ms} ms`);
|
|
344
|
+
this._logLongRunningQuery(payload.query, ms);
|
|
316
345
|
return send({ ...result, statusCode: 200, id: payload.id });
|
|
317
346
|
} catch (error) {
|
|
318
347
|
return send({ id: payload.id, statusCode: 400, error: error.message });
|
package/dist/server.cjs.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/server.ts"],
|
|
4
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAmB;AACnB,yBAA2B;AAC3B,uBAA2C;AAC3C,uBAAwB;AACxB,8BAA0C;AAE1C,0BAA+B;AAC/B,gBAAgC;AAEhC,mBAA4B;
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["assert", "resolve", "now", "parseQueryString"]
|
|
6
6
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ export interface ServerOptions extends HTTPOptions {
|
|
|
14
14
|
backlog?: number;
|
|
15
15
|
/** The keepalive timeout in **milliseconds** (set to `0` to disable) */
|
|
16
16
|
keepAliveTimeout?: number;
|
|
17
|
+
/** The web socket ping interval in **milliseconds** (default: `5_000`) */
|
|
18
|
+
webSocketPingInterval?: number;
|
|
19
|
+
/** The threshold for long running queries in **milliseconds** (default: `30_000`) */
|
|
20
|
+
longRunningQueryThreshold?: number;
|
|
17
21
|
/** Options for the connection pool backing this server */
|
|
18
22
|
pool?: ConnectionPoolOptions;
|
|
19
23
|
}
|
package/dist/server.mjs
CHANGED
|
@@ -18,12 +18,26 @@ var ServerImpl = class {
|
|
|
18
18
|
_backlog;
|
|
19
19
|
_address;
|
|
20
20
|
_port;
|
|
21
|
+
_webSocketPingInterval;
|
|
22
|
+
_longRunningQueryThreshold;
|
|
21
23
|
_started = false;
|
|
22
24
|
_stopped = false;
|
|
23
25
|
constructor(logger, options) {
|
|
24
|
-
const {
|
|
26
|
+
const {
|
|
27
|
+
address,
|
|
28
|
+
port,
|
|
29
|
+
backlog,
|
|
30
|
+
secret,
|
|
31
|
+
healthCheck,
|
|
32
|
+
pool,
|
|
33
|
+
webSocketPingInterval,
|
|
34
|
+
longRunningQueryThreshold,
|
|
35
|
+
...serverOptions
|
|
36
|
+
} = options;
|
|
25
37
|
this.#pool = new ConnectionPool(logger, pool);
|
|
26
38
|
this.#secret = secret;
|
|
39
|
+
this._webSocketPingInterval = webSocketPingInterval || 5e3;
|
|
40
|
+
this._longRunningQueryThreshold = longRunningQueryThreshold || 3e4;
|
|
27
41
|
this._healthCheck = healthCheck ? resolve("/", healthCheck) : null;
|
|
28
42
|
this._backlog = backlog;
|
|
29
43
|
this._address = address;
|
|
@@ -122,6 +136,11 @@ var ServerImpl = class {
|
|
|
122
136
|
/* ======================================================================== *
|
|
123
137
|
* REQUEST HANDLING *
|
|
124
138
|
* ======================================================================== */
|
|
139
|
+
_logLongRunningQuery(query, ms) {
|
|
140
|
+
if (ms <= this._longRunningQueryThreshold) return;
|
|
141
|
+
const normalized = query.replace(/\s+/g, " ").replace(/[\x00-\x1F\x7F]/g, (char) => `\\x${char.charCodeAt(0).toString(16).padStart(2, "0")}`).trim();
|
|
142
|
+
this._logger.warn(`Long running query detected (${ms} ms):`, normalized);
|
|
143
|
+
}
|
|
125
144
|
_sendResponse(object, statusCode, request, response) {
|
|
126
145
|
new Promise((resolve2, reject) => {
|
|
127
146
|
try {
|
|
@@ -164,7 +183,7 @@ var ServerImpl = class {
|
|
|
164
183
|
const latency = Math.floor(Number(queryEnd - start) / 1e4) / 100;
|
|
165
184
|
const connTime = Math.floor(Number(queryStart - start) / 1e4) / 100;
|
|
166
185
|
const queryTime = Math.floor(Number(queryEnd - queryStart) / 1e4) / 100;
|
|
167
|
-
return { ...stats, latency, connTime, queryTime };
|
|
186
|
+
return { ...stats, latency, connTime, queryTime, ...process.memoryUsage() };
|
|
168
187
|
}).then((data) => {
|
|
169
188
|
const { connTime, queryTime, ...stats } = data;
|
|
170
189
|
this._sendResponse(stats, 200, request, response);
|
|
@@ -186,6 +205,7 @@ var ServerImpl = class {
|
|
|
186
205
|
response.statusCode = 415;
|
|
187
206
|
return void response.end();
|
|
188
207
|
}
|
|
208
|
+
let query = "";
|
|
189
209
|
const now = process.hrtime.bigint();
|
|
190
210
|
void Promise.resolve().then(async () => {
|
|
191
211
|
const string = await this._readRequest(request);
|
|
@@ -203,6 +223,7 @@ var ServerImpl = class {
|
|
|
203
223
|
this._logger.error("Error acquiring connection:", error);
|
|
204
224
|
return { id: payload.id, statusCode: 500, error: "Error acquiring connection" };
|
|
205
225
|
}
|
|
226
|
+
query = payload.query;
|
|
206
227
|
try {
|
|
207
228
|
const result = await connection.query(payload.query, payload.params);
|
|
208
229
|
return { ...result, statusCode: 200, id: payload.id };
|
|
@@ -215,6 +236,7 @@ var ServerImpl = class {
|
|
|
215
236
|
this._sendResponse(data, data.statusCode, request, response);
|
|
216
237
|
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 1e4) / 100;
|
|
217
238
|
this._logger.info(`Handled "${data.command}" HTTP request in ${ms} ms`);
|
|
239
|
+
this._logLongRunningQuery(query, ms);
|
|
218
240
|
});
|
|
219
241
|
}
|
|
220
242
|
_upgradeHandler(request, socket, head, wss) {
|
|
@@ -250,22 +272,28 @@ var ServerImpl = class {
|
|
|
250
272
|
}
|
|
251
273
|
});
|
|
252
274
|
};
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
(
|
|
257
|
-
this._logger.
|
|
258
|
-
|
|
275
|
+
let isAlive = 3;
|
|
276
|
+
ws.on("pong", () => isAlive = 3);
|
|
277
|
+
const pingInterval = setInterval(() => {
|
|
278
|
+
if (isAlive <= 0) {
|
|
279
|
+
this._logger.warn("WebSocket did not respond to ping");
|
|
280
|
+
clearInterval(pingInterval);
|
|
281
|
+
ws.terminate();
|
|
282
|
+
} else {
|
|
283
|
+
isAlive--;
|
|
284
|
+
ws.ping();
|
|
259
285
|
}
|
|
260
|
-
);
|
|
286
|
+
}, this._webSocketPingInterval);
|
|
287
|
+
ws.on("error", (error) => this._logger.error("WebSocket error", error));
|
|
261
288
|
ws.on("close", (code, reason) => {
|
|
289
|
+
clearInterval(pingInterval);
|
|
290
|
+
release();
|
|
262
291
|
const extra = reason.toString("utf-8");
|
|
263
292
|
if (extra) {
|
|
264
293
|
this._logger.info(`WebSocket closed (${code}):`, extra);
|
|
265
294
|
} else {
|
|
266
295
|
this._logger.info(`WebSocket closed (${code}):`);
|
|
267
296
|
}
|
|
268
|
-
release();
|
|
269
297
|
});
|
|
270
298
|
ws.on("message", (data) => {
|
|
271
299
|
const now = process.hrtime.bigint();
|
|
@@ -279,6 +307,7 @@ var ServerImpl = class {
|
|
|
279
307
|
const result = await connection.query(payload.query, payload.params);
|
|
280
308
|
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 1e4) / 100;
|
|
281
309
|
this._logger.info(`Handled "${result.command}" WebSocket request in ${ms} ms`);
|
|
310
|
+
this._logLongRunningQuery(payload.query, ms);
|
|
282
311
|
return send({ ...result, statusCode: 200, id: payload.id });
|
|
283
312
|
} catch (error) {
|
|
284
313
|
return send({ id: payload.id, statusCode: 400, error: error.message });
|
package/dist/server.mjs.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/server.ts"],
|
|
4
|
-
"mappings": ";AAAA,OAAO,YAAY;AACnB,SAAS,kBAAkB;AAC3B,SAAS,cAAc,oBAAoB;AAC3C,SAAS,eAAe;AACxB,SAAS,SAAS,wBAAwB;AAE1C,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAEhC,SAAS,mBAAmB;
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["resolve", "now"]
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juit/pgproxy-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"main": "./dist/index.cjs",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/juitnow/juit-pgproxy#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@juit/pgproxy-pool": "1.
|
|
38
|
+
"@juit/pgproxy-pool": "1.5.1",
|
|
39
39
|
"ws": "^8.21.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
package/src/server.ts
CHANGED
|
@@ -42,6 +42,10 @@ export interface ServerOptions extends HTTPOptions {
|
|
|
42
42
|
backlog?: number,
|
|
43
43
|
/** The keepalive timeout in **milliseconds** (set to `0` to disable) */
|
|
44
44
|
keepAliveTimeout?: number,
|
|
45
|
+
/** The web socket ping interval in **milliseconds** (default: `5_000`) */
|
|
46
|
+
webSocketPingInterval?: number,
|
|
47
|
+
/** The threshold for long running queries in **milliseconds** (default: `30_000`) */
|
|
48
|
+
longRunningQueryThreshold?: number,
|
|
45
49
|
/** Options for the connection pool backing this server */
|
|
46
50
|
pool?: ConnectionPoolOptions
|
|
47
51
|
}
|
|
@@ -93,16 +97,30 @@ class ServerImpl implements Server {
|
|
|
93
97
|
private readonly _backlog?: number
|
|
94
98
|
private readonly _address?: string
|
|
95
99
|
private readonly _port?: number
|
|
100
|
+
private readonly _webSocketPingInterval: number
|
|
101
|
+
private readonly _longRunningQueryThreshold: number
|
|
96
102
|
|
|
97
103
|
private _started: boolean = false
|
|
98
104
|
private _stopped: boolean = false
|
|
99
105
|
|
|
100
106
|
constructor(logger: Logger, options: ServerOptions) {
|
|
101
|
-
const {
|
|
107
|
+
const {
|
|
108
|
+
address,
|
|
109
|
+
port,
|
|
110
|
+
backlog,
|
|
111
|
+
secret,
|
|
112
|
+
healthCheck,
|
|
113
|
+
pool,
|
|
114
|
+
webSocketPingInterval,
|
|
115
|
+
longRunningQueryThreshold,
|
|
116
|
+
...serverOptions
|
|
117
|
+
} = options
|
|
102
118
|
|
|
103
119
|
this.#pool = new ConnectionPool(logger, pool)
|
|
104
120
|
this.#secret = secret
|
|
105
121
|
|
|
122
|
+
this._webSocketPingInterval = webSocketPingInterval || 5_000
|
|
123
|
+
this._longRunningQueryThreshold = longRunningQueryThreshold || 30_000
|
|
106
124
|
this._healthCheck = healthCheck ? resolve('/', healthCheck) : null
|
|
107
125
|
this._backlog = backlog
|
|
108
126
|
this._address = address
|
|
@@ -229,6 +247,17 @@ class ServerImpl implements Server {
|
|
|
229
247
|
* REQUEST HANDLING *
|
|
230
248
|
* ======================================================================== */
|
|
231
249
|
|
|
250
|
+
private _logLongRunningQuery(query: string, ms: number): void {
|
|
251
|
+
if (ms <= this._longRunningQueryThreshold) return
|
|
252
|
+
|
|
253
|
+
const normalized = query
|
|
254
|
+
.replace(/\s+/g, ' ')
|
|
255
|
+
// eslint-disable-next-line no-control-regex
|
|
256
|
+
.replace(/[\x00-\x1F\x7F]/g, (char) => `\\x${char.charCodeAt(0).toString(16).padStart(2, '0')}`)
|
|
257
|
+
.trim()
|
|
258
|
+
this._logger.warn(`Long running query detected (${ms} ms):`, normalized)
|
|
259
|
+
}
|
|
260
|
+
|
|
232
261
|
private _sendResponse(
|
|
233
262
|
object: object,
|
|
234
263
|
statusCode: number,
|
|
@@ -284,7 +313,7 @@ class ServerImpl implements Server {
|
|
|
284
313
|
const connTime = Math.floor(Number(queryStart - start) / 10000) / 100
|
|
285
314
|
const queryTime = Math.floor(Number(queryEnd - queryStart) / 10000) / 100
|
|
286
315
|
|
|
287
|
-
return { ...stats, latency, connTime, queryTime }
|
|
316
|
+
return { ...stats, latency, connTime, queryTime, ...process.memoryUsage() }
|
|
288
317
|
}).then((data) => {
|
|
289
318
|
const { connTime, queryTime, ...stats } = data
|
|
290
319
|
this._sendResponse(stats, 200, request, response)
|
|
@@ -316,6 +345,7 @@ class ServerImpl implements Server {
|
|
|
316
345
|
}
|
|
317
346
|
|
|
318
347
|
/* Run asynchronously for the rest of the processing */
|
|
348
|
+
let query: string = '' // to log long running queries
|
|
319
349
|
const now = process.hrtime.bigint()
|
|
320
350
|
void Promise.resolve().then(async (): Promise<Response> => {
|
|
321
351
|
/* Extract the payload from the request */
|
|
@@ -341,6 +371,7 @@ class ServerImpl implements Server {
|
|
|
341
371
|
}
|
|
342
372
|
|
|
343
373
|
/* Run the query */
|
|
374
|
+
query = payload.query
|
|
344
375
|
try {
|
|
345
376
|
const result = await connection.query(payload.query, payload.params)
|
|
346
377
|
return { ...result, statusCode: 200, id: payload.id }
|
|
@@ -353,6 +384,7 @@ class ServerImpl implements Server {
|
|
|
353
384
|
this._sendResponse(data, data.statusCode, request, response)
|
|
354
385
|
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 10000) / 100
|
|
355
386
|
this._logger.info(`Handled "${data.command}" HTTP request in ${ms} ms`)
|
|
387
|
+
this._logLongRunningQuery(query, ms)
|
|
356
388
|
})
|
|
357
389
|
}
|
|
358
390
|
|
|
@@ -399,21 +431,37 @@ class ServerImpl implements Server {
|
|
|
399
431
|
})
|
|
400
432
|
}
|
|
401
433
|
|
|
402
|
-
/*
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
434
|
+
/* Setup our pong handler */
|
|
435
|
+
let isAlive = 3
|
|
436
|
+
ws.on('pong', () => isAlive = 3)
|
|
437
|
+
|
|
438
|
+
/* Setup our ping interval (every 5 seconds) */
|
|
439
|
+
const pingInterval = setInterval(() => {
|
|
440
|
+
if (isAlive <= 0) {
|
|
441
|
+
this._logger.warn('WebSocket did not respond to ping')
|
|
442
|
+
clearInterval(pingInterval)
|
|
443
|
+
ws.terminate()
|
|
444
|
+
} else {
|
|
445
|
+
isAlive --
|
|
446
|
+
ws.ping()
|
|
447
|
+
}
|
|
448
|
+
}, this._webSocketPingInterval)
|
|
449
|
+
|
|
450
|
+
/* coverage ignore next // On websocket error, we just log... Apparently,
|
|
451
|
+
* if the error is fatal, the socket will be closed automatically */
|
|
452
|
+
ws.on('error', (error) => this._logger.error('WebSocket error', error))
|
|
407
453
|
|
|
408
454
|
/* On websocket close, release the connection */
|
|
409
455
|
ws.on('close', (code, reason) => {
|
|
456
|
+
clearInterval(pingInterval)
|
|
457
|
+
release()
|
|
458
|
+
|
|
410
459
|
const extra = reason.toString('utf-8')
|
|
411
460
|
if (extra) {
|
|
412
461
|
this._logger.info(`WebSocket closed (${code}):`, extra)
|
|
413
462
|
} else {
|
|
414
463
|
this._logger.info(`WebSocket closed (${code}):`)
|
|
415
464
|
}
|
|
416
|
-
release()
|
|
417
465
|
})
|
|
418
466
|
|
|
419
467
|
/* On message, run a query and send results back */
|
|
@@ -432,6 +480,7 @@ class ServerImpl implements Server {
|
|
|
432
480
|
|
|
433
481
|
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 10000) / 100
|
|
434
482
|
this._logger.info(`Handled "${result.command}" WebSocket request in ${ms} ms`)
|
|
483
|
+
this._logLongRunningQuery(payload.query, ms)
|
|
435
484
|
return send({ ...result, statusCode: 200, id: payload.id })
|
|
436
485
|
} catch (error: any) {
|
|
437
486
|
return send({ id: payload.id, statusCode: 400, error: error.message })
|