@arcblock/ws 1.13.34 → 1.13.38
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/server/index.js +55 -13
- package/package.json +3 -2
package/lib/server/index.js
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
const EventEmitter = require('events');
|
2
|
+
const cluster = require('cluster');
|
3
|
+
|
2
4
|
const uuid = require('uuid');
|
3
5
|
const WebSocket = require('ws');
|
6
|
+
const eventHub = cluster.isMaster ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
|
4
7
|
|
5
8
|
const createLogger = require('../logger');
|
6
9
|
|
10
|
+
const sleep = (timeout) => new Promise((resolve) => setTimeout(resolve, timeout));
|
11
|
+
|
7
12
|
const reply = (socket, topic, event, response, status = 'ok') => {
|
8
13
|
if (socket.readyState === WebSocket.OPEN) {
|
9
14
|
const res = JSON.stringify([socket.joinRef, socket.ref, topic, event, { status, response }]);
|
@@ -30,6 +35,7 @@ const defaultHooks = {
|
|
30
35
|
* @param {Object} opts.authenticate - authentication function to be called on connection
|
31
36
|
* @param {Object} opts.hooks - hooks to be called on events
|
32
37
|
* @param {Object} opts.logger - logger used to log messages
|
38
|
+
* @param {Object} opts.broadcastEventName - used in cluster mode, default is '@arcblock/ws:broadcast'
|
33
39
|
* @class WsServer
|
34
40
|
* @extends {EventEmitter}
|
35
41
|
*/
|
@@ -47,6 +53,9 @@ class WsServer extends EventEmitter {
|
|
47
53
|
this.wss.on('error', this.onWssError.bind(this));
|
48
54
|
|
49
55
|
this.topics = {}; // <topic>: Set<socket>
|
56
|
+
|
57
|
+
this.broadcastEventName = opts.broadcastEventName || '@arcblock/ws:broadcast';
|
58
|
+
eventHub.on(this.broadcastEventName, (data) => this._doBroadCast(data));
|
50
59
|
}
|
51
60
|
|
52
61
|
attach(server) {
|
@@ -92,6 +101,11 @@ class WsServer extends EventEmitter {
|
|
92
101
|
let event;
|
93
102
|
let data;
|
94
103
|
let options = {};
|
104
|
+
let cb = () => {};
|
105
|
+
|
106
|
+
if (typeof args[args.length - 1] === 'function') {
|
107
|
+
cb = args.pop();
|
108
|
+
}
|
95
109
|
|
96
110
|
if (args.length < 2) {
|
97
111
|
throw new Error('Broadcasting requires at least 2 arguments');
|
@@ -105,29 +119,57 @@ class WsServer extends EventEmitter {
|
|
105
119
|
[topic, event, data, options] = args;
|
106
120
|
}
|
107
121
|
|
108
|
-
const
|
122
|
+
const enableLog = options.enableLog !== undefined ? !!options.enableLog : true;
|
123
|
+
const replyId = uuid.v4();
|
109
124
|
|
125
|
+
// Count of clients what will receive the message
|
126
|
+
// The count is NOT reliable
|
110
127
|
let count = 0;
|
128
|
+
eventHub.on(replyId, ({ count: c } = {}) => {
|
129
|
+
if (c) {
|
130
|
+
count += c;
|
131
|
+
}
|
132
|
+
});
|
111
133
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
}
|
118
|
-
reply(socket, topic, event, data);
|
119
|
-
});
|
120
|
-
} else if (opts.enableLog) {
|
121
|
-
this.logger.info('no connections when broadcast message', { topic, event });
|
122
|
-
}
|
134
|
+
eventHub.broadcast(this.broadcastEventName, { topic, event, data, options, enableLog, replyId });
|
135
|
+
|
136
|
+
// wait 600ms for message sending by each process
|
137
|
+
await sleep(600);
|
138
|
+
eventHub.off(replyId);
|
123
139
|
|
140
|
+
const opts = { count, topic, event, data, options };
|
141
|
+
cb(opts);
|
124
142
|
try {
|
125
|
-
await this.hooks.postBroadcast(
|
143
|
+
await this.hooks.postBroadcast(opts);
|
126
144
|
} catch (error) {
|
127
145
|
this.logger.error('postBroadcast error', { error });
|
128
146
|
}
|
129
147
|
}
|
130
148
|
|
149
|
+
async _doBroadCast({ topic, event, data, enableLog, replyId } = {}) {
|
150
|
+
try {
|
151
|
+
let count = 0;
|
152
|
+
|
153
|
+
if (this.topics[topic] && this.topics[topic].size) {
|
154
|
+
this.topics[topic].forEach((socket) => {
|
155
|
+
count++;
|
156
|
+
if (enableLog) {
|
157
|
+
this.logger.info('broadcast message to', { topic, event, id: socket.id });
|
158
|
+
}
|
159
|
+
reply(socket, topic, event, data);
|
160
|
+
});
|
161
|
+
} else if (enableLog) {
|
162
|
+
this.logger.info('no connections when broadcast message', { topic, event });
|
163
|
+
}
|
164
|
+
|
165
|
+
if (count > 0 && replyId) {
|
166
|
+
eventHub.broadcast(replyId, { count });
|
167
|
+
}
|
168
|
+
} catch (error) {
|
169
|
+
this.logger.error('_doBroadcast error', { error });
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
131
173
|
/**
|
132
174
|
* Send message to 1 subscriber of a topic, can be used as
|
133
175
|
* - send(socket, event, data)
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ws",
|
3
|
-
"version": "1.13.
|
3
|
+
"version": "1.13.38",
|
4
4
|
"description": "OCAP Chain websocket server and client",
|
5
5
|
"keywords": [
|
6
6
|
"websocket"
|
@@ -34,6 +34,7 @@
|
|
34
34
|
"url": "https://github.com/ArcBlock/asset-chain/issues"
|
35
35
|
},
|
36
36
|
"dependencies": {
|
37
|
+
"@arcblock/event-hub": "1.13.38",
|
37
38
|
"debug": "^4.3.2",
|
38
39
|
"eventemitter3": "^4.0.4",
|
39
40
|
"phoenix": "1.5.12",
|
@@ -43,5 +44,5 @@
|
|
43
44
|
"devDependencies": {
|
44
45
|
"get-port": "^5.1.1"
|
45
46
|
},
|
46
|
-
"gitHead": "
|
47
|
+
"gitHead": "1a63d4006790a3a995317552e6f332be8d523e67"
|
47
48
|
}
|