mysql2 3.11.5 → 3.12.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.
- package/lib/pool_cluster.js +131 -49
- package/package.json +1 -1
- package/promise.js +2 -2
- package/typings/mysql/lib/PoolCluster.d.ts +4 -0
package/lib/pool_cluster.js
CHANGED
|
@@ -13,17 +13,30 @@ const EventEmitter = require('events').EventEmitter;
|
|
|
13
13
|
const makeSelector = {
|
|
14
14
|
RR() {
|
|
15
15
|
let index = 0;
|
|
16
|
-
return clusterIds => clusterIds[index++ % clusterIds.length];
|
|
16
|
+
return (clusterIds) => clusterIds[index++ % clusterIds.length];
|
|
17
17
|
},
|
|
18
18
|
RANDOM() {
|
|
19
|
-
return clusterIds =>
|
|
19
|
+
return (clusterIds) =>
|
|
20
20
|
clusterIds[Math.floor(Math.random() * clusterIds.length)];
|
|
21
21
|
},
|
|
22
22
|
ORDER() {
|
|
23
|
-
return clusterIds => clusterIds[0];
|
|
23
|
+
return (clusterIds) => clusterIds[0];
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
const getMonotonicMilliseconds = function () {
|
|
28
|
+
let ms;
|
|
29
|
+
|
|
30
|
+
if (typeof process.hrtime === 'function') {
|
|
31
|
+
ms = process.hrtime();
|
|
32
|
+
ms = ms[0] * 1e3 + ms[1] * 1e-6;
|
|
33
|
+
} else {
|
|
34
|
+
ms = process.uptime() * 1000;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return Math.floor(ms);
|
|
38
|
+
};
|
|
39
|
+
|
|
27
40
|
class PoolNamespace {
|
|
28
41
|
constructor(cluster, pattern, selector) {
|
|
29
42
|
this._cluster = cluster;
|
|
@@ -34,15 +47,28 @@ class PoolNamespace {
|
|
|
34
47
|
getConnection(cb) {
|
|
35
48
|
const clusterNode = this._getClusterNode();
|
|
36
49
|
if (clusterNode === null) {
|
|
37
|
-
|
|
50
|
+
let err = new Error('Pool does Not exist.');
|
|
51
|
+
err.code = 'POOL_NOEXIST';
|
|
52
|
+
|
|
53
|
+
if (this._cluster._findNodeIds(this._pattern, true).length !== 0) {
|
|
54
|
+
err = new Error('Pool does Not have online node.');
|
|
55
|
+
err.code = 'POOL_NONEONLINE';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return cb(err);
|
|
38
59
|
}
|
|
39
60
|
return this._cluster._getConnection(clusterNode, (err, connection) => {
|
|
40
61
|
if (err) {
|
|
62
|
+
if (
|
|
63
|
+
this._cluster._canRetry &&
|
|
64
|
+
this._cluster._findNodeIds(this._pattern).length !== 0
|
|
65
|
+
) {
|
|
66
|
+
this._cluster.emit('warn', err);
|
|
67
|
+
return this.getConnection(cb);
|
|
68
|
+
}
|
|
69
|
+
|
|
41
70
|
return cb(err);
|
|
42
71
|
}
|
|
43
|
-
if (connection === 'retry') {
|
|
44
|
-
return this.getConnection(cb);
|
|
45
|
-
}
|
|
46
72
|
return cb(null, connection);
|
|
47
73
|
});
|
|
48
74
|
}
|
|
@@ -79,9 +105,9 @@ class PoolNamespace {
|
|
|
79
105
|
|
|
80
106
|
/**
|
|
81
107
|
* pool cluster execute
|
|
82
|
-
* @param {*} sql
|
|
83
|
-
* @param {*} values
|
|
84
|
-
* @param {*} cb
|
|
108
|
+
* @param {*} sql
|
|
109
|
+
* @param {*} values
|
|
110
|
+
* @param {*} cb
|
|
85
111
|
*/
|
|
86
112
|
execute(sql, values, cb) {
|
|
87
113
|
if (typeof values === 'function') {
|
|
@@ -123,6 +149,7 @@ class PoolCluster extends EventEmitter {
|
|
|
123
149
|
this._canRetry =
|
|
124
150
|
typeof config.canRetry === 'undefined' ? true : config.canRetry;
|
|
125
151
|
this._removeNodeErrorCount = config.removeNodeErrorCount || 5;
|
|
152
|
+
this._restoreNodeTimeout = config.restoreNodeTimeout || 0;
|
|
126
153
|
this._defaultSelector = config.defaultSelector || 'RR';
|
|
127
154
|
this._closed = false;
|
|
128
155
|
this._lastId = 0;
|
|
@@ -155,13 +182,26 @@ class PoolCluster extends EventEmitter {
|
|
|
155
182
|
this._nodes[id] = {
|
|
156
183
|
id: id,
|
|
157
184
|
errorCount: 0,
|
|
158
|
-
pool: new Pool({ config: new PoolConfig(config) })
|
|
185
|
+
pool: new Pool({ config: new PoolConfig(config) }),
|
|
186
|
+
_offlineUntil: 0
|
|
159
187
|
};
|
|
160
188
|
this._serviceableNodeIds.push(id);
|
|
161
189
|
this._clearFindCaches();
|
|
162
190
|
}
|
|
163
191
|
}
|
|
164
192
|
|
|
193
|
+
remove(pattern) {
|
|
194
|
+
const foundNodeIds = this._findNodeIds(pattern, true);
|
|
195
|
+
|
|
196
|
+
for (let i = 0; i < foundNodeIds.length; i++) {
|
|
197
|
+
const node = this._getNode(foundNodeIds[i]);
|
|
198
|
+
|
|
199
|
+
if (node) {
|
|
200
|
+
this._removeNode(node);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
165
205
|
getConnection(pattern, selector, cb) {
|
|
166
206
|
let namespace;
|
|
167
207
|
if (typeof pattern === 'function') {
|
|
@@ -181,7 +221,7 @@ class PoolCluster extends EventEmitter {
|
|
|
181
221
|
const cb =
|
|
182
222
|
callback !== undefined
|
|
183
223
|
? callback
|
|
184
|
-
: err => {
|
|
224
|
+
: (err) => {
|
|
185
225
|
if (err) {
|
|
186
226
|
throw err;
|
|
187
227
|
}
|
|
@@ -190,11 +230,12 @@ class PoolCluster extends EventEmitter {
|
|
|
190
230
|
process.nextTick(cb);
|
|
191
231
|
return;
|
|
192
232
|
}
|
|
233
|
+
|
|
193
234
|
this._closed = true;
|
|
194
235
|
|
|
195
236
|
let calledBack = false;
|
|
196
237
|
let waitingClose = 0;
|
|
197
|
-
const onEnd = err => {
|
|
238
|
+
const onEnd = (err) => {
|
|
198
239
|
if (!calledBack && (err || --waitingClose <= 0)) {
|
|
199
240
|
calledBack = true;
|
|
200
241
|
return cb(err);
|
|
@@ -205,31 +246,51 @@ class PoolCluster extends EventEmitter {
|
|
|
205
246
|
waitingClose++;
|
|
206
247
|
this._nodes[id].pool.end(onEnd);
|
|
207
248
|
}
|
|
249
|
+
|
|
208
250
|
if (waitingClose === 0) {
|
|
209
251
|
process.nextTick(onEnd);
|
|
210
252
|
}
|
|
211
253
|
}
|
|
212
254
|
|
|
213
|
-
_findNodeIds(pattern) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
255
|
+
_findNodeIds(pattern, includeOffline) {
|
|
256
|
+
let currentTime = 0;
|
|
257
|
+
let foundNodeIds = this._findCaches[pattern];
|
|
258
|
+
|
|
259
|
+
if (typeof this._findCaches[pattern] === 'undefined') {
|
|
260
|
+
if (pattern === '*') {
|
|
261
|
+
// all
|
|
262
|
+
foundNodeIds = this._serviceableNodeIds;
|
|
263
|
+
} else if (this._serviceableNodeIds.indexOf(pattern) !== -1) {
|
|
264
|
+
// one
|
|
265
|
+
foundNodeIds = [pattern];
|
|
266
|
+
} else {
|
|
267
|
+
// wild matching
|
|
268
|
+
const keyword = pattern.substring(pattern.length - 1, 0);
|
|
269
|
+
foundNodeIds = this._serviceableNodeIds.filter((id) =>
|
|
270
|
+
id.startsWith(keyword)
|
|
271
|
+
);
|
|
272
|
+
}
|
|
230
273
|
}
|
|
274
|
+
|
|
231
275
|
this._findCaches[pattern] = foundNodeIds;
|
|
232
|
-
|
|
276
|
+
|
|
277
|
+
if (includeOffline) {
|
|
278
|
+
return foundNodeIds;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return foundNodeIds.filter((nodeId) => {
|
|
282
|
+
const node = this._getNode(nodeId);
|
|
283
|
+
|
|
284
|
+
if (!node._offlineUntil) {
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!currentTime) {
|
|
289
|
+
currentTime = getMonotonicMilliseconds();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return node._offlineUntil <= currentTime;
|
|
293
|
+
});
|
|
233
294
|
}
|
|
234
295
|
|
|
235
296
|
_getNode(id) {
|
|
@@ -237,21 +298,39 @@ class PoolCluster extends EventEmitter {
|
|
|
237
298
|
}
|
|
238
299
|
|
|
239
300
|
_increaseErrorCount(node) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
delete this._nodes[node.id];
|
|
245
|
-
this._clearFindCaches();
|
|
246
|
-
node.pool.end();
|
|
247
|
-
this.emit('remove', node.id);
|
|
248
|
-
}
|
|
301
|
+
const errorCount = ++node.errorCount;
|
|
302
|
+
|
|
303
|
+
if (this._removeNodeErrorCount > errorCount) {
|
|
304
|
+
return;
|
|
249
305
|
}
|
|
306
|
+
|
|
307
|
+
if (this._restoreNodeTimeout > 0) {
|
|
308
|
+
node._offlineUntil =
|
|
309
|
+
getMonotonicMilliseconds() + this._restoreNodeTimeout;
|
|
310
|
+
this.emit('offline', node.id);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
this._removeNode(node);
|
|
315
|
+
this.emit('remove', node.id);
|
|
250
316
|
}
|
|
251
317
|
|
|
252
318
|
_decreaseErrorCount(node) {
|
|
253
|
-
|
|
254
|
-
|
|
319
|
+
let errorCount = node.errorCount;
|
|
320
|
+
|
|
321
|
+
if (errorCount > this._removeNodeErrorCount) {
|
|
322
|
+
errorCount = this._removeNodeErrorCount;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (errorCount < 1) {
|
|
326
|
+
errorCount = 1;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
node.errorCount = errorCount - 1;
|
|
330
|
+
|
|
331
|
+
if (node._offlineUntil) {
|
|
332
|
+
node._offlineUntil = 0;
|
|
333
|
+
this.emit('online', node.id);
|
|
255
334
|
}
|
|
256
335
|
}
|
|
257
336
|
|
|
@@ -259,13 +338,6 @@ class PoolCluster extends EventEmitter {
|
|
|
259
338
|
node.pool.getConnection((err, connection) => {
|
|
260
339
|
if (err) {
|
|
261
340
|
this._increaseErrorCount(node);
|
|
262
|
-
if (this._canRetry) {
|
|
263
|
-
// REVIEW: this seems wrong?
|
|
264
|
-
this.emit('warn', err);
|
|
265
|
-
// eslint-disable-next-line no-console
|
|
266
|
-
console.warn(`[Error] PoolCluster : ${err}`);
|
|
267
|
-
return cb(null, 'retry');
|
|
268
|
-
}
|
|
269
341
|
return cb(err);
|
|
270
342
|
}
|
|
271
343
|
this._decreaseErrorCount(node);
|
|
@@ -275,6 +347,16 @@ class PoolCluster extends EventEmitter {
|
|
|
275
347
|
});
|
|
276
348
|
}
|
|
277
349
|
|
|
350
|
+
_removeNode(node) {
|
|
351
|
+
const index = this._serviceableNodeIds.indexOf(node.id);
|
|
352
|
+
if (index !== -1) {
|
|
353
|
+
this._serviceableNodeIds.splice(index, 1);
|
|
354
|
+
delete this._nodes[node.id];
|
|
355
|
+
this._clearFindCaches();
|
|
356
|
+
node.pool.end();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
278
360
|
_clearFindCaches() {
|
|
279
361
|
this._findCaches = {};
|
|
280
362
|
}
|
package/package.json
CHANGED
package/promise.js
CHANGED
|
@@ -60,7 +60,7 @@ class PromisePoolCluster extends EventEmitter {
|
|
|
60
60
|
super();
|
|
61
61
|
this.poolCluster = poolCluster;
|
|
62
62
|
this.Promise = thePromise || Promise;
|
|
63
|
-
inheritEvents(poolCluster, this, ['warn', 'remove']);
|
|
63
|
+
inheritEvents(poolCluster, this, ['warn', 'remove' , 'online', 'offline']);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
getConnection(pattern, selector) {
|
|
@@ -156,7 +156,7 @@ class PromisePoolCluster extends EventEmitter {
|
|
|
156
156
|
})(func);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
})(['add']);
|
|
159
|
+
})(['add', 'remove']);
|
|
160
160
|
|
|
161
161
|
function createPromisePoolCluster(opts) {
|
|
162
162
|
const corePoolCluster = createPoolCluster(opts);
|
|
@@ -52,6 +52,8 @@ declare class PoolCluster extends EventEmitter {
|
|
|
52
52
|
add(group: string, connectionUri: string): void;
|
|
53
53
|
add(group: string, config: PoolOptions): void;
|
|
54
54
|
|
|
55
|
+
remove(pattern: string): void;
|
|
56
|
+
|
|
55
57
|
end(): void;
|
|
56
58
|
|
|
57
59
|
getConnection(
|
|
@@ -79,6 +81,8 @@ declare class PoolCluster extends EventEmitter {
|
|
|
79
81
|
of(pattern: string, selector?: string): PoolNamespace;
|
|
80
82
|
|
|
81
83
|
on(event: string, listener: (...args: any[]) => void): this;
|
|
84
|
+
on(event: 'online', listener: (nodeId: number) => void): this;
|
|
85
|
+
on(event: 'offline', listener: (nodeId: number) => void): this;
|
|
82
86
|
on(event: 'remove', listener: (nodeId: number) => void): this;
|
|
83
87
|
on(event: 'warn', listener: (err: Error) => void): this;
|
|
84
88
|
}
|