@arcblock/ws 1.13.36 → 1.13.40
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/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.40",
|
|
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.40",
|
|
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": "b540a835813d114c47236f929c7cf0df84949be9"
|
|
47
48
|
}
|