redis-smq 8.0.0-rc.23 → 8.0.0-rc.25
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 +31 -0
- package/README.md +2 -2
- package/dist/cjs/src/common/redis-client/scripts/lua/set-queue-rate-limit.lua +14 -0
- package/dist/cjs/src/common/redis-client/scripts/scripts.d.ts +2 -1
- package/dist/cjs/src/common/redis-client/scripts/scripts.js +4 -0
- package/dist/cjs/src/lib/namespace/errors/index.d.ts +1 -0
- package/dist/cjs/src/lib/namespace/errors/index.js +3 -1
- package/dist/cjs/src/lib/namespace/errors/namespace-invalid-namespace.error.d.ts +4 -0
- package/dist/cjs/src/lib/namespace/errors/namespace-invalid-namespace.error.js +8 -0
- package/dist/cjs/src/lib/namespace/namespace.js +2 -2
- package/dist/cjs/src/lib/queue/_/_parse-queue-extended-params.js +2 -2
- package/dist/cjs/src/lib/queue/_/_parse-queue-params-and-validate.d.ts +4 -0
- package/dist/cjs/src/lib/queue/_/_parse-queue-params-and-validate.js +22 -0
- package/dist/cjs/src/lib/queue/_/_queue-exists.d.ts +4 -0
- package/dist/cjs/src/lib/queue/_/_queue-exists.js +15 -0
- package/dist/cjs/src/lib/queue/queue.js +3 -9
- package/dist/cjs/src/lib/queue-rate-limit/errors/index.d.ts +1 -0
- package/dist/cjs/src/lib/queue-rate-limit/errors/index.js +3 -1
- package/dist/cjs/src/lib/queue-rate-limit/errors/queue-rate-limit-queue-not-found.error.d.ts +4 -0
- package/dist/cjs/src/lib/queue-rate-limit/errors/queue-rate-limit-queue-not-found.error.js +8 -0
- package/dist/cjs/src/lib/queue-rate-limit/queue-rate-limit.js +95 -79
- package/dist/esm/src/common/redis-client/scripts/lua/set-queue-rate-limit.lua +14 -0
- package/dist/esm/src/common/redis-client/scripts/scripts.d.ts +2 -1
- package/dist/esm/src/common/redis-client/scripts/scripts.js +4 -0
- package/dist/esm/src/lib/namespace/errors/index.d.ts +1 -0
- package/dist/esm/src/lib/namespace/errors/index.js +1 -0
- package/dist/esm/src/lib/namespace/errors/namespace-invalid-namespace.error.d.ts +4 -0
- package/dist/esm/src/lib/namespace/errors/namespace-invalid-namespace.error.js +4 -0
- package/dist/esm/src/lib/namespace/namespace.js +3 -3
- package/dist/esm/src/lib/queue/_/_parse-queue-extended-params.js +2 -2
- package/dist/esm/src/lib/queue/_/_parse-queue-params-and-validate.d.ts +4 -0
- package/dist/esm/src/lib/queue/_/_parse-queue-params-and-validate.js +18 -0
- package/dist/esm/src/lib/queue/_/_queue-exists.d.ts +4 -0
- package/dist/esm/src/lib/queue/_/_queue-exists.js +11 -0
- package/dist/esm/src/lib/queue/queue.js +3 -9
- package/dist/esm/src/lib/queue-rate-limit/errors/index.d.ts +1 -0
- package/dist/esm/src/lib/queue-rate-limit/errors/index.js +1 -0
- package/dist/esm/src/lib/queue-rate-limit/errors/queue-rate-limit-queue-not-found.error.d.ts +4 -0
- package/dist/esm/src/lib/queue-rate-limit/errors/queue-rate-limit-queue-not-found.error.js +4 -0
- package/dist/esm/src/lib/queue-rate-limit/queue-rate-limit.js +96 -80
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## [8.0.0-rc.25](https://github.com/weyoss/redis-smq/compare/v8.0.0-rc.24...v8.0.0-rc.25) (2024-07-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Documentation
|
|
7
|
+
|
|
8
|
+
* add a link to redis-smq-rest-api ([a1ab6fc](https://github.com/weyoss/redis-smq/commit/a1ab6fc594b4d32de5f4e4257fbf46c2447f0018))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Misc
|
|
12
|
+
|
|
13
|
+
* make redis-smq-common a peer dependency ([3b7dbab](https://github.com/weyoss/redis-smq/commit/3b7dbab7a14fc3b11aa75badc36a396727fb4f3b))
|
|
14
|
+
|
|
15
|
+
## [8.0.0-rc.24](https://github.com/weyoss/redis-smq/compare/v8.0.0-rc.23...v8.0.0-rc.24) (2024-05-15)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **namespace:** replace generic error in getNamespaceQueues() ([aa9c8e5](https://github.com/weyoss/redis-smq/commit/aa9c8e5a125bdf1fc8e200263618693671219882))
|
|
21
|
+
* **queue-rate-limit:** always validate queue existence ([538cf78](https://github.com/weyoss/redis-smq/commit/538cf786b3b3131f137d1488d6d130323acb571d))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Documentation
|
|
25
|
+
|
|
26
|
+
* add new error classes reference ([6c39625](https://github.com/weyoss/redis-smq/commit/6c3962589537a83fe345e349743a798e73e751a6))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Codebase Refactoring
|
|
30
|
+
|
|
31
|
+
* **queue-rate-limit:** move QueueRateLimit.set() logic to LUA ([d104a9c](https://github.com/weyoss/redis-smq/commit/d104a9c038ea321e5e18049bffefc54850d4294f))
|
|
32
|
+
* **queue:** return the original error instance ([14228ec](https://github.com/weyoss/redis-smq/commit/14228ec255776cabf2a9202078cd016f80b5f5da))
|
|
33
|
+
|
|
3
34
|
## [8.0.0-rc.23](https://github.com/weyoss/redis-smq/compare/v8.0.0-rc.22...v8.0.0-rc.23) (2024-05-10)
|
|
4
35
|
|
|
5
36
|
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing the
|
|
|
30
30
|
* Messages can be [set to expire](docs/api/classes/ProducibleMessage.md#setttl) when not delivered within a given amount of time or to have a [consumption timeout](docs/api/classes/ProducibleMessage.md#setconsumetimeout) while being in process.
|
|
31
31
|
* Queues may be [rate Limited](docs/queue-rate-limiting.md) to control the rate at which the messages are consumed.
|
|
32
32
|
* Has a builtin [scheduler](docs/scheduling-messages.md) allowing messages [to be delayed](docs/api/classes/ProducibleMessage.md#setscheduleddelay), [to be delivered for N times](docs/api/classes/ProducibleMessage.md#setscheduledrepeat) with an optional [period between deliveries](docs/api/classes/ProducibleMessage.md#setscheduledrepeatperiod), or simply [to be scheduled using CRON expressions](docs/api/classes/ProducibleMessage.md#setscheduledcron).
|
|
33
|
-
* Provides [an HTTP
|
|
33
|
+
* Provides [an HTTP interface](https://github.com/weyoss/redis-smq-rest-api) to interact with the message queue using a RESTful API.
|
|
34
34
|
* RedisSMQ can be managed also from your [web browser](https://github.com/weyoss/redis-smq-monitor-client).
|
|
35
35
|
* Either [node-redis](https://github.com/redis/node-redis) or [ioredis](https://github.com/luin/ioredis) can be used as a Redis client.
|
|
36
36
|
* [Highly optimized](https://lgtm.com/projects/g/weyoss/redis-smq/context:javascript), implemented using pure callbacks, with small memory footprint and no memory leaks. See [Callback vs Promise vs Async/Await benchmarks](https://gist.github.com/weyoss/24f9ecbda175d943a48cb7ec38bde821).
|
|
@@ -57,7 +57,7 @@ Current RedisSMQ v8 RC status:
|
|
|
57
57
|
|
|
58
58
|
- [x] RedisSMQ Common Library
|
|
59
59
|
- [x] RedisSMQ
|
|
60
|
-
- [
|
|
60
|
+
- [x] [RESTful API](https://github.com/weyoss/redis-smq-rest-api)
|
|
61
61
|
- [ ] Web UI (WIP)
|
|
62
62
|
|
|
63
63
|
If you wish to get the latest updates early feel free to try RedisSMQ v8 RC. Do not hesitate to report any bug or issue if encountered.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
local keyQueueProperties = KEYS[1]
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
local EQueuePropertyRateLimit = ARGV[1]
|
|
6
|
+
local rateLimit = ARGV[2]
|
|
7
|
+
|
|
8
|
+
local result = redis.call("EXISTS", keyQueueProperties)
|
|
9
|
+
if result == 0 then
|
|
10
|
+
return 'QUEUE_NOT_FOUND';
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
redis.call("HSET", keyQueueProperties, EQueuePropertyRateLimit, rateLimit)
|
|
14
|
+
return 'OK'
|
|
@@ -11,6 +11,7 @@ export declare enum ELuaScriptName {
|
|
|
11
11
|
DELETE_MESSAGE = "DELETE_MESSAGE",
|
|
12
12
|
FETCH_MESSAGE_FOR_PROCESSING = "FETCH_MESSAGE_FOR_PROCESSING",
|
|
13
13
|
DELETE_CONSUMER_GROUP = "DELETE_CONSUMER_GROUP",
|
|
14
|
-
CLEANUP_OFFLINE_CONSUMER = "CLEANUP_OFFLINE_CONSUMER"
|
|
14
|
+
CLEANUP_OFFLINE_CONSUMER = "CLEANUP_OFFLINE_CONSUMER",
|
|
15
|
+
SET_QUEUE_RATE_LIMIT = "SET_QUEUE_RATE_LIMIT"
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=scripts.d.ts.map
|
|
@@ -42,6 +42,7 @@ var ELuaScriptName;
|
|
|
42
42
|
ELuaScriptName["FETCH_MESSAGE_FOR_PROCESSING"] = "FETCH_MESSAGE_FOR_PROCESSING";
|
|
43
43
|
ELuaScriptName["DELETE_CONSUMER_GROUP"] = "DELETE_CONSUMER_GROUP";
|
|
44
44
|
ELuaScriptName["CLEANUP_OFFLINE_CONSUMER"] = "CLEANUP_OFFLINE_CONSUMER";
|
|
45
|
+
ELuaScriptName["SET_QUEUE_RATE_LIMIT"] = "SET_QUEUE_RATE_LIMIT";
|
|
45
46
|
})(ELuaScriptName = exports.ELuaScriptName || (exports.ELuaScriptName = {}));
|
|
46
47
|
redis_smq_common_1.RedisClientAbstract.addScript(ELuaScriptName.PUBLISH_SCHEDULED_MESSAGE, fs
|
|
47
48
|
.readFileSync((0, path_1.resolve)((0, redis_smq_common_1.getDirname)(), './lua/publish-scheduled-message.lua'))
|
|
@@ -78,4 +79,7 @@ redis_smq_common_1.RedisClientAbstract.addScript(ELuaScriptName.DELETE_CONSUMER_
|
|
|
78
79
|
redis_smq_common_1.RedisClientAbstract.addScript(ELuaScriptName.CLEANUP_OFFLINE_CONSUMER, fs
|
|
79
80
|
.readFileSync((0, path_1.resolve)((0, redis_smq_common_1.getDirname)(), './lua/cleanup-offline-consumer.lua'))
|
|
80
81
|
.toString());
|
|
82
|
+
redis_smq_common_1.RedisClientAbstract.addScript(ELuaScriptName.SET_QUEUE_RATE_LIMIT, fs
|
|
83
|
+
.readFileSync((0, path_1.resolve)((0, redis_smq_common_1.getDirname)(), './lua/set-queue-rate-limit.lua'))
|
|
84
|
+
.toString());
|
|
81
85
|
//# sourceMappingURL=scripts.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NamespaceError = exports.NamespaceNotFoundError = void 0;
|
|
3
|
+
exports.NamespaceInvalidNamespaceError = exports.NamespaceError = exports.NamespaceNotFoundError = void 0;
|
|
4
4
|
var namespace_not_found_error_js_1 = require("./namespace-not-found.error.js");
|
|
5
5
|
Object.defineProperty(exports, "NamespaceNotFoundError", { enumerable: true, get: function () { return namespace_not_found_error_js_1.NamespaceNotFoundError; } });
|
|
6
6
|
var namespace_error_js_1 = require("./namespace.error.js");
|
|
7
7
|
Object.defineProperty(exports, "NamespaceError", { enumerable: true, get: function () { return namespace_error_js_1.NamespaceError; } });
|
|
8
|
+
var namespace_invalid_namespace_error_js_1 = require("./namespace-invalid-namespace.error.js");
|
|
9
|
+
Object.defineProperty(exports, "NamespaceInvalidNamespaceError", { enumerable: true, get: function () { return namespace_invalid_namespace_error_js_1.NamespaceInvalidNamespaceError; } });
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NamespaceInvalidNamespaceError = void 0;
|
|
4
|
+
const namespace_error_js_1 = require("./namespace.error.js");
|
|
5
|
+
class NamespaceInvalidNamespaceError extends namespace_error_js_1.NamespaceError {
|
|
6
|
+
}
|
|
7
|
+
exports.NamespaceInvalidNamespaceError = NamespaceInvalidNamespaceError;
|
|
8
|
+
//# sourceMappingURL=namespace-invalid-namespace.error.js.map
|
|
@@ -39,7 +39,7 @@ class Namespace {
|
|
|
39
39
|
getNamespaceQueues(namespace, cb) {
|
|
40
40
|
const ns = redis_keys_js_1.redisKeys.validateRedisKey(namespace);
|
|
41
41
|
if (ns instanceof Error)
|
|
42
|
-
cb(
|
|
42
|
+
cb(new index_js_2.NamespaceInvalidNamespaceError());
|
|
43
43
|
else {
|
|
44
44
|
this.redisClient.getSetInstance((err, client) => {
|
|
45
45
|
if (err)
|
|
@@ -80,7 +80,7 @@ class Namespace {
|
|
|
80
80
|
delete(namespace, cb) {
|
|
81
81
|
const ns = redis_keys_js_1.redisKeys.validateRedisKey(namespace);
|
|
82
82
|
if (ns instanceof Error)
|
|
83
|
-
cb(
|
|
83
|
+
cb(new index_js_2.NamespaceInvalidNamespaceError());
|
|
84
84
|
else {
|
|
85
85
|
this.redisClient.getSetInstance((err, client) => {
|
|
86
86
|
if (err)
|
|
@@ -14,7 +14,7 @@ function _parseQueueExtendedParams(args) {
|
|
|
14
14
|
if (typeof args === 'string') {
|
|
15
15
|
const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(args);
|
|
16
16
|
if (queueParams instanceof Error)
|
|
17
|
-
return
|
|
17
|
+
return queueParams;
|
|
18
18
|
return {
|
|
19
19
|
queueParams,
|
|
20
20
|
groupId: null,
|
|
@@ -23,7 +23,7 @@ function _parseQueueExtendedParams(args) {
|
|
|
23
23
|
if (isQueueParams(args)) {
|
|
24
24
|
const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(args);
|
|
25
25
|
if (queueParams instanceof Error)
|
|
26
|
-
return
|
|
26
|
+
return queueParams;
|
|
27
27
|
return {
|
|
28
28
|
queueParams,
|
|
29
29
|
groupId: null,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ICallback, IRedisClient } from 'redis-smq-common';
|
|
2
|
+
import { IQueueParams } from '../types/queue.js';
|
|
3
|
+
export declare function _parseQueueParamsAndValidate(redisClient: IRedisClient, queue: string | IQueueParams, cb: ICallback<IQueueParams>): void;
|
|
4
|
+
//# sourceMappingURL=_parse-queue-params-and-validate.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._parseQueueParamsAndValidate = void 0;
|
|
4
|
+
const queue_queue_not_found_error_js_1 = require("../errors/queue-queue-not-found.error.js");
|
|
5
|
+
const _parse_queue_params_js_1 = require("./_parse-queue-params.js");
|
|
6
|
+
const _queue_exists_js_1 = require("./_queue-exists.js");
|
|
7
|
+
function _parseQueueParamsAndValidate(redisClient, queue, cb) {
|
|
8
|
+
const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue);
|
|
9
|
+
if (queueParams instanceof Error)
|
|
10
|
+
cb(queueParams);
|
|
11
|
+
else
|
|
12
|
+
(0, _queue_exists_js_1._queueExists)(redisClient, queueParams, (err, reply) => {
|
|
13
|
+
if (err)
|
|
14
|
+
cb(err);
|
|
15
|
+
else if (!reply)
|
|
16
|
+
cb(new queue_queue_not_found_error_js_1.QueueQueueNotFoundError());
|
|
17
|
+
else
|
|
18
|
+
cb(null, queueParams);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
exports._parseQueueParamsAndValidate = _parseQueueParamsAndValidate;
|
|
22
|
+
//# sourceMappingURL=_parse-queue-params-and-validate.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ICallback, IRedisClient } from 'redis-smq-common';
|
|
2
|
+
import { IQueueParams } from '../types/queue.js';
|
|
3
|
+
export declare function _queueExists(redisClient: IRedisClient, queue: IQueueParams, cb: ICallback<boolean>): void;
|
|
4
|
+
//# sourceMappingURL=_queue-exists.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._queueExists = void 0;
|
|
4
|
+
const redis_keys_js_1 = require("../../../common/redis-keys/redis-keys.js");
|
|
5
|
+
function _queueExists(redisClient, queue, cb) {
|
|
6
|
+
const { keyQueues } = redis_keys_js_1.redisKeys.getMainKeys();
|
|
7
|
+
redisClient.sismember(keyQueues, JSON.stringify(queue), (err, reply) => {
|
|
8
|
+
if (err)
|
|
9
|
+
cb(err);
|
|
10
|
+
else
|
|
11
|
+
cb(null, !!reply);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
exports._queueExists = _queueExists;
|
|
15
|
+
//# sourceMappingURL=_queue-exists.js.map
|
|
@@ -11,6 +11,7 @@ const _delete_queue_js_1 = require("./_/_delete-queue.js");
|
|
|
11
11
|
const _get_queue_properties_js_1 = require("./_/_get-queue-properties.js");
|
|
12
12
|
const _get_queues_js_1 = require("./_/_get-queues.js");
|
|
13
13
|
const _parse_queue_params_js_1 = require("./_/_parse-queue-params.js");
|
|
14
|
+
const _queue_exists_js_1 = require("./_/_queue-exists.js");
|
|
14
15
|
const index_js_3 = require("./errors/index.js");
|
|
15
16
|
const index_js_4 = require("./types/index.js");
|
|
16
17
|
class Queue {
|
|
@@ -85,15 +86,8 @@ class Queue {
|
|
|
85
86
|
cb(err);
|
|
86
87
|
else if (!client)
|
|
87
88
|
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
88
|
-
else
|
|
89
|
-
|
|
90
|
-
client.sismember(keyQueues, JSON.stringify(queueParams), (err, reply) => {
|
|
91
|
-
if (err)
|
|
92
|
-
cb(err);
|
|
93
|
-
else
|
|
94
|
-
cb(null, !!reply);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
89
|
+
else
|
|
90
|
+
(0, _queue_exists_js_1._queueExists)(client, queueParams, cb);
|
|
97
91
|
});
|
|
98
92
|
}
|
|
99
93
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { QueueRateLimitError } from './queue-rate-limit.error.js';
|
|
2
2
|
export { QueueRateLimitInvalidIntervalError } from './queue-rate-limit-invalid-interval.error.js';
|
|
3
3
|
export { QueueRateLimitInvalidLimitError } from './queue-rate-limit-invalid-limit.error.js';
|
|
4
|
+
export { QueueRateLimitQueueNotFoundError } from './queue-rate-limit-queue-not-found.error.js';
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.QueueRateLimitInvalidLimitError = exports.QueueRateLimitInvalidIntervalError = exports.QueueRateLimitError = void 0;
|
|
3
|
+
exports.QueueRateLimitQueueNotFoundError = exports.QueueRateLimitInvalidLimitError = exports.QueueRateLimitInvalidIntervalError = exports.QueueRateLimitError = void 0;
|
|
4
4
|
var queue_rate_limit_error_js_1 = require("./queue-rate-limit.error.js");
|
|
5
5
|
Object.defineProperty(exports, "QueueRateLimitError", { enumerable: true, get: function () { return queue_rate_limit_error_js_1.QueueRateLimitError; } });
|
|
6
6
|
var queue_rate_limit_invalid_interval_error_js_1 = require("./queue-rate-limit-invalid-interval.error.js");
|
|
7
7
|
Object.defineProperty(exports, "QueueRateLimitInvalidIntervalError", { enumerable: true, get: function () { return queue_rate_limit_invalid_interval_error_js_1.QueueRateLimitInvalidIntervalError; } });
|
|
8
8
|
var queue_rate_limit_invalid_limit_error_js_1 = require("./queue-rate-limit-invalid-limit.error.js");
|
|
9
9
|
Object.defineProperty(exports, "QueueRateLimitInvalidLimitError", { enumerable: true, get: function () { return queue_rate_limit_invalid_limit_error_js_1.QueueRateLimitInvalidLimitError; } });
|
|
10
|
+
var queue_rate_limit_queue_not_found_error_js_1 = require("./queue-rate-limit-queue-not-found.error.js");
|
|
11
|
+
Object.defineProperty(exports, "QueueRateLimitQueueNotFoundError", { enumerable: true, get: function () { return queue_rate_limit_queue_not_found_error_js_1.QueueRateLimitQueueNotFoundError; } });
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueueRateLimitQueueNotFoundError = void 0;
|
|
4
|
+
const queue_rate_limit_error_js_1 = require("./queue-rate-limit.error.js");
|
|
5
|
+
class QueueRateLimitQueueNotFoundError extends queue_rate_limit_error_js_1.QueueRateLimitError {
|
|
6
|
+
}
|
|
7
|
+
exports.QueueRateLimitQueueNotFoundError = QueueRateLimitQueueNotFoundError;
|
|
8
|
+
//# sourceMappingURL=queue-rate-limit-queue-not-found.error.js.map
|
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.QueueRateLimit = void 0;
|
|
4
4
|
const redis_smq_common_1 = require("redis-smq-common");
|
|
5
5
|
const redis_client_instance_js_1 = require("../../common/redis-client/redis-client-instance.js");
|
|
6
|
+
const scripts_js_1 = require("../../common/redis-client/scripts/scripts.js");
|
|
6
7
|
const redis_keys_js_1 = require("../../common/redis-keys/redis-keys.js");
|
|
7
8
|
const index_js_1 = require("../../config/index.js");
|
|
9
|
+
const _parse_queue_params_and_validate_js_1 = require("../queue/_/_parse-queue-params-and-validate.js");
|
|
8
10
|
const index_js_2 = require("../queue/index.js");
|
|
9
|
-
const _parse_queue_params_js_1 = require("../queue/_/_parse-queue-params.js");
|
|
10
11
|
const _has_rate_limit_exceeded_js_1 = require("./_/_has-rate-limit-exceeded.js");
|
|
11
12
|
const index_js_3 = require("./errors/index.js");
|
|
12
13
|
class QueueRateLimit {
|
|
@@ -20,91 +21,106 @@ class QueueRateLimit {
|
|
|
20
21
|
this.queue = new index_js_2.Queue();
|
|
21
22
|
}
|
|
22
23
|
clear(queue, cb) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
25
|
+
if (err)
|
|
26
|
+
cb(err);
|
|
27
|
+
else if (!client)
|
|
28
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
29
|
+
else
|
|
30
|
+
(0, _parse_queue_params_and_validate_js_1._parseQueueParamsAndValidate)(client, queue, (err, queueParams) => {
|
|
31
|
+
if (err)
|
|
32
|
+
cb(err);
|
|
33
|
+
else if (!queueParams)
|
|
34
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
35
|
+
else {
|
|
36
|
+
const { keyQueueProperties, keyQueueRateLimitCounter } = redis_keys_js_1.redisKeys.getQueueKeys(queueParams, null);
|
|
37
|
+
const multi = client.multi();
|
|
38
|
+
multi.hdel(keyQueueProperties, String(index_js_2.EQueueProperty.RATE_LIMIT));
|
|
39
|
+
multi.del(keyQueueRateLimitCounter);
|
|
40
|
+
multi.exec((err) => cb(err));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
});
|
|
41
44
|
}
|
|
42
45
|
set(queue, rateLimit, cb) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
47
|
+
if (err)
|
|
48
|
+
cb(err);
|
|
49
|
+
else if (!client)
|
|
50
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
51
|
+
else
|
|
52
|
+
(0, _parse_queue_params_and_validate_js_1._parseQueueParamsAndValidate)(client, queue, (err, queueParams) => {
|
|
53
|
+
if (err)
|
|
54
|
+
cb(err);
|
|
55
|
+
else if (!queueParams)
|
|
56
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
57
|
+
else {
|
|
58
|
+
const limit = Number(rateLimit.limit);
|
|
59
|
+
if (isNaN(limit) || limit <= 0) {
|
|
60
|
+
cb(new index_js_3.QueueRateLimitInvalidLimitError());
|
|
61
|
+
}
|
|
62
|
+
const interval = Number(rateLimit.interval);
|
|
63
|
+
if (isNaN(interval) || interval < 1000) {
|
|
64
|
+
cb(new index_js_3.QueueRateLimitInvalidIntervalError());
|
|
65
|
+
}
|
|
66
|
+
const validatedRateLimit = { interval, limit };
|
|
67
|
+
const { keyQueueProperties } = redis_keys_js_1.redisKeys.getQueueKeys(queueParams, null);
|
|
68
|
+
client.runScript(scripts_js_1.ELuaScriptName.SET_QUEUE_RATE_LIMIT, [keyQueueProperties], [index_js_2.EQueueProperty.RATE_LIMIT, JSON.stringify(validatedRateLimit)], (err, reply) => {
|
|
69
|
+
if (err)
|
|
70
|
+
cb(err);
|
|
71
|
+
else if (reply !== 'OK')
|
|
72
|
+
cb(new index_js_3.QueueRateLimitQueueNotFoundError());
|
|
73
|
+
else
|
|
74
|
+
cb();
|
|
75
|
+
});
|
|
60
76
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
client.hset(keyQueueProperties, String(index_js_2.EQueueProperty.RATE_LIMIT), JSON.stringify(validatedRateLimit), (err) => cb(err));
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
67
79
|
}
|
|
68
80
|
hasExceeded(queue, rateLimit, cb) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
82
|
+
if (err)
|
|
83
|
+
cb(err);
|
|
84
|
+
else if (!client)
|
|
85
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
86
|
+
else
|
|
87
|
+
(0, _parse_queue_params_and_validate_js_1._parseQueueParamsAndValidate)(client, queue, (err, queueParams) => {
|
|
88
|
+
if (err)
|
|
89
|
+
cb(err);
|
|
90
|
+
else if (!queueParams)
|
|
91
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
92
|
+
else
|
|
93
|
+
(0, _has_rate_limit_exceeded_js_1._hasRateLimitExceeded)(client, queueParams, rateLimit, cb);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
82
96
|
}
|
|
83
97
|
get(queue, cb) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
99
|
+
if (err)
|
|
100
|
+
cb(err);
|
|
101
|
+
else if (!client)
|
|
102
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
103
|
+
else
|
|
104
|
+
(0, _parse_queue_params_and_validate_js_1._parseQueueParamsAndValidate)(client, queue, (err, queueParams) => {
|
|
105
|
+
if (err)
|
|
106
|
+
cb(err);
|
|
107
|
+
else if (!queueParams)
|
|
108
|
+
cb(new redis_smq_common_1.CallbackEmptyReplyError());
|
|
109
|
+
else {
|
|
110
|
+
const { keyQueueProperties } = redis_keys_js_1.redisKeys.getQueueKeys(queueParams, null);
|
|
111
|
+
client.hget(keyQueueProperties, String(index_js_2.EQueueProperty.RATE_LIMIT), (err, reply) => {
|
|
112
|
+
if (err)
|
|
113
|
+
cb(err);
|
|
114
|
+
else if (!reply)
|
|
115
|
+
cb(null, null);
|
|
116
|
+
else {
|
|
117
|
+
const rateLimit = JSON.parse(reply);
|
|
118
|
+
cb(null, rateLimit);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
108
124
|
}
|
|
109
125
|
}
|
|
110
126
|
exports.QueueRateLimit = QueueRateLimit;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
local keyQueueProperties = KEYS[1]
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
local EQueuePropertyRateLimit = ARGV[1]
|
|
6
|
+
local rateLimit = ARGV[2]
|
|
7
|
+
|
|
8
|
+
local result = redis.call("EXISTS", keyQueueProperties)
|
|
9
|
+
if result == 0 then
|
|
10
|
+
return 'QUEUE_NOT_FOUND';
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
redis.call("HSET", keyQueueProperties, EQueuePropertyRateLimit, rateLimit)
|
|
14
|
+
return 'OK'
|
|
@@ -11,6 +11,7 @@ export declare enum ELuaScriptName {
|
|
|
11
11
|
DELETE_MESSAGE = "DELETE_MESSAGE",
|
|
12
12
|
FETCH_MESSAGE_FOR_PROCESSING = "FETCH_MESSAGE_FOR_PROCESSING",
|
|
13
13
|
DELETE_CONSUMER_GROUP = "DELETE_CONSUMER_GROUP",
|
|
14
|
-
CLEANUP_OFFLINE_CONSUMER = "CLEANUP_OFFLINE_CONSUMER"
|
|
14
|
+
CLEANUP_OFFLINE_CONSUMER = "CLEANUP_OFFLINE_CONSUMER",
|
|
15
|
+
SET_QUEUE_RATE_LIMIT = "SET_QUEUE_RATE_LIMIT"
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=scripts.d.ts.map
|
|
@@ -16,6 +16,7 @@ export var ELuaScriptName;
|
|
|
16
16
|
ELuaScriptName["FETCH_MESSAGE_FOR_PROCESSING"] = "FETCH_MESSAGE_FOR_PROCESSING";
|
|
17
17
|
ELuaScriptName["DELETE_CONSUMER_GROUP"] = "DELETE_CONSUMER_GROUP";
|
|
18
18
|
ELuaScriptName["CLEANUP_OFFLINE_CONSUMER"] = "CLEANUP_OFFLINE_CONSUMER";
|
|
19
|
+
ELuaScriptName["SET_QUEUE_RATE_LIMIT"] = "SET_QUEUE_RATE_LIMIT";
|
|
19
20
|
})(ELuaScriptName = ELuaScriptName || (ELuaScriptName = {}));
|
|
20
21
|
RedisClientAbstract.addScript(ELuaScriptName.PUBLISH_SCHEDULED_MESSAGE, fs
|
|
21
22
|
.readFileSync(resolve(getDirname(), './lua/publish-scheduled-message.lua'))
|
|
@@ -52,4 +53,7 @@ RedisClientAbstract.addScript(ELuaScriptName.DELETE_CONSUMER_GROUP, fs
|
|
|
52
53
|
RedisClientAbstract.addScript(ELuaScriptName.CLEANUP_OFFLINE_CONSUMER, fs
|
|
53
54
|
.readFileSync(resolve(getDirname(), './lua/cleanup-offline-consumer.lua'))
|
|
54
55
|
.toString());
|
|
56
|
+
RedisClientAbstract.addScript(ELuaScriptName.SET_QUEUE_RATE_LIMIT, fs
|
|
57
|
+
.readFileSync(resolve(getDirname(), './lua/set-queue-rate-limit.lua'))
|
|
58
|
+
.toString());
|
|
55
59
|
//# sourceMappingURL=scripts.js.map
|
|
@@ -4,7 +4,7 @@ import { redisKeys } from '../../common/redis-keys/redis-keys.js';
|
|
|
4
4
|
import { Configuration } from '../../config/index.js';
|
|
5
5
|
import { _deleteQueue } from '../queue/_/_delete-queue.js';
|
|
6
6
|
import { _getQueues } from '../queue/_/_get-queues.js';
|
|
7
|
-
import { NamespaceNotFoundError } from './errors/index.js';
|
|
7
|
+
import { NamespaceInvalidNamespaceError, NamespaceNotFoundError, } from './errors/index.js';
|
|
8
8
|
export class Namespace {
|
|
9
9
|
logger;
|
|
10
10
|
redisClient;
|
|
@@ -35,7 +35,7 @@ export class Namespace {
|
|
|
35
35
|
getNamespaceQueues(namespace, cb) {
|
|
36
36
|
const ns = redisKeys.validateRedisKey(namespace);
|
|
37
37
|
if (ns instanceof Error)
|
|
38
|
-
cb(
|
|
38
|
+
cb(new NamespaceInvalidNamespaceError());
|
|
39
39
|
else {
|
|
40
40
|
this.redisClient.getSetInstance((err, client) => {
|
|
41
41
|
if (err)
|
|
@@ -76,7 +76,7 @@ export class Namespace {
|
|
|
76
76
|
delete(namespace, cb) {
|
|
77
77
|
const ns = redisKeys.validateRedisKey(namespace);
|
|
78
78
|
if (ns instanceof Error)
|
|
79
|
-
cb(
|
|
79
|
+
cb(new NamespaceInvalidNamespaceError());
|
|
80
80
|
else {
|
|
81
81
|
this.redisClient.getSetInstance((err, client) => {
|
|
82
82
|
if (err)
|
|
@@ -11,7 +11,7 @@ export function _parseQueueExtendedParams(args) {
|
|
|
11
11
|
if (typeof args === 'string') {
|
|
12
12
|
const queueParams = _parseQueueParams(args);
|
|
13
13
|
if (queueParams instanceof Error)
|
|
14
|
-
return
|
|
14
|
+
return queueParams;
|
|
15
15
|
return {
|
|
16
16
|
queueParams,
|
|
17
17
|
groupId: null,
|
|
@@ -20,7 +20,7 @@ export function _parseQueueExtendedParams(args) {
|
|
|
20
20
|
if (isQueueParams(args)) {
|
|
21
21
|
const queueParams = _parseQueueParams(args);
|
|
22
22
|
if (queueParams instanceof Error)
|
|
23
|
-
return
|
|
23
|
+
return queueParams;
|
|
24
24
|
return {
|
|
25
25
|
queueParams,
|
|
26
26
|
groupId: null,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ICallback, IRedisClient } from 'redis-smq-common';
|
|
2
|
+
import { IQueueParams } from '../types/queue.js';
|
|
3
|
+
export declare function _parseQueueParamsAndValidate(redisClient: IRedisClient, queue: string | IQueueParams, cb: ICallback<IQueueParams>): void;
|
|
4
|
+
//# sourceMappingURL=_parse-queue-params-and-validate.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { QueueQueueNotFoundError } from '../errors/queue-queue-not-found.error.js';
|
|
2
|
+
import { _parseQueueParams } from './_parse-queue-params.js';
|
|
3
|
+
import { _queueExists } from './_queue-exists.js';
|
|
4
|
+
export function _parseQueueParamsAndValidate(redisClient, queue, cb) {
|
|
5
|
+
const queueParams = _parseQueueParams(queue);
|
|
6
|
+
if (queueParams instanceof Error)
|
|
7
|
+
cb(queueParams);
|
|
8
|
+
else
|
|
9
|
+
_queueExists(redisClient, queueParams, (err, reply) => {
|
|
10
|
+
if (err)
|
|
11
|
+
cb(err);
|
|
12
|
+
else if (!reply)
|
|
13
|
+
cb(new QueueQueueNotFoundError());
|
|
14
|
+
else
|
|
15
|
+
cb(null, queueParams);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=_parse-queue-params-and-validate.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ICallback, IRedisClient } from 'redis-smq-common';
|
|
2
|
+
import { IQueueParams } from '../types/queue.js';
|
|
3
|
+
export declare function _queueExists(redisClient: IRedisClient, queue: IQueueParams, cb: ICallback<boolean>): void;
|
|
4
|
+
//# sourceMappingURL=_queue-exists.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { redisKeys } from '../../../common/redis-keys/redis-keys.js';
|
|
2
|
+
export function _queueExists(redisClient, queue, cb) {
|
|
3
|
+
const { keyQueues } = redisKeys.getMainKeys();
|
|
4
|
+
redisClient.sismember(keyQueues, JSON.stringify(queue), (err, reply) => {
|
|
5
|
+
if (err)
|
|
6
|
+
cb(err);
|
|
7
|
+
else
|
|
8
|
+
cb(null, !!reply);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=_queue-exists.js.map
|
|
@@ -8,6 +8,7 @@ import { _deleteQueue } from './_/_delete-queue.js';
|
|
|
8
8
|
import { _getQueueProperties } from './_/_get-queue-properties.js';
|
|
9
9
|
import { _getQueues } from './_/_get-queues.js';
|
|
10
10
|
import { _parseQueueParams } from './_/_parse-queue-params.js';
|
|
11
|
+
import { _queueExists } from './_/_queue-exists.js';
|
|
11
12
|
import { QueueQueueExistsError } from './errors/index.js';
|
|
12
13
|
import { EQueueProperty, } from './types/index.js';
|
|
13
14
|
export class Queue {
|
|
@@ -82,15 +83,8 @@ export class Queue {
|
|
|
82
83
|
cb(err);
|
|
83
84
|
else if (!client)
|
|
84
85
|
cb(new CallbackEmptyReplyError());
|
|
85
|
-
else
|
|
86
|
-
|
|
87
|
-
client.sismember(keyQueues, JSON.stringify(queueParams), (err, reply) => {
|
|
88
|
-
if (err)
|
|
89
|
-
cb(err);
|
|
90
|
-
else
|
|
91
|
-
cb(null, !!reply);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
86
|
+
else
|
|
87
|
+
_queueExists(client, queueParams, cb);
|
|
94
88
|
});
|
|
95
89
|
}
|
|
96
90
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { QueueRateLimitError } from './queue-rate-limit.error.js';
|
|
2
2
|
export { QueueRateLimitInvalidIntervalError } from './queue-rate-limit-invalid-interval.error.js';
|
|
3
3
|
export { QueueRateLimitInvalidLimitError } from './queue-rate-limit-invalid-limit.error.js';
|
|
4
|
+
export { QueueRateLimitQueueNotFoundError } from './queue-rate-limit-queue-not-found.error.js';
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { QueueRateLimitError } from './queue-rate-limit.error.js';
|
|
2
2
|
export { QueueRateLimitInvalidIntervalError } from './queue-rate-limit-invalid-interval.error.js';
|
|
3
3
|
export { QueueRateLimitInvalidLimitError } from './queue-rate-limit-invalid-limit.error.js';
|
|
4
|
+
export { QueueRateLimitQueueNotFoundError } from './queue-rate-limit-queue-not-found.error.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { async, CallbackEmptyReplyError, logger, } from 'redis-smq-common';
|
|
2
2
|
import { RedisClientInstance } from '../../common/redis-client/redis-client-instance.js';
|
|
3
|
+
import { ELuaScriptName } from '../../common/redis-client/scripts/scripts.js';
|
|
3
4
|
import { redisKeys } from '../../common/redis-keys/redis-keys.js';
|
|
4
5
|
import { Configuration } from '../../config/index.js';
|
|
6
|
+
import { _parseQueueParamsAndValidate } from '../queue/_/_parse-queue-params-and-validate.js';
|
|
5
7
|
import { EQueueProperty, Queue, } from '../queue/index.js';
|
|
6
|
-
import { _parseQueueParams } from '../queue/_/_parse-queue-params.js';
|
|
7
8
|
import { _hasRateLimitExceeded } from './_/_has-rate-limit-exceeded.js';
|
|
8
|
-
import { QueueRateLimitInvalidLimitError, QueueRateLimitInvalidIntervalError, } from './errors/index.js';
|
|
9
|
+
import { QueueRateLimitInvalidLimitError, QueueRateLimitInvalidIntervalError, QueueRateLimitQueueNotFoundError, } from './errors/index.js';
|
|
9
10
|
export class QueueRateLimit {
|
|
10
11
|
redisClient;
|
|
11
12
|
logger;
|
|
@@ -17,91 +18,106 @@ export class QueueRateLimit {
|
|
|
17
18
|
this.queue = new Queue();
|
|
18
19
|
}
|
|
19
20
|
clear(queue, cb) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
22
|
+
if (err)
|
|
23
|
+
cb(err);
|
|
24
|
+
else if (!client)
|
|
25
|
+
cb(new CallbackEmptyReplyError());
|
|
26
|
+
else
|
|
27
|
+
_parseQueueParamsAndValidate(client, queue, (err, queueParams) => {
|
|
28
|
+
if (err)
|
|
29
|
+
cb(err);
|
|
30
|
+
else if (!queueParams)
|
|
31
|
+
cb(new CallbackEmptyReplyError());
|
|
32
|
+
else {
|
|
33
|
+
const { keyQueueProperties, keyQueueRateLimitCounter } = redisKeys.getQueueKeys(queueParams, null);
|
|
34
|
+
const multi = client.multi();
|
|
35
|
+
multi.hdel(keyQueueProperties, String(EQueueProperty.RATE_LIMIT));
|
|
36
|
+
multi.del(keyQueueRateLimitCounter);
|
|
37
|
+
multi.exec((err) => cb(err));
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
38
41
|
}
|
|
39
42
|
set(queue, rateLimit, cb) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
44
|
+
if (err)
|
|
45
|
+
cb(err);
|
|
46
|
+
else if (!client)
|
|
47
|
+
cb(new CallbackEmptyReplyError());
|
|
48
|
+
else
|
|
49
|
+
_parseQueueParamsAndValidate(client, queue, (err, queueParams) => {
|
|
50
|
+
if (err)
|
|
51
|
+
cb(err);
|
|
52
|
+
else if (!queueParams)
|
|
53
|
+
cb(new CallbackEmptyReplyError());
|
|
54
|
+
else {
|
|
55
|
+
const limit = Number(rateLimit.limit);
|
|
56
|
+
if (isNaN(limit) || limit <= 0) {
|
|
57
|
+
cb(new QueueRateLimitInvalidLimitError());
|
|
58
|
+
}
|
|
59
|
+
const interval = Number(rateLimit.interval);
|
|
60
|
+
if (isNaN(interval) || interval < 1000) {
|
|
61
|
+
cb(new QueueRateLimitInvalidIntervalError());
|
|
62
|
+
}
|
|
63
|
+
const validatedRateLimit = { interval, limit };
|
|
64
|
+
const { keyQueueProperties } = redisKeys.getQueueKeys(queueParams, null);
|
|
65
|
+
client.runScript(ELuaScriptName.SET_QUEUE_RATE_LIMIT, [keyQueueProperties], [EQueueProperty.RATE_LIMIT, JSON.stringify(validatedRateLimit)], (err, reply) => {
|
|
66
|
+
if (err)
|
|
67
|
+
cb(err);
|
|
68
|
+
else if (reply !== 'OK')
|
|
69
|
+
cb(new QueueRateLimitQueueNotFoundError());
|
|
70
|
+
else
|
|
71
|
+
cb();
|
|
72
|
+
});
|
|
57
73
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
client.hset(keyQueueProperties, String(EQueueProperty.RATE_LIMIT), JSON.stringify(validatedRateLimit), (err) => cb(err));
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
64
76
|
}
|
|
65
77
|
hasExceeded(queue, rateLimit, cb) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
79
|
+
if (err)
|
|
80
|
+
cb(err);
|
|
81
|
+
else if (!client)
|
|
82
|
+
cb(new CallbackEmptyReplyError());
|
|
83
|
+
else
|
|
84
|
+
_parseQueueParamsAndValidate(client, queue, (err, queueParams) => {
|
|
85
|
+
if (err)
|
|
86
|
+
cb(err);
|
|
87
|
+
else if (!queueParams)
|
|
88
|
+
cb(new CallbackEmptyReplyError());
|
|
89
|
+
else
|
|
90
|
+
_hasRateLimitExceeded(client, queueParams, rateLimit, cb);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
79
93
|
}
|
|
80
94
|
get(queue, cb) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
this.redisClient.getSetInstance((err, client) => {
|
|
96
|
+
if (err)
|
|
97
|
+
cb(err);
|
|
98
|
+
else if (!client)
|
|
99
|
+
cb(new CallbackEmptyReplyError());
|
|
100
|
+
else
|
|
101
|
+
_parseQueueParamsAndValidate(client, queue, (err, queueParams) => {
|
|
102
|
+
if (err)
|
|
103
|
+
cb(err);
|
|
104
|
+
else if (!queueParams)
|
|
105
|
+
cb(new CallbackEmptyReplyError());
|
|
106
|
+
else {
|
|
107
|
+
const { keyQueueProperties } = redisKeys.getQueueKeys(queueParams, null);
|
|
108
|
+
client.hget(keyQueueProperties, String(EQueueProperty.RATE_LIMIT), (err, reply) => {
|
|
109
|
+
if (err)
|
|
110
|
+
cb(err);
|
|
111
|
+
else if (!reply)
|
|
112
|
+
cb(null, null);
|
|
113
|
+
else {
|
|
114
|
+
const rateLimit = JSON.parse(reply);
|
|
115
|
+
cb(null, rateLimit);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
105
121
|
}
|
|
106
122
|
shutdown = (cb) => {
|
|
107
123
|
async.waterfall([this.queue.shutdown, this.redisClient.shutdown], cb);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redis-smq",
|
|
3
|
-
"version": "8.0.0-rc.
|
|
3
|
+
"version": "8.0.0-rc.25",
|
|
4
4
|
"description": "A simple high-performance Redis message queue for Node.js.",
|
|
5
5
|
"author": "Weyoss <weyoss@protonmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,10 +47,12 @@
|
|
|
47
47
|
},
|
|
48
48
|
"./package.json": "./package.json"
|
|
49
49
|
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"redis-smq-common": "3.0.0-rc.15"
|
|
52
|
+
},
|
|
50
53
|
"dependencies": {
|
|
51
54
|
"cron-parser": "4.7.1",
|
|
52
55
|
"lodash": "4.17.21",
|
|
53
|
-
"redis-smq-common": "3.0.0-rc.15",
|
|
54
56
|
"uuid": "9.0.0"
|
|
55
57
|
},
|
|
56
58
|
"devDependencies": {
|