redis-smq-common 1.0.0 → 1.0.3
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/CHANGELOG.md +21 -0
- package/dist/src/async/async.js +8 -6
- package/dist/src/lock-manager/errors/lock-manager-method-not-allowed.error.d.ts +4 -0
- package/dist/src/lock-manager/errors/lock-manager-method-not-allowed.error.js +11 -0
- package/dist/src/lock-manager/errors/lock-manager-not-acquired.error.d.ts +4 -0
- package/dist/src/lock-manager/errors/lock-manager-not-acquired.error.js +11 -0
- package/dist/src/lock-manager/errors/lock-manager-not-released.error.d.ts +4 -0
- package/dist/src/lock-manager/errors/lock-manager-not-released.error.js +11 -0
- package/dist/src/lock-manager/lock-manager.d.ts +8 -4
- package/dist/src/lock-manager/lock-manager.js +55 -20
- package/dist/src/redis-client/clients/ioredis-client.d.ts +4 -0
- package/dist/src/redis-client/clients/ioredis-client.js +22 -0
- package/dist/src/redis-client/clients/node-redis-v3-client.d.ts +4 -0
- package/dist/src/redis-client/clients/node-redis-v3-client.js +22 -0
- package/dist/src/redis-client/clients/node-redis-v4-client.d.ts +4 -0
- package/dist/src/redis-client/clients/node-redis-v4-client.js +21 -0
- package/dist/src/redis-client/redis-client.d.ts +6 -1
- package/dist/src/redis-client/redis-client.js +6 -0
- package/dist/src/worker/worker-error.d.ts +3 -0
- package/dist/src/worker/worker-error.js +8 -0
- package/dist/src/worker/worker-runner/worker-pool.d.ts +0 -2
- package/dist/src/worker/worker-runner/worker-pool.js +3 -15
- package/dist/src/worker/worker-runner/worker-runner.js +7 -11
- package/dist/src/worker/worker.js +4 -4
- package/package.json +1 -1
- package/dist/src/worker/worker-runner/worker-runner.error.d.ts +0 -3
- package/dist/src/worker/worker-runner/worker-runner.error.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.0.3 (2022-08-16)
|
|
4
|
+
|
|
5
|
+
* [RedisClient] Update tests (6f1fd51)
|
|
6
|
+
* [RedisClient] Make validateRedisVersion() public (c2fccb3)
|
|
7
|
+
* [RedisClient] Support MATCH and COUNT options for sscan (12b24ac)
|
|
8
|
+
* [RedisClient] Fallback to smembers when sscan is not supported (8a4409f)
|
|
9
|
+
* [RedisClient] Test sscan command (17b8279)
|
|
10
|
+
* [RedisClient] Add sscan command (b771873)
|
|
11
|
+
|
|
12
|
+
## 1.0.2 (2022-08-10)
|
|
13
|
+
|
|
14
|
+
* Update LockManager tests (321c8c4)
|
|
15
|
+
* Fix "LockManagerExtendError: Acquired lock could not be extended" (fa3a8e5)
|
|
16
|
+
|
|
17
|
+
## 1.0.1 (2022-07-07)
|
|
18
|
+
|
|
19
|
+
* Remove unused WorkerRunnerError (48e7206)
|
|
20
|
+
* Use namespaced WorkerError (517224c)
|
|
21
|
+
* Make array looping asynchronous (cd66e51)
|
|
22
|
+
* Run workers one by one without a delay (099b488)
|
|
23
|
+
|
|
3
24
|
## 1.0.0 (20220-06-18)
|
|
4
25
|
|
|
5
26
|
* Rename logger/test00018 (f20fdf9)
|
package/dist/src/async/async.js
CHANGED
|
@@ -10,7 +10,7 @@ const eachOf = (collection, iteratee, callback) => {
|
|
|
10
10
|
if (err || idx >= collection.length)
|
|
11
11
|
callback(err);
|
|
12
12
|
else
|
|
13
|
-
iterate();
|
|
13
|
+
setTimeout(() => iterate(), 0);
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
16
|
iterate();
|
|
@@ -30,7 +30,7 @@ const eachIn = (collection, iteratee, callback) => {
|
|
|
30
30
|
if (err || idx >= keys.length)
|
|
31
31
|
callback(err);
|
|
32
32
|
else
|
|
33
|
-
iterate();
|
|
33
|
+
setTimeout(() => iterate(), 0);
|
|
34
34
|
});
|
|
35
35
|
};
|
|
36
36
|
iterate();
|
|
@@ -53,10 +53,12 @@ const waterfall = (tasks, callback) => {
|
|
|
53
53
|
callback(err);
|
|
54
54
|
}
|
|
55
55
|
else if (idx < tasks.length) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
if (args.length)
|
|
58
|
+
tasks[idx](...args, exec);
|
|
59
|
+
else
|
|
60
|
+
tasks[idx](exec);
|
|
61
|
+
}, 0);
|
|
60
62
|
}
|
|
61
63
|
else if (args.length) {
|
|
62
64
|
callback(null, args[0]);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LockManagerMethodNotAllowedError = void 0;
|
|
4
|
+
const lock_manager_error_1 = require("./lock-manager.error");
|
|
5
|
+
class LockManagerMethodNotAllowedError extends lock_manager_error_1.LockManagerError {
|
|
6
|
+
constructor(message = `This method can not be used when autoExtend is enabled`) {
|
|
7
|
+
super(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.LockManagerMethodNotAllowedError = LockManagerMethodNotAllowedError;
|
|
11
|
+
//# sourceMappingURL=lock-manager-method-not-allowed.error.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LockManagerNotAcquiredError = void 0;
|
|
4
|
+
const lock_manager_error_1 = require("./lock-manager.error");
|
|
5
|
+
class LockManagerNotAcquiredError extends lock_manager_error_1.LockManagerError {
|
|
6
|
+
constructor(message = `Can not extend a lock which has not been yet acquired. Maybe a pending operation is in progress.`) {
|
|
7
|
+
super(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.LockManagerNotAcquiredError = LockManagerNotAcquiredError;
|
|
11
|
+
//# sourceMappingURL=lock-manager-not-acquired.error.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LockManagerNotReleasedError = void 0;
|
|
4
|
+
const lock_manager_error_1 = require("./lock-manager.error");
|
|
5
|
+
class LockManagerNotReleasedError extends lock_manager_error_1.LockManagerError {
|
|
6
|
+
constructor(message = `A lock has been already obtained but not yet released or maybe a pending operation is in progress.`) {
|
|
7
|
+
super(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.LockManagerNotReleasedError = LockManagerNotReleasedError;
|
|
11
|
+
//# sourceMappingURL=lock-manager-not-released.error.js.map
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { ICallback } from '../../types';
|
|
3
3
|
import { RedisClient } from '../redis-client/redis-client';
|
|
4
|
-
declare enum ELockStatus {
|
|
4
|
+
export declare enum ELockStatus {
|
|
5
5
|
unlocked = 0,
|
|
6
6
|
locking = 1,
|
|
7
7
|
locked = 2,
|
|
8
8
|
releasing = 3,
|
|
9
|
-
extending = 4
|
|
9
|
+
extending = 4,
|
|
10
|
+
extended = 5
|
|
10
11
|
}
|
|
11
12
|
export declare enum ELuaScript {
|
|
12
13
|
RELEASE_LOCK = "RELEASE_LOCK",
|
|
@@ -22,16 +23,19 @@ export declare class LockManager {
|
|
|
22
23
|
protected status: ELockStatus;
|
|
23
24
|
protected lockingTimer: NodeJS.Timeout | null;
|
|
24
25
|
protected autoExtendTimer: NodeJS.Timeout | null;
|
|
25
|
-
|
|
26
|
+
protected throwExceptions: boolean;
|
|
27
|
+
constructor(redisClient: RedisClient, lockKey: string, ttl: number, retryOnFail?: boolean, autoExtend?: boolean, throwExceptions?: boolean);
|
|
26
28
|
protected resetTimers(): void;
|
|
27
29
|
protected setUnlocked(): void;
|
|
28
30
|
protected setLocked(): void;
|
|
31
|
+
protected setExtended(): void;
|
|
29
32
|
protected extend(cb: ICallback<void>): void;
|
|
30
33
|
protected runAutoExtendTimer(): void;
|
|
31
34
|
acquireLock(cb: ICallback<void>): void;
|
|
32
35
|
extendLock(cb: ICallback<void>): void;
|
|
33
36
|
releaseLock(cb: ICallback<void>): void;
|
|
37
|
+
acquireOrExtend(cb: ICallback<ELockStatus>): void;
|
|
34
38
|
isLocked(): boolean;
|
|
39
|
+
isReleased(): boolean;
|
|
35
40
|
getId(): string;
|
|
36
41
|
}
|
|
37
|
-
export {};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LockManager = exports.ELuaScript = void 0;
|
|
3
|
+
exports.LockManager = exports.ELuaScript = exports.ELockStatus = void 0;
|
|
4
4
|
const redis_client_1 = require("../redis-client/redis-client");
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
|
-
const lock_manager_error_1 = require("./errors/lock-manager.error");
|
|
7
6
|
const lock_manager_abort_error_1 = require("./errors/lock-manager-abort.error");
|
|
8
7
|
const lock_manager_extend_error_1 = require("./errors/lock-manager-extend.error");
|
|
9
8
|
const lock_manager_acquire_error_1 = require("./errors/lock-manager-acquire.error");
|
|
10
9
|
const fs = require("fs");
|
|
10
|
+
const lock_manager_method_not_allowed_error_1 = require("./errors/lock-manager-method-not-allowed.error");
|
|
11
|
+
const lock_manager_not_acquired_error_1 = require("./errors/lock-manager-not-acquired.error");
|
|
12
|
+
const lock_manager_not_released_error_1 = require("./errors/lock-manager-not-released.error");
|
|
11
13
|
var ELockStatus;
|
|
12
14
|
(function (ELockStatus) {
|
|
13
15
|
ELockStatus[ELockStatus["unlocked"] = 0] = "unlocked";
|
|
@@ -15,7 +17,8 @@ var ELockStatus;
|
|
|
15
17
|
ELockStatus[ELockStatus["locked"] = 2] = "locked";
|
|
16
18
|
ELockStatus[ELockStatus["releasing"] = 3] = "releasing";
|
|
17
19
|
ELockStatus[ELockStatus["extending"] = 4] = "extending";
|
|
18
|
-
|
|
20
|
+
ELockStatus[ELockStatus["extended"] = 5] = "extended";
|
|
21
|
+
})(ELockStatus = exports.ELockStatus || (exports.ELockStatus = {}));
|
|
19
22
|
var ELuaScript;
|
|
20
23
|
(function (ELuaScript) {
|
|
21
24
|
ELuaScript["RELEASE_LOCK"] = "RELEASE_LOCK";
|
|
@@ -24,16 +27,18 @@ var ELuaScript;
|
|
|
24
27
|
redis_client_1.RedisClient.addScript(ELuaScript.RELEASE_LOCK, fs.readFileSync(`${__dirname}/redis-client/lua/release-lock.lua`).toString());
|
|
25
28
|
redis_client_1.RedisClient.addScript(ELuaScript.EXTEND_LOCK, fs.readFileSync(`${__dirname}/redis-client/lua/extend-lock.lua`).toString());
|
|
26
29
|
class LockManager {
|
|
27
|
-
constructor(redisClient, lockKey, ttl, retryOnFail = false, autoExtend = false) {
|
|
30
|
+
constructor(redisClient, lockKey, ttl, retryOnFail = false, autoExtend = false, throwExceptions = true) {
|
|
28
31
|
this.status = ELockStatus.unlocked;
|
|
29
32
|
this.lockingTimer = null;
|
|
30
33
|
this.autoExtendTimer = null;
|
|
34
|
+
this.throwExceptions = true;
|
|
31
35
|
this.lockKey = lockKey;
|
|
32
36
|
this.ttl = ttl;
|
|
33
37
|
this.retryOnFail = retryOnFail;
|
|
34
38
|
this.lockId = (0, uuid_1.v4)();
|
|
35
39
|
this.redisClient = redisClient;
|
|
36
40
|
this.autoExtend = autoExtend;
|
|
41
|
+
this.throwExceptions = throwExceptions;
|
|
37
42
|
}
|
|
38
43
|
resetTimers() {
|
|
39
44
|
if (this.lockingTimer) {
|
|
@@ -51,10 +56,12 @@ class LockManager {
|
|
|
51
56
|
setLocked() {
|
|
52
57
|
this.status = ELockStatus.locked;
|
|
53
58
|
}
|
|
59
|
+
setExtended() {
|
|
60
|
+
this.status = ELockStatus.extended;
|
|
61
|
+
}
|
|
54
62
|
extend(cb) {
|
|
55
|
-
if (this.
|
|
56
|
-
cb(new
|
|
57
|
-
}
|
|
63
|
+
if (!this.isLocked())
|
|
64
|
+
cb(new lock_manager_not_acquired_error_1.LockManagerNotAcquiredError());
|
|
58
65
|
else {
|
|
59
66
|
this.status = ELockStatus.extending;
|
|
60
67
|
this.redisClient.runScript(ELuaScript.EXTEND_LOCK, [this.lockKey], [this.lockId, this.ttl], (err, reply) => {
|
|
@@ -67,7 +74,7 @@ class LockManager {
|
|
|
67
74
|
cb(new lock_manager_extend_error_1.LockManagerExtendError());
|
|
68
75
|
}
|
|
69
76
|
else {
|
|
70
|
-
this.
|
|
77
|
+
this.setExtended();
|
|
71
78
|
cb();
|
|
72
79
|
}
|
|
73
80
|
}
|
|
@@ -83,14 +90,14 @@ class LockManager {
|
|
|
83
90
|
this.autoExtendTimer = setTimeout(() => this.extend((err) => {
|
|
84
91
|
if (!err)
|
|
85
92
|
this.runAutoExtendTimer();
|
|
86
|
-
else if (
|
|
93
|
+
else if (this.throwExceptions &&
|
|
94
|
+
!(err instanceof lock_manager_abort_error_1.LockManagerAbortError))
|
|
87
95
|
throw err;
|
|
88
96
|
}), ms);
|
|
89
97
|
}
|
|
90
98
|
acquireLock(cb) {
|
|
91
|
-
if (this.
|
|
92
|
-
cb(new
|
|
93
|
-
}
|
|
99
|
+
if (!this.isReleased())
|
|
100
|
+
cb(new lock_manager_not_released_error_1.LockManagerNotReleasedError());
|
|
94
101
|
else {
|
|
95
102
|
this.status = ELockStatus.locking;
|
|
96
103
|
const lock = () => {
|
|
@@ -134,18 +141,17 @@ class LockManager {
|
|
|
134
141
|
}
|
|
135
142
|
}
|
|
136
143
|
extendLock(cb) {
|
|
137
|
-
if (this.autoExtend)
|
|
138
|
-
cb(new
|
|
139
|
-
}
|
|
144
|
+
if (this.autoExtend)
|
|
145
|
+
cb(new lock_manager_method_not_allowed_error_1.LockManagerMethodNotAllowedError());
|
|
140
146
|
else
|
|
141
147
|
this.extend(cb);
|
|
142
148
|
}
|
|
143
149
|
releaseLock(cb) {
|
|
144
150
|
const status = this.status;
|
|
145
|
-
if (status === ELockStatus.
|
|
146
|
-
cb(new lock_manager_error_1.LockManagerError('A pending releaseLock() call is in progress'));
|
|
147
|
-
else if (status === ELockStatus.unlocked)
|
|
151
|
+
if (status === ELockStatus.unlocked)
|
|
148
152
|
cb();
|
|
153
|
+
else if (!this.isLocked())
|
|
154
|
+
cb(new lock_manager_not_acquired_error_1.LockManagerNotAcquiredError());
|
|
149
155
|
else {
|
|
150
156
|
this.resetTimers();
|
|
151
157
|
this.status = ELockStatus.releasing;
|
|
@@ -159,9 +165,38 @@ class LockManager {
|
|
|
159
165
|
});
|
|
160
166
|
}
|
|
161
167
|
}
|
|
168
|
+
acquireOrExtend(cb) {
|
|
169
|
+
if (this.autoExtend)
|
|
170
|
+
cb(new lock_manager_method_not_allowed_error_1.LockManagerMethodNotAllowedError());
|
|
171
|
+
else {
|
|
172
|
+
const lock = () => {
|
|
173
|
+
this.acquireLock((err) => {
|
|
174
|
+
if (err)
|
|
175
|
+
cb(err);
|
|
176
|
+
else
|
|
177
|
+
cb(null, ELockStatus.locked);
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
if (this.isLocked())
|
|
181
|
+
this.extend((err) => {
|
|
182
|
+
if (err) {
|
|
183
|
+
if (err instanceof lock_manager_extend_error_1.LockManagerExtendError)
|
|
184
|
+
lock();
|
|
185
|
+
else
|
|
186
|
+
cb(err);
|
|
187
|
+
}
|
|
188
|
+
else
|
|
189
|
+
cb(null, ELockStatus.extended);
|
|
190
|
+
});
|
|
191
|
+
else
|
|
192
|
+
lock();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
162
195
|
isLocked() {
|
|
163
|
-
return (this.status === ELockStatus.locked ||
|
|
164
|
-
|
|
196
|
+
return (this.status === ELockStatus.locked || this.status === ELockStatus.extended);
|
|
197
|
+
}
|
|
198
|
+
isReleased() {
|
|
199
|
+
return this.status === ELockStatus.unlocked;
|
|
165
200
|
}
|
|
166
201
|
getId() {
|
|
167
202
|
return this.lockId;
|
|
@@ -17,6 +17,10 @@ export declare class IoredisClient extends RedisClient {
|
|
|
17
17
|
watch(args: string[], cb: ICallback<string>): void;
|
|
18
18
|
unwatch(cb: ICallback<string>): void;
|
|
19
19
|
sismember(key: string, member: string, cb: ICallback<number>): void;
|
|
20
|
+
sscan(key: string, options: {
|
|
21
|
+
MATCH?: string;
|
|
22
|
+
COUNT?: number;
|
|
23
|
+
}, cb: ICallback<string[]>): void;
|
|
20
24
|
zcard(key: string, cb: ICallback<number>): void;
|
|
21
25
|
zrange(key: string, min: number, max: number, cb: ICallback<string[]>): void;
|
|
22
26
|
psubscribe(pattern: string): void;
|
|
@@ -47,6 +47,28 @@ class IoredisClient extends redis_client_1.RedisClient {
|
|
|
47
47
|
sismember(key, member, cb) {
|
|
48
48
|
this.client.sismember(key, member, cb);
|
|
49
49
|
}
|
|
50
|
+
sscan(key, options, cb) {
|
|
51
|
+
const result = new Set();
|
|
52
|
+
const iterate = (position) => {
|
|
53
|
+
const args = [key, position];
|
|
54
|
+
if (options.MATCH)
|
|
55
|
+
args.push('MATCH', options.MATCH);
|
|
56
|
+
if (options.COUNT)
|
|
57
|
+
args.push('COUNT', String(options.COUNT));
|
|
58
|
+
this.client.sscan(...args, (err, [cursor, items]) => {
|
|
59
|
+
if (err)
|
|
60
|
+
cb(err);
|
|
61
|
+
else {
|
|
62
|
+
items.forEach((i) => result.add(i));
|
|
63
|
+
if (cursor === '0')
|
|
64
|
+
cb(null, [...result]);
|
|
65
|
+
else
|
|
66
|
+
iterate(cursor);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
iterate('0');
|
|
71
|
+
}
|
|
50
72
|
zcard(key, cb) {
|
|
51
73
|
this.client.zcard(key, cb);
|
|
52
74
|
}
|
|
@@ -17,6 +17,10 @@ export declare class NodeRedisV3Client extends RedisClient {
|
|
|
17
17
|
watch(args: string[], cb: ICallback<string>): void;
|
|
18
18
|
unwatch(cb: ICallback<string>): void;
|
|
19
19
|
sismember(key: string, member: string, cb: ICallback<number>): void;
|
|
20
|
+
sscan(key: string, options: {
|
|
21
|
+
MATCH?: string;
|
|
22
|
+
COUNT?: number;
|
|
23
|
+
}, cb: ICallback<string[]>): void;
|
|
20
24
|
zcard(key: string, cb: ICallback<number>): void;
|
|
21
25
|
zrange(key: string, min: number, max: number, cb: ICallback<string[]>): void;
|
|
22
26
|
psubscribe(pattern: string): void;
|
|
@@ -74,6 +74,28 @@ class NodeRedisV3Client extends redis_client_1.RedisClient {
|
|
|
74
74
|
sismember(key, member, cb) {
|
|
75
75
|
this.client.sismember(key, member, cb);
|
|
76
76
|
}
|
|
77
|
+
sscan(key, options, cb) {
|
|
78
|
+
const result = new Set();
|
|
79
|
+
const iterate = (position) => {
|
|
80
|
+
const args = [key, position];
|
|
81
|
+
if (options.MATCH)
|
|
82
|
+
args.push('MATCH', options.MATCH);
|
|
83
|
+
if (options.COUNT)
|
|
84
|
+
args.push('COUNT', String(options.COUNT));
|
|
85
|
+
this.client.sscan(...args, (err, [cursor, items]) => {
|
|
86
|
+
if (err)
|
|
87
|
+
cb(err);
|
|
88
|
+
else {
|
|
89
|
+
items.forEach((i) => result.add(i));
|
|
90
|
+
if (cursor === '0')
|
|
91
|
+
cb(null, [...result]);
|
|
92
|
+
else
|
|
93
|
+
iterate(cursor);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
iterate('0');
|
|
98
|
+
}
|
|
77
99
|
zcard(key, cb) {
|
|
78
100
|
this.client.zcard(key, cb);
|
|
79
101
|
}
|
|
@@ -25,6 +25,10 @@ export declare class NodeRedisV4Client extends RedisClient {
|
|
|
25
25
|
unsubscribe(channel: string): void;
|
|
26
26
|
zrangebyscore(key: string, min: number | string, max: number | string, cb: ICallback<string[]>): void;
|
|
27
27
|
smembers(key: string, cb: ICallback<string[]>): void;
|
|
28
|
+
sscan(key: string, options: {
|
|
29
|
+
MATCH?: string;
|
|
30
|
+
COUNT?: number;
|
|
31
|
+
}, cb: ICallback<string[]>): void;
|
|
28
32
|
sadd(key: string, member: string, cb: ICallback<number>): void;
|
|
29
33
|
hgetall(key: string, cb: ICallback<Record<string, string>>): void;
|
|
30
34
|
hget(key: string, field: string, cb: ICallback<string | null>): void;
|
|
@@ -94,6 +94,27 @@ class NodeRedisV4Client extends redis_client_1.RedisClient {
|
|
|
94
94
|
.then((reply) => cb(null, reply))
|
|
95
95
|
.catch(cb);
|
|
96
96
|
}
|
|
97
|
+
sscan(key, options, cb) {
|
|
98
|
+
const result = new Set();
|
|
99
|
+
const iterate = (position) => {
|
|
100
|
+
const args = [
|
|
101
|
+
key,
|
|
102
|
+
position,
|
|
103
|
+
options,
|
|
104
|
+
];
|
|
105
|
+
this.client
|
|
106
|
+
.sScan(...args)
|
|
107
|
+
.then(({ cursor, members }) => {
|
|
108
|
+
members.forEach((i) => result.add(i));
|
|
109
|
+
if (cursor === 0)
|
|
110
|
+
cb(null, [...result]);
|
|
111
|
+
else
|
|
112
|
+
iterate(cursor);
|
|
113
|
+
})
|
|
114
|
+
.catch(cb);
|
|
115
|
+
};
|
|
116
|
+
iterate(0);
|
|
117
|
+
}
|
|
97
118
|
sadd(key, member, cb) {
|
|
98
119
|
this.client
|
|
99
120
|
.sAdd(key, member)
|
|
@@ -12,7 +12,7 @@ export declare abstract class RedisClient extends EventEmitter {
|
|
|
12
12
|
protected static scriptsLoaded: boolean;
|
|
13
13
|
protected static luaScripts: LuaScripts;
|
|
14
14
|
protected connectionClosed: boolean;
|
|
15
|
-
|
|
15
|
+
validateRedisVersion(major: number, feature?: number, minor?: number): boolean;
|
|
16
16
|
abstract set(key: string, value: string, options: {
|
|
17
17
|
expire?: {
|
|
18
18
|
mode: 'EX' | 'PX';
|
|
@@ -33,6 +33,11 @@ export declare abstract class RedisClient extends EventEmitter {
|
|
|
33
33
|
abstract unsubscribe(channel: string): void;
|
|
34
34
|
abstract zrangebyscore(key: string, min: number | string, max: number | string, cb: ICallback<string[]>): void;
|
|
35
35
|
abstract smembers(key: string, cb: ICallback<string[]>): void;
|
|
36
|
+
abstract sscan(key: string, options: {
|
|
37
|
+
MATCH?: string;
|
|
38
|
+
COUNT?: number;
|
|
39
|
+
}, cb: ICallback<string[]>): void;
|
|
40
|
+
sscanFallback(key: string, cb: ICallback<string[]>): void;
|
|
36
41
|
abstract sadd(key: string, member: string, cb: ICallback<number>): void;
|
|
37
42
|
abstract hgetall(key: string, cb: ICallback<Record<string, string>>): void;
|
|
38
43
|
abstract hget(key: string, field: string, cb: ICallback<string | null>): void;
|
|
@@ -25,6 +25,12 @@ class RedisClient extends events_1.EventEmitter {
|
|
|
25
25
|
RedisClient.redisServerVersion[1] >= feature &&
|
|
26
26
|
RedisClient.redisServerVersion[2] >= minor));
|
|
27
27
|
}
|
|
28
|
+
sscanFallback(key, cb) {
|
|
29
|
+
if (this.validateRedisVersion(2, 8))
|
|
30
|
+
this.sscan(key, {}, cb);
|
|
31
|
+
else
|
|
32
|
+
this.smembers(key, cb);
|
|
33
|
+
}
|
|
28
34
|
zpophgetrpush(source, sourceHash, destination, cb) {
|
|
29
35
|
this.runScript(ELuaScriptName.ZPOPHGETRPUSH, [source, sourceHash, destination], [], (err, res) => {
|
|
30
36
|
if (err)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WorkerError = void 0;
|
|
4
|
+
const panic_error_1 = require("../errors/panic.error");
|
|
5
|
+
class WorkerError extends panic_error_1.PanicError {
|
|
6
|
+
}
|
|
7
|
+
exports.WorkerError = WorkerError;
|
|
8
|
+
//# sourceMappingURL=worker-error.js.map
|
|
@@ -2,8 +2,6 @@ import { Worker } from '../worker';
|
|
|
2
2
|
import { ICallback } from '../../../types';
|
|
3
3
|
export declare class WorkerPool {
|
|
4
4
|
private pool;
|
|
5
|
-
private index;
|
|
6
|
-
private getCurrentPoolItem;
|
|
7
5
|
work: (cb: ICallback<void>) => void;
|
|
8
6
|
add: (worker: Worker) => number;
|
|
9
7
|
clear: (cb: ICallback<void>) => void;
|
|
@@ -5,22 +5,11 @@ const async_1 = require("../../async/async");
|
|
|
5
5
|
class WorkerPool {
|
|
6
6
|
constructor() {
|
|
7
7
|
this.pool = [];
|
|
8
|
-
this.
|
|
9
|
-
this.getCurrentPoolItem = () => {
|
|
8
|
+
this.work = (cb) => {
|
|
10
9
|
if (this.pool.length) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
if (this.index >= this.pool.length) {
|
|
14
|
-
this.index = 0;
|
|
15
|
-
}
|
|
16
|
-
return worker;
|
|
10
|
+
const tasks = this.pool.map((worker) => (cb) => worker.work(cb));
|
|
11
|
+
async_1.async.waterfall(tasks, cb);
|
|
17
12
|
}
|
|
18
|
-
return null;
|
|
19
|
-
};
|
|
20
|
-
this.work = (cb) => {
|
|
21
|
-
const worker = this.getCurrentPoolItem();
|
|
22
|
-
if (worker)
|
|
23
|
-
worker.work(cb);
|
|
24
13
|
else
|
|
25
14
|
cb();
|
|
26
15
|
};
|
|
@@ -33,7 +22,6 @@ class WorkerPool {
|
|
|
33
22
|
worker.quit(done);
|
|
34
23
|
}, () => {
|
|
35
24
|
this.pool = [];
|
|
36
|
-
this.index = 0;
|
|
37
25
|
cb();
|
|
38
26
|
});
|
|
39
27
|
};
|
|
@@ -14,16 +14,12 @@ class WorkerRunner extends events_1.EventEmitter {
|
|
|
14
14
|
this.onTick = () => {
|
|
15
15
|
async_1.async.waterfall([
|
|
16
16
|
(cb) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
else
|
|
26
|
-
cb();
|
|
17
|
+
this.lockManager.acquireOrExtend((err, status) => {
|
|
18
|
+
if (status === lock_manager_1.ELockStatus.locked) {
|
|
19
|
+
this.logger.info(`Workers are exclusively running from this instance (Lock ID ${this.lockManager.getId()}).`);
|
|
20
|
+
}
|
|
21
|
+
cb(err);
|
|
22
|
+
});
|
|
27
23
|
},
|
|
28
24
|
(cb) => {
|
|
29
25
|
this.workerPool.work(cb);
|
|
@@ -58,7 +54,7 @@ class WorkerRunner extends events_1.EventEmitter {
|
|
|
58
54
|
this.powerManager = new power_manager_1.PowerManager();
|
|
59
55
|
this.redisClient = redisClient;
|
|
60
56
|
this.logger = logger;
|
|
61
|
-
this.lockManager = new lock_manager_1.LockManager(redisClient, keyLock,
|
|
57
|
+
this.lockManager = new lock_manager_1.LockManager(redisClient, keyLock, 60000);
|
|
62
58
|
this.ticker = new ticker_1.Ticker(this.onTick);
|
|
63
59
|
this.workerPool = workerPool;
|
|
64
60
|
}
|
|
@@ -4,14 +4,14 @@ exports.Worker = void 0;
|
|
|
4
4
|
const ticker_1 = require("../ticker/ticker");
|
|
5
5
|
const events_1 = require("../events/events");
|
|
6
6
|
const power_manager_1 = require("../power-manager/power-manager");
|
|
7
|
-
const
|
|
7
|
+
const worker_error_1 = require("./worker-error");
|
|
8
8
|
class Worker {
|
|
9
9
|
constructor(managed, timeout = 1000) {
|
|
10
10
|
this.ticker = null;
|
|
11
11
|
this.powerManager = null;
|
|
12
12
|
this.getTicker = () => {
|
|
13
13
|
if (!this.ticker) {
|
|
14
|
-
throw new
|
|
14
|
+
throw new worker_error_1.WorkerError(`Expected an instance of Ticker`);
|
|
15
15
|
}
|
|
16
16
|
return this.ticker;
|
|
17
17
|
};
|
|
@@ -24,7 +24,7 @@ class Worker {
|
|
|
24
24
|
};
|
|
25
25
|
this.run = () => {
|
|
26
26
|
if (this.managed) {
|
|
27
|
-
throw new
|
|
27
|
+
throw new worker_error_1.WorkerError('You can not run a managed worker');
|
|
28
28
|
}
|
|
29
29
|
const powerManager = this.getPowerManager();
|
|
30
30
|
powerManager.goingUp();
|
|
@@ -54,7 +54,7 @@ class Worker {
|
|
|
54
54
|
}
|
|
55
55
|
getPowerManager() {
|
|
56
56
|
if (!this.powerManager) {
|
|
57
|
-
throw new
|
|
57
|
+
throw new worker_error_1.WorkerError('Expected an instance of PowerManager');
|
|
58
58
|
}
|
|
59
59
|
return this.powerManager;
|
|
60
60
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WorkerRunnerError = void 0;
|
|
4
|
-
const redis_smq_error_1 = require("../../errors/redis-smq.error");
|
|
5
|
-
class WorkerRunnerError extends redis_smq_error_1.RedisSMQError {
|
|
6
|
-
}
|
|
7
|
-
exports.WorkerRunnerError = WorkerRunnerError;
|
|
8
|
-
//# sourceMappingURL=worker-runner.error.js.map
|