bullmq 1.54.5 → 1.56.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/README.md +1 -1
- package/dist/classes/backoffs.js.map +1 -1
- package/dist/classes/child-pool.js +4 -7
- package/dist/classes/child-pool.js.map +1 -1
- package/dist/classes/child-processor.js +8 -8
- package/dist/classes/child-processor.js.map +1 -1
- package/dist/classes/flow-producer.js +2 -2
- package/dist/classes/flow-producer.js.map +1 -1
- package/dist/classes/index.js +14 -14
- package/dist/classes/index.js.map +1 -1
- package/dist/classes/job.d.ts +5 -1
- package/dist/classes/job.js +13 -9
- package/dist/classes/job.js.map +1 -1
- package/dist/classes/master.js +2 -2
- package/dist/classes/master.js.map +1 -1
- package/dist/classes/queue-events.js +6 -6
- package/dist/classes/queue-events.js.map +1 -1
- package/dist/classes/queue-getters.js.map +1 -1
- package/dist/classes/queue-scheduler.js +3 -3
- package/dist/classes/queue-scheduler.js.map +1 -1
- package/dist/classes/queue.js +7 -7
- package/dist/classes/queue.js.map +1 -1
- package/dist/classes/redis-connection.d.ts +0 -1
- package/dist/classes/redis-connection.js +3 -6
- package/dist/classes/redis-connection.js.map +1 -1
- package/dist/classes/repeat.js +2 -2
- package/dist/classes/repeat.js.map +1 -1
- package/dist/classes/sandbox.js +1 -1
- package/dist/classes/sandbox.js.map +1 -1
- package/dist/classes/scripts.js +12 -8
- package/dist/classes/scripts.js.map +1 -1
- package/dist/classes/timer-manager.js +1 -1
- package/dist/classes/timer-manager.js.map +1 -1
- package/dist/classes/worker.d.ts +1 -1
- package/dist/classes/worker.js +16 -14
- package/dist/classes/worker.js.map +1 -1
- package/dist/commands/addJob-9.lua +3 -3
- package/dist/commands/index.d.ts +4 -3
- package/dist/commands/index.js +8 -72
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/moveStalledJobsToWait-8.lua +2 -2
- package/dist/commands/moveToFinished-8.lua +17 -13
- package/dist/commands/removeJob-1.lua +3 -3
- package/dist/commands/script-loader.d.ts +120 -0
- package/dist/commands/script-loader.js +400 -0
- package/dist/commands/script-loader.js.map +1 -0
- package/dist/enums/index.js +1 -1
- package/dist/enums/index.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/interfaces/index.js +19 -19
- package/dist/interfaces/index.js.map +1 -1
- package/dist/interfaces/jobs-options.d.ts +2 -0
- package/dist/utils.js +7 -5
- package/dist/utils.js.map +1 -1
- package/package.json +14 -12
package/dist/commands/index.js
CHANGED
@@ -1,74 +1,10 @@
|
|
1
|
-
|
2
|
-
* Load redis lua scripts.
|
3
|
-
* The name of the script must have the following format:
|
4
|
-
*
|
5
|
-
* cmdName-numKeys.lua
|
6
|
-
*
|
7
|
-
* cmdName must be in camel case format.
|
8
|
-
*
|
9
|
-
* For example:
|
10
|
-
* moveToFinish-3.lua
|
11
|
-
*
|
12
|
-
*/
|
13
|
-
'use strict';
|
1
|
+
"use strict";
|
14
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
15
|
-
exports.
|
16
|
-
const
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
const
|
21
|
-
|
22
|
-
const exists = util.promisify(fs.exists);
|
23
|
-
exports.load = async function (client, pathname, extraIncludes) {
|
24
|
-
const scripts = await loadScripts(pathname, extraIncludes);
|
25
|
-
scripts.forEach((command) => {
|
26
|
-
// Only define the command if not already defined
|
27
|
-
if (!client[command.name]) {
|
28
|
-
client.defineCommand(command.name, command.options);
|
29
|
-
}
|
30
|
-
});
|
31
|
-
};
|
32
|
-
async function loadScripts(dir, extraIncludes) {
|
33
|
-
const files = await readdir(dir);
|
34
|
-
const includes = await exports.loadIncludes(dir, extraIncludes);
|
35
|
-
const luaFiles = files.filter((file) => path.extname(file) === '.lua');
|
36
|
-
if (luaFiles.length === 0) {
|
37
|
-
/**
|
38
|
-
* To prevent unclarified runtime error "updateDelayset is not a function
|
39
|
-
* @see https://github.com/OptimalBits/bull/issues/920
|
40
|
-
*/
|
41
|
-
throw new Error('No .lua files found!');
|
42
|
-
}
|
43
|
-
const commands = [];
|
44
|
-
for (let i = 0; i < luaFiles.length; i++) {
|
45
|
-
const file = luaFiles[i];
|
46
|
-
if (path.extname(file) === '.lua') {
|
47
|
-
const longName = path.basename(file, '.lua');
|
48
|
-
const name = longName.split('-')[0];
|
49
|
-
const numberOfKeys = parseInt(longName.split('-')[1]);
|
50
|
-
const lua = (await readFile(path.join(dir, file))).toString();
|
51
|
-
const compiled = lodash_1.template(lua);
|
52
|
-
commands.push({
|
53
|
-
name,
|
54
|
-
options: { numberOfKeys, lua: compiled(includes) },
|
55
|
-
});
|
56
|
-
}
|
57
|
-
}
|
58
|
-
return commands;
|
59
|
-
}
|
60
|
-
exports.loadIncludes = async function (dir, extraIncludes) {
|
61
|
-
const includes = extraIncludes || {};
|
62
|
-
const includesDir = path.join(dir, 'includes');
|
63
|
-
if (await exists(includesDir)) {
|
64
|
-
const includesFiles = await readdir(includesDir);
|
65
|
-
for (let i = 0; i < includesFiles.length; i++) {
|
66
|
-
const file = includesFiles[i];
|
67
|
-
const lua = await readFile(path.join(includesDir, file));
|
68
|
-
const name = path.basename(file, '.lua');
|
69
|
-
includes[name] = lua.toString();
|
70
|
-
}
|
71
|
-
}
|
72
|
-
return includes;
|
73
|
-
};
|
3
|
+
exports.scriptLoader = exports.ScriptLoader = exports.ScriptLoaderError = void 0;
|
4
|
+
const script_loader_1 = require("./script-loader");
|
5
|
+
Object.defineProperty(exports, "ScriptLoader", { enumerable: true, get: function () { return script_loader_1.ScriptLoader; } });
|
6
|
+
var script_loader_2 = require("./script-loader");
|
7
|
+
Object.defineProperty(exports, "ScriptLoaderError", { enumerable: true, get: function () { return script_loader_2.ScriptLoaderError; } });
|
8
|
+
const scriptLoader = new script_loader_1.ScriptLoader();
|
9
|
+
exports.scriptLoader = scriptLoader;
|
74
10
|
//# sourceMappingURL=index.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":";;;AAAA,mDAA+C;AAKtC,6FALA,4BAAY,OAKA;AAJrB,iDAA6E;AAA3C,kHAAA,iBAAiB,OAAA;AAEnD,MAAM,YAAY,GAAG,IAAI,4BAAY,EAAE,CAAC;AAEjB,oCAAY"}
|
@@ -75,8 +75,8 @@ if (#stalling > 0) then
|
|
75
75
|
if (stalledCount > MAX_STALLED_JOB_COUNT) then
|
76
76
|
local failedReason = "job stalled more than allowable limit"
|
77
77
|
rcall("ZADD", KEYS[4], ARGV[3], jobId)
|
78
|
-
rcall("
|
79
|
-
failedReason)
|
78
|
+
rcall("HMSET", jobKey, "failedReason",
|
79
|
+
failedReason, "finishedOn", ARGV[3])
|
80
80
|
rcall("XADD", KEYS[8], "*", "event", "failed", "jobId",
|
81
81
|
jobId, 'prev', 'active', 'failedReason',
|
82
82
|
failedReason)
|
@@ -42,8 +42,8 @@
|
|
42
42
|
local rcall = redis.call
|
43
43
|
|
44
44
|
-- Includes
|
45
|
-
|
46
|
-
|
45
|
+
--- @include "includes/updateParentDepsIfNeeded"
|
46
|
+
--- @include "includes/destructureJobKey"
|
47
47
|
|
48
48
|
local jobIdKey = KEYS[3]
|
49
49
|
if rcall("EXISTS",jobIdKey) == 1 then -- // Make sure job exists
|
@@ -70,8 +70,16 @@ if rcall("EXISTS",jobIdKey) == 1 then -- // Make sure job exists
|
|
70
70
|
if(numRemovedElements < 1) then
|
71
71
|
return -3
|
72
72
|
end
|
73
|
-
|
74
|
-
|
73
|
+
|
74
|
+
|
75
|
+
-- Trim events before emiting them to avoid trimming events emitted in this script
|
76
|
+
local maxEvents = rcall("HGET", KEYS[7], "opts.maxLenEvents")
|
77
|
+
if (maxEvents == false) then
|
78
|
+
maxEvents = 10000
|
79
|
+
end
|
80
|
+
rcall("XTRIM", KEYS[6], "MAXLEN", "~", maxEvents)
|
81
|
+
|
82
|
+
-- If job has a parent we need to
|
75
83
|
-- 1) remove this job id from parents dependencies
|
76
84
|
-- 2) move the job Id to parent "processed" set
|
77
85
|
-- 3) push the results into parent "results" list
|
@@ -83,15 +91,15 @@ if rcall("EXISTS",jobIdKey) == 1 then -- // Make sure job exists
|
|
83
91
|
parentId = getJobIdFromKey(ARGV[14])
|
84
92
|
parentQueueKey = getJobKeyPrefix(ARGV[14], ":" .. parentId)
|
85
93
|
end
|
86
|
-
if parentId ~= "" and ARGV[5] == "completed" then
|
94
|
+
if parentId ~= "" and ARGV[5] == "completed" then
|
87
95
|
local parentKey = parentQueueKey .. ":" .. parentId
|
88
96
|
local dependenciesSet = parentKey .. ":dependencies"
|
89
97
|
local result = rcall("SREM", dependenciesSet, jobIdKey)
|
90
|
-
if result == 1 then
|
98
|
+
if result == 1 then
|
91
99
|
updateParentDepsIfNeeded(parentKey, parentQueueKey, dependenciesSet, parentId, jobIdKey, ARGV[4])
|
92
100
|
end
|
93
101
|
end
|
94
|
-
|
102
|
+
|
95
103
|
-- Remove job?
|
96
104
|
local removeJobs = tonumber(ARGV[6])
|
97
105
|
if removeJobs ~= 1 then
|
@@ -140,15 +148,11 @@ if rcall("EXISTS",jobIdKey) == 1 then -- // Make sure job exists
|
|
140
148
|
rcall("HSET", jobKey, "processedOn", ARGV[2])
|
141
149
|
|
142
150
|
return {rcall("HGETALL", jobKey), jobId} -- get job data
|
151
|
+
else
|
152
|
+
rcall("XADD", KEYS[6], "*", "event", "drained");
|
143
153
|
end
|
144
154
|
end
|
145
155
|
|
146
|
-
local maxEvents = rcall("HGET", KEYS[7], "opts.maxLenEvents")
|
147
|
-
if (maxEvents == false) then
|
148
|
-
maxEvents = 10000
|
149
|
-
end
|
150
|
-
rcall("XTRIM", KEYS[6], "MAXLEN", "~", maxEvents)
|
151
|
-
|
152
156
|
return 0
|
153
157
|
else
|
154
158
|
return -1
|
@@ -13,7 +13,7 @@
|
|
13
13
|
local rcall = redis.call
|
14
14
|
|
15
15
|
-- Includes
|
16
|
-
|
16
|
+
--- @include "includes/destructureJobKey"
|
17
17
|
|
18
18
|
-- recursively check if there are no locks on the
|
19
19
|
-- jobs to be removed.
|
@@ -45,13 +45,13 @@ local function removeJob( prefix, jobId)
|
|
45
45
|
local jobKey = prefix .. jobId;
|
46
46
|
|
47
47
|
-- Check if this job has a parent. If so we will just remove it from
|
48
|
-
-- the parent child list, but if it is the last child we should move the parent to "wait/paused"
|
48
|
+
-- the parent child list, but if it is the last child we should move the parent to "wait/paused"
|
49
49
|
-- which requires code from "moveToFinished"
|
50
50
|
local parentKey = rcall("HGET", jobKey, "parentKey")
|
51
51
|
if( (type(parentKey) == "string") and parentKey ~= "" and (rcall("EXISTS", parentKey) == 1)) then
|
52
52
|
local parentDependenciesKey = parentKey .. ":dependencies"
|
53
53
|
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
54
|
-
if rcall("SCARD", parentDependenciesKey) == 0 then
|
54
|
+
if rcall("SCARD", parentDependenciesKey) == 0 then
|
55
55
|
local parentId = getJobIdFromKey(parentKey)
|
56
56
|
local parentPrefix = getJobKeyPrefix(parentKey, parentId)
|
57
57
|
|
@@ -0,0 +1,120 @@
|
|
1
|
+
import { RedisClient } from '../interfaces';
|
2
|
+
export interface Command {
|
3
|
+
name: string;
|
4
|
+
options: {
|
5
|
+
numberOfKeys: number;
|
6
|
+
lua: string;
|
7
|
+
};
|
8
|
+
}
|
9
|
+
/**
|
10
|
+
* Script metadata
|
11
|
+
*/
|
12
|
+
export interface ScriptMetadata {
|
13
|
+
/**
|
14
|
+
* Name of the script
|
15
|
+
*/
|
16
|
+
name: string;
|
17
|
+
numberOfKeys?: number;
|
18
|
+
/**
|
19
|
+
* The path to the script. For includes, this is the normalized path,
|
20
|
+
* whereas it may not be normalized for the top-level parent
|
21
|
+
*/
|
22
|
+
path: string;
|
23
|
+
/**
|
24
|
+
* The raw script content
|
25
|
+
*/
|
26
|
+
content: string;
|
27
|
+
/**
|
28
|
+
* A hash of the normalized path for easy replacement in the parent
|
29
|
+
*/
|
30
|
+
token: string;
|
31
|
+
/**
|
32
|
+
* Metadata on the scripts that this script includes
|
33
|
+
*/
|
34
|
+
includes: ScriptMetadata[];
|
35
|
+
}
|
36
|
+
export declare class ScriptLoaderError extends Error {
|
37
|
+
readonly path: string;
|
38
|
+
/**
|
39
|
+
* The include stack
|
40
|
+
*/
|
41
|
+
readonly includes: string[];
|
42
|
+
readonly line: number;
|
43
|
+
readonly position: number;
|
44
|
+
constructor(message: string, path: string, stack?: string[], line?: number, position?: number);
|
45
|
+
}
|
46
|
+
/**
|
47
|
+
* Lua script loader with include support
|
48
|
+
*/
|
49
|
+
export declare class ScriptLoader {
|
50
|
+
/**
|
51
|
+
* Map an alias to a path
|
52
|
+
*/
|
53
|
+
private pathMapper;
|
54
|
+
private clientScripts;
|
55
|
+
/**
|
56
|
+
* Cache commands by dir
|
57
|
+
*/
|
58
|
+
private commandCache;
|
59
|
+
private rootPath;
|
60
|
+
constructor();
|
61
|
+
/**
|
62
|
+
* Add a script path mapping. Allows includes of the form "<includes>/utils.lua" where `includes` is a user
|
63
|
+
* defined path
|
64
|
+
* @param name - the name of the mapping. Note: do not include angle brackets
|
65
|
+
* @param mappedPath - if a relative path is passed, it's relative to the *caller* of this function.
|
66
|
+
* Mapped paths are also accepted, e.g. "~/server/scripts/lua" or "<base>/includes"
|
67
|
+
*/
|
68
|
+
addPathMapping(name: string, mappedPath: string): void;
|
69
|
+
/**
|
70
|
+
* Resolve the script path considering path mappings
|
71
|
+
* @param scriptName - the name of the script
|
72
|
+
* @param stack - the include stack, for nicer errors
|
73
|
+
*/
|
74
|
+
resolvePath(scriptName: string, stack?: string[]): string;
|
75
|
+
/**
|
76
|
+
* Recursively collect all scripts included in a file
|
77
|
+
* @param file - the parent file
|
78
|
+
* @param cache - a cache for file metadata to increase efficiency. Since a file can be included
|
79
|
+
* multiple times, we make sure to load it only once.
|
80
|
+
* @param stack - internal stack to prevent circular references
|
81
|
+
*/
|
82
|
+
private resolveDependencies;
|
83
|
+
/**
|
84
|
+
* Parse a (top-level) lua script
|
85
|
+
* @param filename - the full path to the script
|
86
|
+
* @param content - the content of the script
|
87
|
+
* @param cache - cache
|
88
|
+
*/
|
89
|
+
parseScript(filename: string, content: string, cache?: Map<string, ScriptMetadata>): Promise<ScriptMetadata>;
|
90
|
+
/**
|
91
|
+
* Construct the final version of a file by interpolating its includes in dependency order.
|
92
|
+
* @param file - the file whose content we want to construct
|
93
|
+
* @param processed - a cache to keep track of which includes have already been processed
|
94
|
+
*/
|
95
|
+
interpolate(file: ScriptMetadata, processed?: Set<string>): string;
|
96
|
+
loadCommand(filename: string, cache?: Map<string, ScriptMetadata>): Promise<Command>;
|
97
|
+
/**
|
98
|
+
* Load redis lua scripts.
|
99
|
+
* The name of the script must have the following format:
|
100
|
+
*
|
101
|
+
* cmdName-numKeys.lua
|
102
|
+
*
|
103
|
+
* cmdName must be in camel case format.
|
104
|
+
*
|
105
|
+
* For example:
|
106
|
+
* moveToFinish-3.lua
|
107
|
+
*
|
108
|
+
*/
|
109
|
+
loadScripts(dir?: string, cache?: Map<string, ScriptMetadata>): Promise<Command[]>;
|
110
|
+
/**
|
111
|
+
* Attach all lua scripts in a given directory to a client instance
|
112
|
+
* @param client - redis client to attach script to
|
113
|
+
* @param pathname - the path to the directory containing the scripts
|
114
|
+
*/
|
115
|
+
load(client: RedisClient, pathname: string): Promise<void>;
|
116
|
+
/**
|
117
|
+
* Clears the command cache
|
118
|
+
*/
|
119
|
+
clearCache(): void;
|
120
|
+
}
|