@mixd-id/web-scaffold 0.1.240411094 → 0.1.240411095

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/utils/wss.js +87 -14
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.240411094",
4
+ "version": "0.1.240411095",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
package/src/utils/wss.js CHANGED
@@ -72,8 +72,6 @@ class WSS extends EventEmitter2{
72
72
 
73
73
  _authFn = []
74
74
  _reqFn = []
75
- _retryCount = 0
76
-
77
75
  _connectionId = 0
78
76
  _debugIds = {}
79
77
 
@@ -110,6 +108,7 @@ class WSS extends EventEmitter2{
110
108
 
111
109
  this._instance.on('connection', async (socket, req) => {
112
110
  socket.id = `${++this._connectionId}`
111
+ socket._retryCount = 0
113
112
 
114
113
  if(`${req.url}`.indexOf('debug-ws') > 0){
115
114
  this._debugIds[socket.id] = {}
@@ -167,7 +166,7 @@ class WSS extends EventEmitter2{
167
166
 
168
167
  if(pong){
169
168
  delete socket.pinging
170
- this._retryCount = 0
169
+ socket._retryCount = 0
171
170
  }
172
171
  else if(ping){
173
172
  socket.send(await this.toBinaryData({ pong: 1 }, !!this._debugIds[socket.id]))
@@ -217,6 +216,9 @@ class WSS extends EventEmitter2{
217
216
  if(subscriber){
218
217
  subscriber.disconnect()
219
218
  }
219
+ if(this._debugIds[socket.id]){
220
+ delete this._debugIds[socket.id]
221
+ }
220
222
  this.emit('close', e, socket)
221
223
  });
222
224
 
@@ -230,46 +232,117 @@ class WSS extends EventEmitter2{
230
232
  await fn(token, socket)
231
233
  }
232
234
 
233
- socket.isAuth = true
234
- socket.send(await this.toBinaryData({ auth:true }, !!this._debugIds[socket.id]))
235
-
236
235
  subscriber = this._client.duplicate()
237
236
  await subscriber.connect()
237
+
238
+ socket.isAuth = true
239
+ socket.send(await this.toBinaryData({ auth:true }, !!this._debugIds[socket.id]))
238
240
  }
239
241
  catch(e){
240
242
  return socket.close(1002, (e.message ?? '').substring(0, 123));
241
243
  }
242
244
 
243
245
  if(this._opt.ping !== false){
246
+ let pingTimer
244
247
 
245
248
  const ping = async() => {
249
+ if(socket.readyState !== WebSocket.OPEN) return
250
+
246
251
  socket.send(await this.toBinaryData({ ping:1 }, !!this._debugIds[socket.id]))
247
252
  socket.pinging = true
248
253
 
249
- setTimeout(() => {
254
+ pingTimer = setTimeout(() => {
250
255
  if(socket.pinging){
251
- this._retryCount++
256
+ socket._retryCount++
252
257
 
253
- if(this._retryCount > 10){
258
+ if(socket._retryCount > 10){
254
259
  socket.close(1002, 'ping timeout')
255
260
  if(subscriber){
256
261
  subscriber.disconnect()
257
262
  }
258
- else{
259
- console.log('CLOSE SOCKET#2', token.substring(0, 10) + '...')
260
- }
263
+ }
264
+ else{
265
+ pingTimer = setTimeout(ping, 3000)
261
266
  }
262
267
  }
263
268
  else{
264
- setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
269
+ pingTimer = setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
265
270
  }
266
271
  }, 3000)
267
272
  }
268
- setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
273
+ pingTimer = setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
274
+
275
+ socket.on('close', () => {
276
+ clearTimeout(pingTimer)
277
+ })
269
278
  }
270
279
  })
271
280
  }
272
281
 
282
+ stats(){
283
+ let authenticated = 0
284
+ this._instance.clients.forEach(socket => {
285
+ if(socket.isAuth) authenticated++
286
+ })
287
+
288
+ return {
289
+ pid: process.pid,
290
+ connections: this._instance.clients.size,
291
+ authenticated,
292
+ totalConnections: this._connectionId,
293
+ debugConnections: Object.keys(this._debugIds).length,
294
+ }
295
+ }
296
+
297
+ clusterStats(){
298
+ return new Promise((resolve) => {
299
+ const workers = {}
300
+ const timeout = setTimeout(() => resolve(this._aggregateStats(workers)), 3000)
301
+
302
+ process.on('message', (packet) => {
303
+ if(packet.type === 'process:msg' && packet.data?.type === 'wss:stats:response'){
304
+ workers[packet.data.pid] = packet.data.stats
305
+ }
306
+
307
+ const expected = parseInt(process.env.instances || '0', 10)
308
+ if(expected > 0 && Object.keys(workers).length >= expected){
309
+ clearTimeout(timeout)
310
+ resolve(this._aggregateStats(workers))
311
+ }
312
+ })
313
+
314
+ process.send({ type: 'process:msg', data: { type: 'wss:stats:request' } })
315
+
316
+ // Include own stats
317
+ workers[process.pid] = this.stats()
318
+ })
319
+ }
320
+
321
+ _aggregateStats(workers){
322
+ const pids = Object.keys(workers)
323
+ return {
324
+ workers: pids.length,
325
+ connections: pids.reduce((sum, pid) => sum + workers[pid].connections, 0),
326
+ authenticated: pids.reduce((sum, pid) => sum + workers[pid].authenticated, 0),
327
+ totalConnections: pids.reduce((sum, pid) => sum + workers[pid].totalConnections, 0),
328
+ debugConnections: pids.reduce((sum, pid) => sum + workers[pid].debugConnections, 0),
329
+ perWorker: workers,
330
+ }
331
+ }
332
+
333
+ initClusterStats(){
334
+ if(process.send){
335
+ process.on('message', (packet) => {
336
+ if(packet.type === 'process:msg' && packet.data?.type === 'wss:stats:request'){
337
+ process.send({
338
+ type: 'process:msg',
339
+ data: { type: 'wss:stats:response', pid: process.pid, stats: this.stats() }
340
+ })
341
+ }
342
+ })
343
+ }
344
+ }
345
+
273
346
  auth(fn){
274
347
  this._authFn.push(fn)
275
348
  }