redis-smq-common 1.0.1 → 1.0.2
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 +5 -0
- 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/worker/worker-runner/worker-runner.js +7 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -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;
|
|
@@ -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
|
}
|
package/package.json
CHANGED