bullmq 6.0.7 → 6.0.8
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/dist/cjs/classes/errors/connection-closed-error.js +10 -2
- package/dist/cjs/classes/redis-connection.js +18 -21
- package/dist/cjs/postgres/sql-loader.js +22 -2
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/cjs/utils/index.js +1 -4
- package/dist/cjs/version.js +1 -1
- package/dist/esm/classes/errors/connection-closed-error.d.ts +8 -0
- package/dist/esm/classes/errors/connection-closed-error.js +9 -1
- package/dist/esm/classes/redis-connection.js +1 -4
- package/dist/esm/postgres/sql-loader.js +23 -3
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils/index.d.ts +6 -2
- package/dist/esm/utils/index.js +1 -4
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +5 -5
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ConnectionClosedError = void 0;
|
|
3
|
+
exports.ConnectionClosedError = exports.CONNECTION_CLOSED_ERROR_MSG = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Error message used when a connection is closed.
|
|
6
|
+
*
|
|
7
|
+
* This mirrors the constant exported by ioredis (`ioredis/built/utils`) but is
|
|
8
|
+
* defined locally so that BullMQ can be used without ioredis installed (for
|
|
9
|
+
* example, when using the PostgreSQL backend).
|
|
10
|
+
*/
|
|
11
|
+
exports.CONNECTION_CLOSED_ERROR_MSG = 'Connection is closed.';
|
|
4
12
|
/**
|
|
5
13
|
* Thrown by any BullMQ Redis adapter (ioredis, node-redis, Bun, …) when a
|
|
6
14
|
* command fails because the connection is already closed or was closed
|
|
@@ -11,7 +19,7 @@ exports.ConnectionClosedError = void 0;
|
|
|
11
19
|
*/
|
|
12
20
|
class ConnectionClosedError extends Error {
|
|
13
21
|
constructor(message, cause) {
|
|
14
|
-
super(message !== null && message !== void 0 ? message :
|
|
22
|
+
super(message !== null && message !== void 0 ? message : exports.CONNECTION_CLOSED_ERROR_MSG);
|
|
15
23
|
this.cause = cause;
|
|
16
24
|
this.name = 'ConnectionClosedError';
|
|
17
25
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
@@ -4,10 +4,7 @@ exports.RedisConnection = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const events_1 = require("events");
|
|
6
6
|
const ioredis_1 = require("ioredis");
|
|
7
|
-
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
const utils_1 = require("ioredis/built/utils");
|
|
10
|
-
const utils_2 = require("../utils");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
11
8
|
const version_1 = require("../version");
|
|
12
9
|
const scripts = require("../scripts");
|
|
13
10
|
const ioredis_client_1 = require("./ioredis-client");
|
|
@@ -44,7 +41,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
44
41
|
this.disabledBlockingClusterReconnect = false;
|
|
45
42
|
// Set extra options defaults
|
|
46
43
|
this.extraOptions = Object.assign({ shared: false, blocking: true, skipVersionCheck: false, skipWaitingForReady: false, clusterReconnectTimeoutMs: DEFAULT_CLUSTER_RECONNECT_TIMEOUT_MS }, extraOptions);
|
|
47
|
-
if (!(0,
|
|
44
|
+
if (!(0, utils_1.isRedisInstance)(opts)) {
|
|
48
45
|
this.checkBlockingOptions(overrideMessage, opts);
|
|
49
46
|
this.opts = Object.assign({ port: 6379, host: '127.0.0.1', retryStrategy: function (times) {
|
|
50
47
|
return Math.max(Math.min(Math.exp(times), 20000), 1000);
|
|
@@ -118,14 +115,14 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
118
115
|
// 'ready' that standalone Redis uses. Treat it as already connected so we
|
|
119
116
|
// don't hang waiting for a 'ready' event that will never fire and end up
|
|
120
117
|
// throwing a spurious "Connection is closed" error during disconnect.
|
|
121
|
-
if (client.status === 'connect' && (0,
|
|
118
|
+
if (client.status === 'connect' && (0, utils_1.isRedisCluster)(client)) {
|
|
122
119
|
return;
|
|
123
120
|
}
|
|
124
121
|
if (client.status === 'wait') {
|
|
125
122
|
return client.connect();
|
|
126
123
|
}
|
|
127
124
|
if (client.status === 'end') {
|
|
128
|
-
throw new connection_closed_error_1.ConnectionClosedError(
|
|
125
|
+
throw new connection_closed_error_1.ConnectionClosedError(connection_closed_error_1.CONNECTION_CLOSED_ERROR_MSG);
|
|
129
126
|
}
|
|
130
127
|
let handleReady;
|
|
131
128
|
let handleEnd;
|
|
@@ -142,7 +139,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
142
139
|
handleEnd = () => {
|
|
143
140
|
if (client.status !== 'end') {
|
|
144
141
|
reject(lastError ||
|
|
145
|
-
new connection_closed_error_1.ConnectionClosedError(
|
|
142
|
+
new connection_closed_error_1.ConnectionClosedError(connection_closed_error_1.CONNECTION_CLOSED_ERROR_MSG));
|
|
146
143
|
}
|
|
147
144
|
else {
|
|
148
145
|
if (lastError) {
|
|
@@ -154,7 +151,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
154
151
|
}
|
|
155
152
|
}
|
|
156
153
|
};
|
|
157
|
-
(0,
|
|
154
|
+
(0, utils_1.increaseMaxListeners)(client, 3);
|
|
158
155
|
client.once('ready', handleReady);
|
|
159
156
|
client.on('end', handleEnd);
|
|
160
157
|
client.once('error', handleError);
|
|
@@ -164,7 +161,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
164
161
|
client.removeListener('end', handleEnd);
|
|
165
162
|
client.removeListener('error', handleError);
|
|
166
163
|
client.removeListener('ready', handleReady);
|
|
167
|
-
(0,
|
|
164
|
+
(0, utils_1.decreaseMaxListeners)(client, 3);
|
|
168
165
|
}
|
|
169
166
|
}
|
|
170
167
|
get client() {
|
|
@@ -194,7 +191,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
194
191
|
this._client = (0, ioredis_client_1.createIORedisClient)(ioredisClient);
|
|
195
192
|
}
|
|
196
193
|
}
|
|
197
|
-
(0,
|
|
194
|
+
(0, utils_1.increaseMaxListeners)(this._client, 3);
|
|
198
195
|
this._client.on('error', this.handleClientError);
|
|
199
196
|
// ioredis treats connection errors as a different event ('close')
|
|
200
197
|
this._client.on('close', this.handleClientClose);
|
|
@@ -209,18 +206,18 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
209
206
|
this.version = versionResult.version;
|
|
210
207
|
this.dbType = versionResult.databaseType;
|
|
211
208
|
if (this.skipVersionCheck !== true && !this.closing) {
|
|
212
|
-
if ((0,
|
|
209
|
+
if ((0, utils_1.isRedisVersionLowerThan)(this.version, RedisConnection.minimumVersion, this.dbType)) {
|
|
213
210
|
throw new Error(`Redis version needs to be greater or equal than ${RedisConnection.minimumVersion} ` +
|
|
214
211
|
`Current: ${this.version}`);
|
|
215
212
|
}
|
|
216
|
-
if ((0,
|
|
213
|
+
if ((0, utils_1.isRedisVersionLowerThan)(this.version, RedisConnection.recommendedMinimumVersion, this.dbType)) {
|
|
217
214
|
console.warn(`It is highly recommended to use a minimum Redis version of ${RedisConnection.recommendedMinimumVersion}
|
|
218
215
|
Current: ${this.version}`);
|
|
219
216
|
}
|
|
220
217
|
}
|
|
221
218
|
this.capabilities = {
|
|
222
|
-
canDoubleTimeout: !(0,
|
|
223
|
-
canBlockFor1Ms: !(0,
|
|
219
|
+
canDoubleTimeout: !(0, utils_1.isRedisVersionLowerThan)(this.version, '6.0.0', this.dbType),
|
|
220
|
+
canBlockFor1Ms: !(0, utils_1.isRedisVersionLowerThan)(this.version, '7.0.8', this.dbType),
|
|
224
221
|
};
|
|
225
222
|
this.status = 'ready';
|
|
226
223
|
}
|
|
@@ -231,7 +228,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
231
228
|
const client = this._client;
|
|
232
229
|
const blockingClient = client;
|
|
233
230
|
if (!this.extraOptions.blocking ||
|
|
234
|
-
!(0,
|
|
231
|
+
!(0, utils_1.isRedisCluster)(client) ||
|
|
235
232
|
typeof blockingClient.bzpopmin !== 'function') {
|
|
236
233
|
return;
|
|
237
234
|
}
|
|
@@ -384,7 +381,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
384
381
|
return client.disconnect();
|
|
385
382
|
}
|
|
386
383
|
const disconnecting = new Promise((resolve, reject) => {
|
|
387
|
-
(0,
|
|
384
|
+
(0, utils_1.increaseMaxListeners)(client, 2);
|
|
388
385
|
client.once('end', resolve);
|
|
389
386
|
client.once('error', reject);
|
|
390
387
|
_resolve = resolve;
|
|
@@ -395,7 +392,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
395
392
|
await disconnecting;
|
|
396
393
|
}
|
|
397
394
|
finally {
|
|
398
|
-
(0,
|
|
395
|
+
(0, utils_1.decreaseMaxListeners)(client, 2);
|
|
399
396
|
client.removeListener('end', _resolve);
|
|
400
397
|
client.removeListener('error', _reject);
|
|
401
398
|
}
|
|
@@ -405,7 +402,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
405
402
|
const client = await this.client;
|
|
406
403
|
for (;;) {
|
|
407
404
|
if (client.status === 'ready' ||
|
|
408
|
-
(client.status === 'connect' && (0,
|
|
405
|
+
(client.status === 'connect' && (0, utils_1.isRedisCluster)(client))) {
|
|
409
406
|
return;
|
|
410
407
|
}
|
|
411
408
|
if (client.status === 'wait' || client.status === 'end') {
|
|
@@ -449,7 +446,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
449
446
|
}
|
|
450
447
|
}
|
|
451
448
|
catch (error) {
|
|
452
|
-
if ((0,
|
|
449
|
+
if ((0, utils_1.isNotConnectionError)(error)) {
|
|
453
450
|
throw error;
|
|
454
451
|
}
|
|
455
452
|
}
|
|
@@ -458,7 +455,7 @@ class RedisConnection extends events_1.EventEmitter {
|
|
|
458
455
|
this._client.off('error', this.handleClientError);
|
|
459
456
|
this._client.off('close', this.handleClientClose);
|
|
460
457
|
this._client.off('ready', this.handleClientReady);
|
|
461
|
-
(0,
|
|
458
|
+
(0, utils_1.decreaseMaxListeners)(this._client, 3);
|
|
462
459
|
this.removeAllListeners();
|
|
463
460
|
this.status = 'closed';
|
|
464
461
|
}
|
|
@@ -4,6 +4,26 @@ exports.loadMigrationSql = loadMigrationSql;
|
|
|
4
4
|
exports.loadCommandSql = loadCommandSql;
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
+
const url_1 = require("url");
|
|
8
|
+
function getDirname() {
|
|
9
|
+
if (typeof __dirname !== 'undefined' && __dirname) {
|
|
10
|
+
return __dirname;
|
|
11
|
+
}
|
|
12
|
+
const stack = new Error().stack || '';
|
|
13
|
+
for (const line of stack.split('\n')) {
|
|
14
|
+
const match = line.match(/(file:\/\/\/[^\s)]+)/);
|
|
15
|
+
if (match) {
|
|
16
|
+
try {
|
|
17
|
+
return (0, path_1.dirname)((0, url_1.fileURLToPath)(match[1]));
|
|
18
|
+
}
|
|
19
|
+
catch (_a) {
|
|
20
|
+
// continue searching
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
throw new Error('Could not determine sql-loader directory path');
|
|
25
|
+
}
|
|
26
|
+
const currentDir = getDirname();
|
|
7
27
|
/**
|
|
8
28
|
* Loads a migration's SQL from its `.sql` file — the portable source of truth
|
|
9
29
|
* shared with the Elixir/Python ports. Results are cached after the first read.
|
|
@@ -13,7 +33,7 @@ const path_1 = require("path");
|
|
|
13
33
|
* analogous to how the Lua scripts are bundled), so the same relative lookup
|
|
14
34
|
* works at runtime.
|
|
15
35
|
*/
|
|
16
|
-
const MIGRATIONS_DIR = (0, path_1.join)(
|
|
36
|
+
const MIGRATIONS_DIR = (0, path_1.join)(currentDir, 'migrations');
|
|
17
37
|
/**
|
|
18
38
|
* Runtime queries live under `commands/`. Each `.sql` file is one parameterized
|
|
19
39
|
* statement (a `SELECT fn(...)` for the PL/pgSQL operations, or a direct
|
|
@@ -22,7 +42,7 @@ const MIGRATIONS_DIR = (0, path_1.join)(__dirname, 'migrations');
|
|
|
22
42
|
* Python/Elixir/PHP/Rust ports (mirroring how the Redis backend's `.lua`
|
|
23
43
|
* scripts never hardcode the key prefix).
|
|
24
44
|
*/
|
|
25
|
-
const COMMANDS_DIR = (0, path_1.join)(
|
|
45
|
+
const COMMANDS_DIR = (0, path_1.join)(currentDir, 'commands');
|
|
26
46
|
const migrationCache = new Map();
|
|
27
47
|
const commandCache = new Map();
|
|
28
48
|
function loadMigrationSql(file) {
|