@zintrust/queue-redis 0.4.27 → 0.4.39
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/BullMQRedisQueue.js +52 -36
- package/dist/RedisPublishClient.js +11 -105
- package/dist/build-manifest.json +11 -11
- package/package.json +3 -3
package/dist/BullMQRedisQueue.js
CHANGED
|
@@ -28,6 +28,53 @@ export const BullMQRedisQueue = (() => {
|
|
|
28
28
|
const queues = new Map();
|
|
29
29
|
let sharedConnection = null;
|
|
30
30
|
let lockProviderCache = null;
|
|
31
|
+
const isRedisProxyEnabled = () => {
|
|
32
|
+
return Env.USE_REDIS_PROXY === true || Env.get('REDIS_PROXY_URL', '').trim() !== '';
|
|
33
|
+
};
|
|
34
|
+
const assertProxyAndWorkersCompatibility = (isWorkersRuntime) => {
|
|
35
|
+
if (isRedisProxyEnabled() && shouldUseHttpProxyDriver() === false) {
|
|
36
|
+
throw ErrorFactory.createConfigError('BullMQ Redis driver does not support REDIS proxy transport directly. Enable QUEUE_HTTP_PROXY_ENABLED=true for queue proxy mode, or disable REDIS proxy mode for direct BullMQ access.');
|
|
37
|
+
}
|
|
38
|
+
if (isWorkersRuntime && Cloudflare.isCloudflareSocketsEnabled() === false) {
|
|
39
|
+
throw ErrorFactory.createConfigError('BullMQ Redis driver requires ENABLE_CLOUDFLARE_SOCKETS=true in Cloudflare Workers. To use HTTP queue proxy mode, set QUEUE_HTTP_PROXY_ENABLED=true and QUEUE_HTTP_PROXY_URL.');
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const resolveQueueRedisConfig = () => {
|
|
43
|
+
const workersHost = Cloudflare.getWorkersVar('WORKERS_REDIS_HOST');
|
|
44
|
+
const workersPortRaw = Cloudflare.getWorkersVar('WORKERS_REDIS_PORT');
|
|
45
|
+
const workersPassword = Cloudflare.getWorkersVar('WORKERS_REDIS_PASSWORD');
|
|
46
|
+
const workersDbRaw = Cloudflare.getWorkersVar('WORKERS_REDIS_QUEUE_DB');
|
|
47
|
+
return {
|
|
48
|
+
host: workersHost !== null && workersHost.trim() !== '' ? workersHost.trim() : Env.REDIS_HOST,
|
|
49
|
+
port: workersPortRaw !== null && Number.isFinite(Number.parseInt(workersPortRaw, 10))
|
|
50
|
+
? Number.parseInt(workersPortRaw, 10)
|
|
51
|
+
: Env.REDIS_PORT,
|
|
52
|
+
password: workersPassword !== null && workersPassword.trim() !== ''
|
|
53
|
+
? workersPassword
|
|
54
|
+
: Env.REDIS_PASSWORD,
|
|
55
|
+
database: workersDbRaw !== null && Number.isFinite(Number.parseInt(workersDbRaw, 10))
|
|
56
|
+
? Number.parseInt(workersDbRaw, 10)
|
|
57
|
+
: Env.getInt('REDIS_QUEUE_DB', 0),
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const assertWorkersHostIsReachable = (isWorkersRuntime, redisConfig) => {
|
|
61
|
+
if (isWorkersRuntime &&
|
|
62
|
+
(redisConfig.host === 'localhost' || redisConfig.host === '127.0.0.1')) {
|
|
63
|
+
throw ErrorFactory.createConfigError('Redis host cannot be localhost in Cloudflare Workers. Use a public Redis host, or enable queue HTTP proxy mode with QUEUE_HTTP_PROXY_ENABLED=true and QUEUE_HTTP_PROXY_URL.');
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const createSharedBullMqConnection = () => {
|
|
67
|
+
const isWorkersRuntime = Cloudflare.getWorkersEnv() !== null;
|
|
68
|
+
assertProxyAndWorkersCompatibility(isWorkersRuntime);
|
|
69
|
+
const redisConfig = resolveQueueRedisConfig();
|
|
70
|
+
assertWorkersHostIsReachable(isWorkersRuntime, redisConfig);
|
|
71
|
+
return createRedisConnection({
|
|
72
|
+
host: redisConfig.host,
|
|
73
|
+
port: redisConfig.port,
|
|
74
|
+
password: redisConfig.password,
|
|
75
|
+
db: redisConfig.database,
|
|
76
|
+
}, 3, { subsystem: 'queue-bullmq' });
|
|
77
|
+
};
|
|
31
78
|
const getDefaultLockDriveName = () => {
|
|
32
79
|
const driver = queueConfig.default;
|
|
33
80
|
return driver.length > 0 ? driver : ZintrustLang.REDIS;
|
|
@@ -59,40 +106,7 @@ export const BullMQRedisQueue = (() => {
|
|
|
59
106
|
const getSharedConnection = () => {
|
|
60
107
|
if (sharedConnection)
|
|
61
108
|
return sharedConnection;
|
|
62
|
-
|
|
63
|
-
if (isWorkersRuntime && Cloudflare.isCloudflareSocketsEnabled() === false) {
|
|
64
|
-
throw ErrorFactory.createConfigError('BullMQ Redis driver requires ENABLE_CLOUDFLARE_SOCKETS=true in Cloudflare Workers. To use HTTP queue proxy mode, set QUEUE_HTTP_PROXY_ENABLED=true and QUEUE_HTTP_PROXY_URL.');
|
|
65
|
-
}
|
|
66
|
-
const workersHost = Cloudflare.getWorkersVar('WORKERS_REDIS_HOST');
|
|
67
|
-
const workersPortRaw = Cloudflare.getWorkersVar('WORKERS_REDIS_PORT');
|
|
68
|
-
const workersPassword = Cloudflare.getWorkersVar('WORKERS_REDIS_PASSWORD');
|
|
69
|
-
const workersDbRaw = Cloudflare.getWorkersVar('WORKERS_REDIS_QUEUE_DB');
|
|
70
|
-
const resolvedHost = workersHost !== null && workersHost.trim() !== '' ? workersHost.trim() : Env.REDIS_HOST;
|
|
71
|
-
const resolvedPort = workersPortRaw !== null && Number.isFinite(Number.parseInt(workersPortRaw, 10))
|
|
72
|
-
? Number.parseInt(workersPortRaw, 10)
|
|
73
|
-
: Env.REDIS_PORT;
|
|
74
|
-
const resolvedPassword = workersPassword !== null && workersPassword.trim() !== ''
|
|
75
|
-
? workersPassword
|
|
76
|
-
: Env.REDIS_PASSWORD;
|
|
77
|
-
const resolvedDb = workersDbRaw !== null && Number.isFinite(Number.parseInt(workersDbRaw, 10))
|
|
78
|
-
? Number.parseInt(workersDbRaw, 10)
|
|
79
|
-
: Env.getInt('REDIS_QUEUE_DB', 0);
|
|
80
|
-
const redisConfig = {
|
|
81
|
-
host: resolvedHost,
|
|
82
|
-
port: resolvedPort,
|
|
83
|
-
password: resolvedPassword,
|
|
84
|
-
database: resolvedDb,
|
|
85
|
-
};
|
|
86
|
-
if (isWorkersRuntime &&
|
|
87
|
-
(redisConfig.host === 'localhost' || redisConfig.host === '127.0.0.1')) {
|
|
88
|
-
throw ErrorFactory.createConfigError('Redis host cannot be localhost in Cloudflare Workers. Use a public Redis host, or enable queue HTTP proxy mode with QUEUE_HTTP_PROXY_ENABLED=true and QUEUE_HTTP_PROXY_URL.');
|
|
89
|
-
}
|
|
90
|
-
sharedConnection = createRedisConnection({
|
|
91
|
-
host: redisConfig.host,
|
|
92
|
-
port: redisConfig.port,
|
|
93
|
-
password: redisConfig.password,
|
|
94
|
-
db: redisConfig.database,
|
|
95
|
-
});
|
|
109
|
+
sharedConnection = createSharedBullMqConnection();
|
|
96
110
|
return sharedConnection; // sharedConnection is IoRedis (compatible with BullMQ)
|
|
97
111
|
};
|
|
98
112
|
const waitForRedisReady = async (client, timeoutMs) => {
|
|
@@ -308,13 +322,15 @@ export const BullMQRedisQueue = (() => {
|
|
|
308
322
|
? deduplication.ttl
|
|
309
323
|
: undefined;
|
|
310
324
|
const replace = deduplication.replace === true;
|
|
325
|
+
const jobId = jobOptions.jobId ?? generateUuid();
|
|
326
|
+
jobOptions.jobId = jobId;
|
|
311
327
|
// Check existing lock
|
|
312
|
-
const hasExistingLock = await checkExistingLock(deduplicationId, provider, replace, queue,
|
|
328
|
+
const hasExistingLock = await checkExistingLock(deduplicationId, provider, replace, queue, jobId);
|
|
313
329
|
if (hasExistingLock) {
|
|
314
330
|
return { payloadToSend: payloadData, shouldReturn: true, returnValue: deduplicationId };
|
|
315
331
|
}
|
|
316
332
|
// Acquire lock
|
|
317
|
-
const lockAcquired = await acquireDeduplicationLock(deduplicationId, provider, ttl, queue,
|
|
333
|
+
const lockAcquired = await acquireDeduplicationLock(deduplicationId, provider, ttl, queue, jobId);
|
|
318
334
|
if (!lockAcquired) {
|
|
319
335
|
return { payloadToSend: payloadData, shouldReturn: true, returnValue: deduplicationId };
|
|
320
336
|
}
|
|
@@ -1,113 +1,19 @@
|
|
|
1
|
-
import { Env, ErrorFactory,
|
|
2
|
-
const
|
|
3
|
-
try {
|
|
4
|
-
const parsed = new URL(baseUrl);
|
|
5
|
-
const path = parsed.pathname.endsWith('/') ? parsed.pathname.slice(0, -1) : parsed.pathname;
|
|
6
|
-
if (path === '' || path === '/')
|
|
7
|
-
return undefined;
|
|
8
|
-
return path;
|
|
9
|
-
}
|
|
10
|
-
catch {
|
|
11
|
-
return undefined;
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
const buildRequestUrl = (baseUrl, path) => {
|
|
15
|
-
const url = new URL(baseUrl);
|
|
16
|
-
const basePath = url.pathname.endsWith('/') ? url.pathname.slice(0, -1) : url.pathname;
|
|
17
|
-
const requestPath = path.startsWith('/') ? path : `/${path}`;
|
|
18
|
-
url.pathname = `${basePath}${requestPath}`;
|
|
19
|
-
return url;
|
|
20
|
-
};
|
|
21
|
-
const buildSigningUrl = (requestUrl, baseUrl) => {
|
|
22
|
-
const prefix = resolveSigningPrefix(baseUrl);
|
|
23
|
-
if (!prefix)
|
|
24
|
-
return requestUrl;
|
|
25
|
-
if (requestUrl.pathname === prefix || requestUrl.pathname.startsWith(`${prefix}/`)) {
|
|
26
|
-
const signingUrl = new URL(requestUrl.toString());
|
|
27
|
-
const stripped = requestUrl.pathname.slice(prefix.length);
|
|
28
|
-
signingUrl.pathname = stripped.startsWith('/') ? stripped : `/${stripped}`;
|
|
29
|
-
return signingUrl;
|
|
30
|
-
}
|
|
31
|
-
return requestUrl;
|
|
32
|
-
};
|
|
1
|
+
import { Env, ErrorFactory, ZintrustLang, createRedisConnection } from '@zintrust/core';
|
|
2
|
+
const createSharedRedisConnection = createRedisConnection;
|
|
33
3
|
let publishClientInstance = null;
|
|
34
4
|
let publishClientConnected = false;
|
|
35
|
-
const resolveProxyBaseUrl = () => {
|
|
36
|
-
const explicit = Env.REDIS_PROXY_URL.trim();
|
|
37
|
-
if (explicit !== '')
|
|
38
|
-
return explicit;
|
|
39
|
-
if (Env.USE_REDIS_PROXY === false)
|
|
40
|
-
return '';
|
|
41
|
-
const host = Env.REDIS_PROXY_HOST || '127.0.0.1';
|
|
42
|
-
const port = Env.REDIS_PROXY_PORT;
|
|
43
|
-
return `http://${host}:${port}`;
|
|
44
|
-
};
|
|
45
|
-
const buildProxySettings = () => {
|
|
46
|
-
const baseUrl = resolveProxyBaseUrl();
|
|
47
|
-
const keyId = Env.REDIS_PROXY_KEY_ID || undefined;
|
|
48
|
-
const secret = Env.REDIS_PROXY_SECRET || Env.APP_KEY || undefined;
|
|
49
|
-
const timeoutMs = Env.REDIS_PROXY_TIMEOUT_MS;
|
|
50
|
-
return { baseUrl, keyId, secret, timeoutMs };
|
|
51
|
-
};
|
|
52
|
-
const buildHeaders = async (settings, requestUrl, body) => {
|
|
53
|
-
const headers = {
|
|
54
|
-
'Content-Type': 'application/json',
|
|
55
|
-
};
|
|
56
|
-
if (settings.keyId && settings.secret) {
|
|
57
|
-
const signingUrl = buildSigningUrl(requestUrl, settings.baseUrl);
|
|
58
|
-
const signed = await SignedRequest.createHeaders({
|
|
59
|
-
method: 'POST',
|
|
60
|
-
url: signingUrl,
|
|
61
|
-
body,
|
|
62
|
-
keyId: settings.keyId,
|
|
63
|
-
secret: settings.secret,
|
|
64
|
-
});
|
|
65
|
-
Object.assign(headers, signed);
|
|
66
|
-
}
|
|
67
|
-
return headers;
|
|
68
|
-
};
|
|
69
|
-
const requestProxy = async (settings, path, payload) => {
|
|
70
|
-
if (settings.baseUrl.trim() === '') {
|
|
71
|
-
throw ErrorFactory.createConfigError('Redis proxy URL is missing (REDIS_PROXY_URL)');
|
|
72
|
-
}
|
|
73
|
-
const body = JSON.stringify(payload);
|
|
74
|
-
const url = buildRequestUrl(settings.baseUrl, path);
|
|
75
|
-
const headers = await buildHeaders(settings, url, body);
|
|
76
|
-
const timeoutSignal = typeof AbortSignal !== 'undefined' && 'timeout' in AbortSignal;
|
|
77
|
-
const signal = timeoutSignal ? AbortSignal.timeout(settings.timeoutMs) : undefined;
|
|
78
|
-
const response = await fetch(url.toString(), {
|
|
79
|
-
method: 'POST',
|
|
80
|
-
headers,
|
|
81
|
-
body,
|
|
82
|
-
signal,
|
|
83
|
-
});
|
|
84
|
-
if (!response.ok) {
|
|
85
|
-
const text = await response.text();
|
|
86
|
-
throw ErrorFactory.createTryCatchError(`Redis proxy request failed (${response.status})`, text);
|
|
87
|
-
}
|
|
88
|
-
return (await response.json());
|
|
89
|
-
};
|
|
90
|
-
const toNumber = (value) => {
|
|
91
|
-
if (typeof value === 'number')
|
|
92
|
-
return value;
|
|
93
|
-
if (typeof value === 'string') {
|
|
94
|
-
const parsed = Number(value);
|
|
95
|
-
return Number.isFinite(parsed) ? parsed : 0;
|
|
96
|
-
}
|
|
97
|
-
return 0;
|
|
98
|
-
};
|
|
99
5
|
const tryCreateProxyPublishClient = async () => {
|
|
100
|
-
|
|
101
|
-
if (settings.baseUrl.trim() === '')
|
|
6
|
+
if (Env.REDIS_PROXY_URL.trim() === '' && Env.USE_REDIS_PROXY !== true)
|
|
102
7
|
return null;
|
|
8
|
+
const client = createSharedRedisConnection({
|
|
9
|
+
host: Env.get('REDIS_HOST', 'localhost'),
|
|
10
|
+
port: Env.getInt('REDIS_PORT', ZintrustLang.REDIS_DEFAULT_PORT),
|
|
11
|
+
password: Env.get('REDIS_PASSWORD'),
|
|
12
|
+
db: Env.getInt('REDIS_QUEUE_DB', ZintrustLang.REDIS_DEFAULT_DB),
|
|
13
|
+
}, 3, { subsystem: 'broadcast-publish' });
|
|
103
14
|
return {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
command: 'PUBLISH',
|
|
107
|
-
args: [channel, message],
|
|
108
|
-
});
|
|
109
|
-
return toNumber(response.result);
|
|
110
|
-
},
|
|
15
|
+
connect: client.connect,
|
|
16
|
+
publish: (channel, message) => client.publish(channel, message),
|
|
111
17
|
};
|
|
112
18
|
};
|
|
113
19
|
/**
|
package/dist/build-manifest.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/queue-redis",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"buildDate": "2026-03-
|
|
3
|
+
"version": "0.4.39",
|
|
4
|
+
"buildDate": "2026-03-30T20:12:42.664Z",
|
|
5
5
|
"buildEnvironment": {
|
|
6
6
|
"node": "v22.22.1",
|
|
7
7
|
"platform": "darwin",
|
|
8
8
|
"arch": "arm64"
|
|
9
9
|
},
|
|
10
10
|
"git": {
|
|
11
|
-
"commit": "
|
|
12
|
-
"branch": "
|
|
11
|
+
"commit": "0d093bc6",
|
|
12
|
+
"branch": "release"
|
|
13
13
|
},
|
|
14
14
|
"package": {
|
|
15
15
|
"engines": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"sha256": "52fb0f688cd17cc7d8e8128e60df6f5eea4c803282382ac75550e6aacee7cbb0"
|
|
30
30
|
},
|
|
31
31
|
"BullMQRedisQueue.js": {
|
|
32
|
-
"size":
|
|
33
|
-
"sha256": "
|
|
32
|
+
"size": 21034,
|
|
33
|
+
"sha256": "4432bacf5e54fe24a8d7aec9f228db5f8c1ea827e9584709b922aecb126942da"
|
|
34
34
|
},
|
|
35
35
|
"HttpQueueDriver.d.ts": {
|
|
36
36
|
"size": 835,
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"sha256": "341a68a3b8603b453146dc721f9d2eaf0d65bb6a1acb67908a9c6f9542b9fd2d"
|
|
54
54
|
},
|
|
55
55
|
"RedisPublishClient.js": {
|
|
56
|
-
"size":
|
|
57
|
-
"sha256": "
|
|
56
|
+
"size": 5464,
|
|
57
|
+
"sha256": "18b785c47b4df689f9969625880d1b559e6cf8c95bb8c3cd3a4112fa75e0d870"
|
|
58
58
|
},
|
|
59
59
|
"RedisQueue.d.ts": {
|
|
60
60
|
"size": 438,
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"sha256": "dc8b2c28b2e288e048423067f90ffbe0389ac813086246a1c8fafeeeab5c142d"
|
|
66
66
|
},
|
|
67
67
|
"build-manifest.json": {
|
|
68
|
-
"size":
|
|
69
|
-
"sha256": "
|
|
68
|
+
"size": 2513,
|
|
69
|
+
"sha256": "91ec17322539b8ed460e0d916878c0ed23ba67537d3c68c08488e3776ac3e35b"
|
|
70
70
|
},
|
|
71
71
|
"index.d.ts": {
|
|
72
72
|
"size": 565,
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
},
|
|
75
75
|
"index.js": {
|
|
76
76
|
"size": 677,
|
|
77
|
-
"sha256": "
|
|
77
|
+
"sha256": "af7ad24e2f89f39773f97c4f7bd1998c8f1507eb48ab5a563bd3a6cf86a11ef3"
|
|
78
78
|
},
|
|
79
79
|
"register.d.ts": {
|
|
80
80
|
"size": 169,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/queue-redis",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.39",
|
|
4
4
|
"description": "Redis queue driver for ZinTrust.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"node": ">=20.0.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@zintrust/core": "^0.4.
|
|
26
|
+
"@zintrust/core": "^0.4.39"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@zintrust/core": "file:../../dist"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"prepublishOnly": "npm run build"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"ioredis": "^5.10.
|
|
46
|
+
"ioredis": "^5.10.1",
|
|
47
47
|
"redis": "^5.11.0"
|
|
48
48
|
}
|
|
49
49
|
}
|