@burdenoff/be-sdk 2026.514.1 → 2026.516.1
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/EventQueueFactory-DGHBOV7I.js +8 -0
- package/dist/{EventQueueFactory-TWDDFMQY.js.map → EventQueueFactory-DGHBOV7I.js.map} +1 -1
- package/dist/cache/index.d.ts +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/{chunk-4B765NQA.js → chunk-24VR7PF3.js} +2 -2
- package/dist/{chunk-4B765NQA.js.map → chunk-24VR7PF3.js.map} +1 -1
- package/dist/{chunk-6JHB4FDQ.js → chunk-462GJL5K.js} +5 -5
- package/dist/{chunk-6JHB4FDQ.js.map → chunk-462GJL5K.js.map} +1 -1
- package/dist/{chunk-MI72VKNQ.js → chunk-7V6GUNGP.js} +3 -3
- package/dist/{chunk-MI72VKNQ.js.map → chunk-7V6GUNGP.js.map} +1 -1
- package/dist/{chunk-L72RC2EI.js → chunk-CCV2AVAI.js} +3 -3
- package/dist/{chunk-L72RC2EI.js.map → chunk-CCV2AVAI.js.map} +1 -1
- package/dist/{chunk-3JBKPVWY.js → chunk-FSTWNBRX.js} +5 -5
- package/dist/{chunk-3JBKPVWY.js.map → chunk-FSTWNBRX.js.map} +1 -1
- package/dist/{chunk-Q6HJARHV.js → chunk-KLYAIEAX.js} +3 -3
- package/dist/{chunk-Q6HJARHV.js.map → chunk-KLYAIEAX.js.map} +1 -1
- package/dist/{chunk-EMSON3UD.js → chunk-LRGXT37B.js} +4 -74
- package/dist/chunk-LRGXT37B.js.map +1 -0
- package/dist/{chunk-Y4TPKRZB.js → chunk-M3PYLAPT.js} +3 -3
- package/dist/{chunk-Y4TPKRZB.js.map → chunk-M3PYLAPT.js.map} +1 -1
- package/dist/{chunk-QKJR4L7B.js → chunk-N52W3RQA.js} +100 -6
- package/dist/chunk-N52W3RQA.js.map +1 -0
- package/dist/{chunk-6PKIKOTT.js → chunk-Q6N74R6S.js} +71 -68
- package/dist/chunk-Q6N74R6S.js.map +1 -0
- package/dist/{chunk-A46X4Y5Q.js → chunk-SNW4BLF2.js} +3 -3
- package/dist/{chunk-A46X4Y5Q.js.map → chunk-SNW4BLF2.js.map} +1 -1
- package/dist/{chunk-NAOHXHUP.js → chunk-U455UF4O.js} +3 -3
- package/dist/{chunk-NAOHXHUP.js.map → chunk-U455UF4O.js.map} +1 -1
- package/dist/event-queue/index.d.ts +1 -1
- package/dist/event-queue/index.js +4 -4
- package/dist/export/index.js +3 -3
- package/dist/gateway/index.js +2 -2
- package/dist/gateway/security/index.js +1 -1
- package/dist/graph/index.js +5 -5
- package/dist/graphql/index.js +2 -2
- package/dist/{index-BODgvRtL.d.ts → index-B6IwtUb1.d.ts} +3 -1
- package/dist/{index-eUvoVdr7.d.ts → index-syMAjErz.d.ts} +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +15 -15
- package/dist/init/index.js +5 -5
- package/dist/prisma/index.js +4 -4
- package/package.json +1 -1
- package/dist/EventQueueFactory-TWDDFMQY.js +0 -8
- package/dist/chunk-6PKIKOTT.js.map +0 -1
- package/dist/chunk-EMSON3UD.js.map +0 -1
- package/dist/chunk-QKJR4L7B.js.map +0 -1
|
@@ -2,6 +2,85 @@ import { logger } from './chunk-CBZNP6RF.js';
|
|
|
2
2
|
import { __name } from './chunk-XE4OXN2W.js';
|
|
3
3
|
import { connect, credsAuthenticator } from 'nats';
|
|
4
4
|
|
|
5
|
+
// src/event-queue/implementations/redis-streams/keyspace.ts
|
|
6
|
+
var DEFAULT_PREFIX = "boff:events";
|
|
7
|
+
var REGISTRY_PREFIX = "boff:registry:subjects";
|
|
8
|
+
var DELAYQ_PREFIX = "boff:delayq";
|
|
9
|
+
var DELAYQ_LOCK_PREFIX = "boff:lock:delayq";
|
|
10
|
+
var DLQ_PREFIX = "boff:dlq";
|
|
11
|
+
var DEDUP_PREFIX = "boff:dedup";
|
|
12
|
+
var REPLY_PREFIX = "boff:replies";
|
|
13
|
+
var currentScope = "";
|
|
14
|
+
function setKeyScope(scope) {
|
|
15
|
+
currentScope = scope ?? "";
|
|
16
|
+
}
|
|
17
|
+
__name(setKeyScope, "setKeyScope");
|
|
18
|
+
function scoped(prefix) {
|
|
19
|
+
return currentScope ? `${currentScope}${prefix}` : prefix;
|
|
20
|
+
}
|
|
21
|
+
__name(scoped, "scoped");
|
|
22
|
+
function subjectToKey(subject) {
|
|
23
|
+
return subject.replace(/\./g, ":");
|
|
24
|
+
}
|
|
25
|
+
__name(subjectToKey, "subjectToKey");
|
|
26
|
+
function streamKey(subject, opts = {}) {
|
|
27
|
+
const prefix = opts.prefix ?? DEFAULT_PREFIX;
|
|
28
|
+
return `${scoped(prefix)}:${subjectToKey(subject)}`;
|
|
29
|
+
}
|
|
30
|
+
__name(streamKey, "streamKey");
|
|
31
|
+
function registryKey(boundary) {
|
|
32
|
+
return `${scoped(REGISTRY_PREFIX)}:${boundary}`;
|
|
33
|
+
}
|
|
34
|
+
__name(registryKey, "registryKey");
|
|
35
|
+
function boundaryOf(subject) {
|
|
36
|
+
const first = subject.split(".")[0];
|
|
37
|
+
return first ?? subject;
|
|
38
|
+
}
|
|
39
|
+
__name(boundaryOf, "boundaryOf");
|
|
40
|
+
function delayQueueKey(stream) {
|
|
41
|
+
return `${scoped(DELAYQ_PREFIX)}:${stream}`;
|
|
42
|
+
}
|
|
43
|
+
__name(delayQueueKey, "delayQueueKey");
|
|
44
|
+
function delayLockKey(stream) {
|
|
45
|
+
return `${scoped(DELAYQ_LOCK_PREFIX)}:${stream}`;
|
|
46
|
+
}
|
|
47
|
+
__name(delayLockKey, "delayLockKey");
|
|
48
|
+
function dlqKey(stream) {
|
|
49
|
+
return `${scoped(DLQ_PREFIX)}:${stream}`;
|
|
50
|
+
}
|
|
51
|
+
__name(dlqKey, "dlqKey");
|
|
52
|
+
function dedupKey(stream, msgId) {
|
|
53
|
+
return `${scoped(DEDUP_PREFIX)}:${stream}:${msgId}`;
|
|
54
|
+
}
|
|
55
|
+
__name(dedupKey, "dedupKey");
|
|
56
|
+
function replyKey(correlationId) {
|
|
57
|
+
return `${scoped(REPLY_PREFIX)}:${correlationId}`;
|
|
58
|
+
}
|
|
59
|
+
__name(replyKey, "replyKey");
|
|
60
|
+
function matchSubject(pattern, subject) {
|
|
61
|
+
if (pattern === subject) return true;
|
|
62
|
+
const pParts = pattern.split(".");
|
|
63
|
+
const sParts = subject.split(".");
|
|
64
|
+
const last = pParts[pParts.length - 1];
|
|
65
|
+
if (last === ">") {
|
|
66
|
+
if (sParts.length < pParts.length) return false;
|
|
67
|
+
for (let i = 0; i < pParts.length - 1; i++) {
|
|
68
|
+
if (pParts[i] !== sParts[i]) return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (pParts.length !== sParts.length) return false;
|
|
73
|
+
for (let i = 0; i < pParts.length; i++) {
|
|
74
|
+
if (pParts[i] !== "*" && pParts[i] !== sParts[i]) return false;
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
__name(matchSubject, "matchSubject");
|
|
79
|
+
function isWildcard(pattern) {
|
|
80
|
+
return pattern.includes("*") || pattern.includes(">");
|
|
81
|
+
}
|
|
82
|
+
__name(isWildcard, "isWildcard");
|
|
83
|
+
|
|
5
84
|
// src/event-queue/implementations/redis-streams/RedisStreamsConnection.ts
|
|
6
85
|
var ioredisModulePromise = null;
|
|
7
86
|
async function loadIoRedis() {
|
|
@@ -37,15 +116,23 @@ function normaliseUrl(rawUrl) {
|
|
|
37
116
|
tls = true;
|
|
38
117
|
}
|
|
39
118
|
let host = "localhost";
|
|
119
|
+
let dbIndex = 0;
|
|
40
120
|
try {
|
|
41
121
|
const parsed = new URL(url);
|
|
42
122
|
host = parsed.hostname || host;
|
|
123
|
+
const pathDb = parsed.pathname.replace(/^\//, "");
|
|
124
|
+
if (pathDb && /^\d+$/.test(pathDb)) {
|
|
125
|
+
dbIndex = parseInt(pathDb, 10);
|
|
126
|
+
parsed.pathname = "";
|
|
127
|
+
url = parsed.toString();
|
|
128
|
+
}
|
|
43
129
|
} catch {
|
|
44
130
|
}
|
|
45
131
|
return {
|
|
46
132
|
url,
|
|
47
133
|
tls,
|
|
48
|
-
host
|
|
134
|
+
host,
|
|
135
|
+
dbIndex
|
|
49
136
|
};
|
|
50
137
|
}
|
|
51
138
|
__name(normaliseUrl, "normaliseUrl");
|
|
@@ -59,12 +146,17 @@ var RedisStreamsConnection = class {
|
|
|
59
146
|
tls;
|
|
60
147
|
host;
|
|
61
148
|
normalisedUrl;
|
|
149
|
+
dbIndex;
|
|
62
150
|
constructor(config) {
|
|
63
151
|
this.config = config;
|
|
64
|
-
const { url, tls, host } = normaliseUrl(config.url);
|
|
152
|
+
const { url, tls, host, dbIndex } = normaliseUrl(config.url);
|
|
65
153
|
this.normalisedUrl = url;
|
|
66
154
|
this.tls = tls || process.env["REDIS_TLS"] === "true";
|
|
67
155
|
this.host = host;
|
|
156
|
+
this.dbIndex = dbIndex;
|
|
157
|
+
if (dbIndex > 0) {
|
|
158
|
+
setKeyScope(`db${String(dbIndex)}:`);
|
|
159
|
+
}
|
|
68
160
|
}
|
|
69
161
|
/** True once `connect()` has resolved and ioredis is in `ready` state. */
|
|
70
162
|
isConnected() {
|
|
@@ -112,7 +204,9 @@ var RedisStreamsConnection = class {
|
|
|
112
204
|
await this.client.connect();
|
|
113
205
|
logger.info("[RedisStreamsConnection] connected", {
|
|
114
206
|
url: this.normalisedUrl.replace(/:[^:@/]*@/, ":***@"),
|
|
115
|
-
tls: this.tls
|
|
207
|
+
tls: this.tls,
|
|
208
|
+
dbIndex: this.dbIndex,
|
|
209
|
+
keyScope: this.dbIndex > 0 ? `db${String(this.dbIndex)}:` : ""
|
|
116
210
|
});
|
|
117
211
|
}
|
|
118
212
|
async disconnect() {
|
|
@@ -319,6 +413,6 @@ function normalizeNatsCreds(creds) {
|
|
|
319
413
|
}
|
|
320
414
|
__name(normalizeNatsCreds, "normalizeNatsCreds");
|
|
321
415
|
|
|
322
|
-
export { NatsConnectionManager, RedisStreamsConnection };
|
|
323
|
-
//# sourceMappingURL=chunk-
|
|
324
|
-
//# sourceMappingURL=chunk-
|
|
416
|
+
export { NatsConnectionManager, RedisStreamsConnection, boundaryOf, dedupKey, delayLockKey, delayQueueKey, dlqKey, isWildcard, matchSubject, registryKey, replyKey, streamKey };
|
|
417
|
+
//# sourceMappingURL=chunk-N52W3RQA.js.map
|
|
418
|
+
//# sourceMappingURL=chunk-N52W3RQA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/event-queue/implementations/redis-streams/keyspace.ts","../src/event-queue/implementations/redis-streams/RedisStreamsConnection.ts","../src/event-queue/implementations/nats/NatsConnection.ts"],"names":["DEFAULT_PREFIX","REGISTRY_PREFIX","DELAYQ_PREFIX","DELAYQ_LOCK_PREFIX","DLQ_PREFIX","DEDUP_PREFIX","REPLY_PREFIX","currentScope","setKeyScope","scope","scoped","prefix","subjectToKey","subject","replace","streamKey","opts","registryKey","boundary","boundaryOf","first","split","delayQueueKey","stream","delayLockKey","dlqKey","dedupKey","msgId","replyKey","correlationId","matchSubject","pattern","pParts","sParts","last","length","i","isWildcard","includes","ioredisModulePromise","loadIoRedis","mod","default","Redis","err","logger","error","Error","message","String","ctor","normaliseUrl","rawUrl","url","tls","test","host","dbIndex","parsed","URL","hostname","pathDb","pathname","parseInt","toString","RedisStreamsConnection","client","connecting","normalisedUrl","config","process","env","isConnected","status","connect","doConnect","finally","lazyConnect","maxRetriesPerRequest","enableReadyCheck","connectTimeout","connectionTimeout","reconnectOnError","retryStrategy","times","Math","min","password","user","servername","on","args","warn","info","keyScope","disconnect","quit","getClient","makeBlockingClient","dup","duplicate","ping","NatsConnectionManager","nc","js","jsm","connected","connectionPromise","debug","_doConnect","connectionOptions","createNatsConnectionOptions","jetstream","jetstreamManager","name","setupEventHandlers","type","catch","drain","close","isClosed","getJetStream","getJetStreamManager","getNatsConnection","servers","pass","token","maxReconnectAttempts","reconnectTimeWait","creds","resolveNatsCreds","authenticator","credsAuthenticator","TextEncoder","encode","normalizeNatsCreds","credsFile","undefined","fs","readFile","startsWith","Buffer","from","slice","replaceAll"],"mappings":"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","file":"chunk-N52W3RQA.js","sourcesContent":["/**\n * Redis Streams key namespace helpers.\n *\n * All keys are prefixed with `boff:` because DB 0 of Azure Managed Redis is\n * shared with the be-sdk cache provider.\n */\n\nexport interface KeyspaceOptions {\n /** Top-level prefix for event streams. Defaults to `boff:events`. */\n prefix?: string;\n}\n\nconst DEFAULT_PREFIX = 'boff:events';\nconst REGISTRY_PREFIX = 'boff:registry:subjects';\nconst DELAYQ_PREFIX = 'boff:delayq';\nconst DELAYQ_LOCK_PREFIX = 'boff:lock:delayq';\nconst DLQ_PREFIX = 'boff:dlq';\nconst DEDUP_PREFIX = 'boff:dedup';\nconst REPLY_PREFIX = 'boff:replies';\n\n// ── Process-wide key scope (DB-as-prefix) ────────────────────────────────\n//\n// Azure Managed Redis Balanced/B0 only exposes DB 0. Services that used to\n// rely on a non-zero DB index in their REDIS_URL (e.g. `…/4`) for namespace\n// isolation now share DB 0 — RedisStreamsConnection strips the path, pins\n// the connection to DB 0, and calls `setKeyScope(\"db4:\")` so every key that\n// flows through this module is automatically prefixed with `db4:`. That\n// preserves the per-service isolation the DB number used to give us without\n// any of the callers having to change.\n//\n// Default scope is empty (back-compat for services on classic Redis or\n// already using DB 0). Set once at connection time; reads are O(1).\nlet currentScope = '';\n\nexport function setKeyScope(scope: string): void {\n currentScope = scope ?? '';\n}\n\nexport function getKeyScope(): string {\n return currentScope;\n}\n\nfunction scoped(prefix: string): string {\n return currentScope ? `${currentScope}${prefix}` : prefix;\n}\n\n/** Convert a NATS-style subject to a Redis key segment (`.` → `:`). */\nexport function subjectToKey(subject: string): string {\n return subject.replace(/\\./g, ':');\n}\n\n/** Build the stream key for a given subject. */\nexport function streamKey(subject: string, opts: KeyspaceOptions = {}): string {\n const prefix = opts.prefix ?? DEFAULT_PREFIX;\n return `${scoped(prefix)}:${subjectToKey(subject)}`;\n}\n\n/** Stream key from a NATS-style wildcard prefix (e.g. `wspace`). */\nexport function registryKey(boundary: string): string {\n return `${scoped(REGISTRY_PREFIX)}:${boundary}`;\n}\n\n/** Extract the leading boundary (`x` in `x.y.z`). */\nexport function boundaryOf(subject: string): string {\n const first = subject.split('.')[0];\n return first ?? subject;\n}\n\n/** Sorted-set key for delayed-NAK re-delivery, scoped per stream. */\nexport function delayQueueKey(stream: string): string {\n return `${scoped(DELAYQ_PREFIX)}:${stream}`;\n}\n\n/** Lock key the delay-queue worker uses to serialise across replicas. */\nexport function delayLockKey(stream: string): string {\n return `${scoped(DELAYQ_LOCK_PREFIX)}:${stream}`;\n}\n\n/** Per-stream dead-letter queue. */\nexport function dlqKey(stream: string): string {\n return `${scoped(DLQ_PREFIX)}:${stream}`;\n}\n\n/** Per-message dedup marker key. */\nexport function dedupKey(stream: string, msgId: string): string {\n return `${scoped(DEDUP_PREFIX)}:${stream}:${msgId}`;\n}\n\n/** Reply-stream key for request/response emulation. */\nexport function replyKey(correlationId: string): string {\n return `${scoped(REPLY_PREFIX)}:${correlationId}`;\n}\n\n/**\n * Resolve a NATS-style subject pattern to a concrete list of stream keys, using\n * a registry of known subjects.\n *\n * Patterns supported:\n * - `x.y.z` — exact subject, returns single stream\n * - `x.>` — all subjects starting with `x.`\n * - `x.*` — all subjects with exactly one more segment after `x.`\n * - `x.*.z` — single-segment wildcard at position\n */\nexport function matchSubject(pattern: string, subject: string): boolean {\n if (pattern === subject) return true;\n const pParts = pattern.split('.');\n const sParts = subject.split('.');\n const last = pParts[pParts.length - 1];\n if (last === '>') {\n if (sParts.length < pParts.length) return false;\n for (let i = 0; i < pParts.length - 1; i++) {\n if (pParts[i] !== sParts[i]) return false;\n }\n return true;\n }\n if (pParts.length !== sParts.length) return false;\n for (let i = 0; i < pParts.length; i++) {\n if (pParts[i] !== '*' && pParts[i] !== sParts[i]) return false;\n }\n return true;\n}\n\n/** True if subject pattern contains a wildcard token. */\nexport function isWildcard(pattern: string): boolean {\n return pattern.includes('*') || pattern.includes('>');\n}\n","/**\n * Manages a single ioredis client (or cluster) for the Redis Streams backend.\n *\n * Connection URL conventions:\n * - `redis://host:port` — plaintext\n * - `rediss://host:port` — TLS (Azure Managed Redis uses port 10000)\n * - `valkey://`/`valkeys://` — accepted as aliases, normalised internally\n *\n * Hostname → SNI is set automatically for TLS endpoints so Azure-managed certs\n * validate.\n */\nimport { logger } from '../../../logger/index.js';\nimport type { BaseQueueConfig } from '../../types/config.js';\nimport { setKeyScope } from './keyspace.js';\n\ntype IoRedis = {\n status: string;\n connect: () => Promise<void>;\n disconnect: () => void;\n quit: () => Promise<unknown>;\n ping: () => Promise<string>;\n on: (event: string, handler: (...args: unknown[]) => void) => void;\n duplicate: () => IoRedis;\n // Stream + key commands used by publisher/consumer/sweeper\n xadd: (...args: unknown[]) => Promise<string>;\n xack: (...args: unknown[]) => Promise<number>;\n xreadgroup: (...args: unknown[]) => Promise<unknown>;\n xgroup: (...args: unknown[]) => Promise<unknown>;\n xautoclaim: (...args: unknown[]) => Promise<unknown>;\n xpending: (...args: unknown[]) => Promise<unknown>;\n xlen: (key: string) => Promise<number>;\n xinfo: (...args: unknown[]) => Promise<unknown>;\n xrevrange: (...args: unknown[]) => Promise<unknown>;\n xrange: (...args: unknown[]) => Promise<unknown>;\n xdel: (key: string, ...ids: string[]) => Promise<number>;\n set: (...args: unknown[]) => Promise<string | null>;\n expire: (key: string, seconds: number) => Promise<number>;\n del: (...keys: string[]) => Promise<number>;\n sadd: (key: string, ...members: string[]) => Promise<number>;\n smembers: (key: string) => Promise<string[]>;\n zadd: (...args: unknown[]) => Promise<number>;\n zrangebyscore: (...args: unknown[]) => Promise<string[]>;\n zrem: (key: string, ...members: string[]) => Promise<number>;\n pipeline: () => { xadd: (...args: unknown[]) => unknown; exec: () => Promise<Array<[Error | null, unknown]>> };\n};\n\ntype IoRedisCtor = new (url: string, opts: Record<string, unknown>) => IoRedis;\n\nlet ioredisModulePromise: Promise<IoRedisCtor | null> | null = null;\n\nasync function loadIoRedis(): Promise<IoRedisCtor> {\n if (!ioredisModulePromise) {\n ioredisModulePromise = (async () => {\n try {\n const mod = (await import('ioredis')) as unknown as { default?: IoRedisCtor; Redis?: IoRedisCtor };\n return mod.default ?? mod.Redis ?? null;\n } catch (err) {\n logger.error('[RedisStreamsConnection] ioredis not installed', {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n })();\n }\n const ctor = await ioredisModulePromise;\n if (!ctor) {\n throw new Error(\n '[RedisStreamsConnection] ioredis is required for the redis-streams event-queue backend. ' +\n \"Install it with: bun add ioredis (or npm i ioredis)\"\n );\n }\n return ctor;\n}\n\nfunction normaliseUrl(rawUrl: string): { url: string; tls: boolean; host: string; dbIndex: number } {\n let url = rawUrl;\n let tls = false;\n if (/^valkeys:\\/\\//.test(url)) {\n tls = true;\n url = url.replace(/^valkeys:\\/\\//, 'rediss://');\n } else if (/^valkey:\\/\\//.test(url)) {\n url = url.replace(/^valkey:\\/\\//, 'redis://');\n } else if (/^rediss:\\/\\//.test(url)) {\n tls = true;\n }\n let host = 'localhost';\n let dbIndex = 0;\n try {\n const parsed = new URL(url);\n host = parsed.hostname || host;\n // Azure Managed Redis Balanced/B0 only exposes DB 0. If the URL pins a\n // non-zero DB in its path (e.g. `…/4`), ioredis would issue `SELECT 4`\n // on every reconnect and the server returns `ERR DB index is out of\n // range` in a tight loop that pegs the event loop. Strip the path here\n // so the connection lands on DB 0, then surface the original index to\n // the caller — we use it as a key-prefix scope so the per-service\n // isolation the DB number used to give us is preserved.\n const pathDb = parsed.pathname.replace(/^\\//, '');\n if (pathDb && /^\\d+$/.test(pathDb)) {\n dbIndex = parseInt(pathDb, 10);\n parsed.pathname = '';\n url = parsed.toString();\n }\n } catch {\n /* keep defaults */\n }\n return { url, tls, host, dbIndex };\n}\n\nexport class RedisStreamsConnection {\n private client: IoRedis | null = null;\n private connecting: Promise<void> | null = null;\n private readonly tls: boolean;\n private readonly host: string;\n private readonly normalisedUrl: string;\n private readonly dbIndex: number;\n\n constructor(private readonly config: BaseQueueConfig) {\n const { url, tls, host, dbIndex } = normaliseUrl(config.url);\n this.normalisedUrl = url;\n this.tls = tls || process.env['REDIS_TLS'] === 'true';\n this.host = host;\n this.dbIndex = dbIndex;\n // Install the DB-as-prefix scope before the first publish/consume runs.\n // Safe to call at construction: keyspace.setKeyScope is process-wide and\n // every key produced after this point will be prefixed with `db{N}:`.\n if (dbIndex > 0) {\n setKeyScope(`db${String(dbIndex)}:`);\n }\n }\n\n /** True once `connect()` has resolved and ioredis is in `ready` state. */\n isConnected(): boolean {\n return this.client !== null && this.client.status === 'ready';\n }\n\n /** Connect lazily; subsequent calls await the in-flight promise. */\n async connect(): Promise<void> {\n if (this.isConnected()) return;\n if (this.connecting) {\n await this.connecting;\n return;\n }\n this.connecting = this.doConnect().finally(() => {\n this.connecting = null;\n });\n await this.connecting;\n }\n\n private async doConnect(): Promise<void> {\n const Redis = await loadIoRedis();\n const opts: Record<string, unknown> = {\n lazyConnect: true,\n maxRetriesPerRequest: null,\n enableReadyCheck: true,\n connectTimeout: this.config.connectionTimeout ?? 15000,\n reconnectOnError: () => true,\n retryStrategy: (times: number): number => Math.min(times * 200, 2000),\n };\n if (this.config.password) opts['password'] = this.config.password;\n if (this.config.user) opts['username'] = this.config.user;\n if (this.tls) {\n opts['tls'] = { servername: this.host };\n }\n this.client = new Redis(this.normalisedUrl, opts);\n this.client.on('error', (...args: unknown[]) => {\n const err = args[0] as Error | undefined;\n logger.warn('[RedisStreamsConnection] redis error', {\n error: err?.message ?? 'unknown',\n });\n });\n this.client.on('reconnecting', () => {\n logger.info('[RedisStreamsConnection] reconnecting');\n });\n await this.client.connect();\n logger.info('[RedisStreamsConnection] connected', {\n url: this.normalisedUrl.replace(/:[^:@/]*@/, ':***@'),\n tls: this.tls,\n dbIndex: this.dbIndex,\n keyScope: this.dbIndex > 0 ? `db${String(this.dbIndex)}:` : '',\n });\n }\n\n async disconnect(): Promise<void> {\n if (!this.client) return;\n try {\n await this.client.quit();\n } catch {\n this.client.disconnect();\n }\n this.client = null;\n }\n\n /** The shared command client. Throws if not connected. */\n getClient(): IoRedis {\n if (!this.client) {\n throw new Error('[RedisStreamsConnection] not connected — call connect() first');\n }\n return this.client;\n }\n\n /** Make a dedicated client (e.g. for a blocking XREADGROUP loop). */\n async makeBlockingClient(): Promise<IoRedis> {\n await this.connect();\n const dup = this.getClient().duplicate();\n if ('connect' in dup && typeof dup.connect === 'function') {\n try {\n await dup.connect();\n } catch {\n /* ioredis auto-connects in some versions */\n }\n }\n return dup;\n }\n\n async ping(): Promise<string> {\n await this.connect();\n return this.getClient().ping();\n }\n}\n\nexport type { IoRedis };\n","/**\n * NATS JetStream Connection Manager\n * Handles connection lifecycle and provides access to NATS clients\n */\nimport { logger } from '../../../logger/index.js';\nimport {\n type ConnectionOptions,\n type JetStreamClient,\n type JetStreamManager,\n type NatsConnection,\n connect,\n credsAuthenticator,\n} from 'nats';\n\nimport type { BaseQueueConfig } from '../../types/config.js';\n\n/**\n * Internal connection manager for NATS JetStream\n * Shared between NatsEventPublisher and NatsEventConsumer\n */\nexport class NatsConnectionManager {\n private nc: NatsConnection | null = null;\n private js: JetStreamClient | null = null;\n private jsm: JetStreamManager | null = null;\n private connected: boolean = false;\n private connectionPromise: Promise<void> | null = null;\n\n constructor(private config: BaseQueueConfig) {}\n\n /**\n * Connect to NATS server\n */\n async connect(): Promise<void> {\n // Prevent multiple concurrent connections\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.connected) {\n logger.debug('[NatsConnection] Already connected');\n return;\n }\n\n this.connectionPromise = this._doConnect();\n try {\n await this.connectionPromise;\n } finally {\n this.connectionPromise = null;\n }\n }\n\n /**\n * Internal connection logic\n */\n private async _doConnect(): Promise<void> {\n try {\n const connectionOptions = await createNatsConnectionOptions(this.config);\n\n this.nc = await connect(connectionOptions);\n this.js = this.nc.jetstream();\n this.jsm = await this.nc.jetstreamManager();\n this.connected = true;\n\n logger.info('[NatsConnection] Connected to NATS', {\n url: this.config.url,\n name: this.config.name,\n });\n\n // Handle connection events\n this.setupEventHandlers();\n } catch (error) {\n logger.error('[NatsConnection] Failed to connect to NATS', {\n error: error instanceof Error ? error.message : 'Unknown error',\n url: this.config.url,\n });\n throw error;\n }\n }\n\n /**\n * Setup connection event handlers\n */\n private setupEventHandlers(): void {\n if (!this.nc) return;\n\n (async (): Promise<void> => {\n if (!this.nc) return;\n\n for await (const status of this.nc.status()) {\n if (status.type === 'disconnect') {\n this.connected = false;\n } else if (status.type === 'reconnect') {\n this.connected = true;\n }\n }\n })().catch((error) => {\n logger.error('[NatsConnection] Error handling connection events', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n });\n }\n\n /**\n * Disconnect from NATS\n */\n async disconnect(): Promise<void> {\n if (!this.connected || !this.nc) {\n return;\n }\n\n try {\n await this.nc.drain();\n await this.nc.close();\n this.connected = false;\n this.nc = null;\n this.js = null;\n this.jsm = null;\n\n logger.info('[NatsConnection] Disconnected from NATS');\n } catch (error) {\n logger.error('[NatsConnection] Error disconnecting from NATS', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.nc !== null && !this.nc.isClosed();\n }\n\n /**\n * Get JetStream client\n */\n getJetStream(): JetStreamClient {\n if (!this.js) {\n throw new Error('NATS not connected - call connect() first');\n }\n return this.js;\n }\n\n /**\n * Get JetStream Manager\n */\n getJetStreamManager(): JetStreamManager {\n if (!this.jsm) {\n throw new Error('NATS not connected - call connect() first');\n }\n return this.jsm;\n }\n\n /**\n * Get NATS connection\n */\n getNatsConnection(): NatsConnection {\n if (!this.nc) {\n throw new Error('NATS not connected - call connect() first');\n }\n return this.nc;\n }\n}\n\nexport async function createNatsConnectionOptions(config: BaseQueueConfig): Promise<ConnectionOptions> {\n const connectionOptions: ConnectionOptions = {\n servers: config.url,\n name: config.name,\n user: config.user,\n pass: config.password,\n token: config.token,\n maxReconnectAttempts: config.maxReconnectAttempts ?? -1,\n reconnectTimeWait: config.reconnectTimeWait ?? 2000,\n };\n\n const creds = await resolveNatsCreds(config);\n if (creds) {\n connectionOptions.authenticator = credsAuthenticator(new TextEncoder().encode(creds));\n delete connectionOptions.user;\n delete connectionOptions.pass;\n delete connectionOptions.token;\n }\n\n return connectionOptions;\n}\n\nexport async function resolveNatsCreds(\n config: Pick<BaseQueueConfig, 'creds' | 'credsFile'>\n): Promise<string | undefined> {\n if (config.creds) {\n return normalizeNatsCreds(config.creds);\n }\n\n if (!config.credsFile) {\n return undefined;\n }\n\n const fs = await import('node:fs/promises');\n return normalizeNatsCreds(await fs.readFile(config.credsFile, 'utf8'));\n}\n\nfunction normalizeNatsCreds(creds: string): string {\n if (creds.startsWith('base64:')) {\n return Buffer.from(creds.slice('base64:'.length), 'base64').toString('utf8');\n }\n\n if (creds.includes('\\\\n') && !creds.includes('\\n')) {\n return creds.replaceAll('\\\\n', '\\n');\n }\n\n return creds;\n}\n"]}
|
|
@@ -447,7 +447,16 @@ var ValkeyGlideProvider = class {
|
|
|
447
447
|
clusterScanCursor = null;
|
|
448
448
|
clientIsCluster = false;
|
|
449
449
|
connected = false;
|
|
450
|
+
// Single in-flight connect promise so concurrent first-time `get/set` calls
|
|
451
|
+
// share one connect attempt instead of racing into N parallel `createClient`
|
|
452
|
+
// invocations. Reset to `null` after connect resolves/rejects so the next
|
|
453
|
+
// call after an explicit disconnect() (or a connect failure) can retry.
|
|
454
|
+
connectPromise = null;
|
|
450
455
|
config;
|
|
456
|
+
// Mutable: when a URL like `…/4` lands on Azure Managed Redis we fold the
|
|
457
|
+
// DB index into the namespace at connect time to preserve per-service
|
|
458
|
+
// isolation on the forced-DB-0 connection. Not const, but only ever
|
|
459
|
+
// appended to once during connect().
|
|
451
460
|
namespace;
|
|
452
461
|
defaultTTL;
|
|
453
462
|
enableLogging;
|
|
@@ -491,20 +500,38 @@ var ValkeyGlideProvider = class {
|
|
|
491
500
|
return keys;
|
|
492
501
|
}
|
|
493
502
|
async getKeys(pattern) {
|
|
494
|
-
|
|
495
|
-
throw new Error("Not connected");
|
|
496
|
-
}
|
|
503
|
+
const client = await this.ensureConnected();
|
|
497
504
|
if (this.clientIsCluster) {
|
|
498
505
|
return this.scanClusterKeys(pattern);
|
|
499
506
|
}
|
|
500
|
-
if (!
|
|
507
|
+
if (!client.keys) {
|
|
501
508
|
throw new Error("KEYS command is not available on this Valkey client");
|
|
502
509
|
}
|
|
503
|
-
return
|
|
510
|
+
return client.keys(pattern);
|
|
504
511
|
}
|
|
505
512
|
/**
|
|
506
513
|
* Connect to Valkey server using @valkey/valkey-glide
|
|
507
514
|
*/
|
|
515
|
+
/**
|
|
516
|
+
* Lazy-connect helper used by every public operation so callers can just do
|
|
517
|
+
* `const cache = createCache('x'); await cache.set(...)` without an explicit
|
|
518
|
+
* `await cache.connect()`. Multiple concurrent ops share the same in-flight
|
|
519
|
+
* connect promise.
|
|
520
|
+
*/
|
|
521
|
+
async ensureConnected() {
|
|
522
|
+
if (!(this.connected && this.client)) {
|
|
523
|
+
if (!this.connectPromise) {
|
|
524
|
+
this.connectPromise = this.connect().finally(() => {
|
|
525
|
+
this.connectPromise = null;
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
await this.connectPromise;
|
|
529
|
+
}
|
|
530
|
+
if (!this.client) {
|
|
531
|
+
throw new Error("Valkey client connect failed");
|
|
532
|
+
}
|
|
533
|
+
return this.client;
|
|
534
|
+
}
|
|
508
535
|
async connect() {
|
|
509
536
|
if (this.connected && this.client) {
|
|
510
537
|
return;
|
|
@@ -546,6 +573,12 @@ var ValkeyGlideProvider = class {
|
|
|
546
573
|
const dbMatch = url.pathname.match(/^\/(\d+)$/);
|
|
547
574
|
if (dbMatch && dbMatch[1]) {
|
|
548
575
|
databaseFromUrl = parseInt(dbMatch[1], 10);
|
|
576
|
+
const isAzureManagedRedis = /\.redis\.azure\.net$/i.test(host);
|
|
577
|
+
if (isAzureManagedRedis && databaseFromUrl > 0) {
|
|
578
|
+
logger.warn(`[ValkeyGlideProvider] Azure Managed Redis only supports DB 0; ignoring /${String(databaseFromUrl)} in URL and folding it into namespace.`);
|
|
579
|
+
this.namespace = `${this.namespace}:db${String(databaseFromUrl)}`;
|
|
580
|
+
databaseFromUrl = 0;
|
|
581
|
+
}
|
|
549
582
|
}
|
|
550
583
|
}
|
|
551
584
|
const addresses = this.config.clusterNodes?.length ? this.config.clusterNodes : [
|
|
@@ -683,14 +716,12 @@ var ValkeyGlideProvider = class {
|
|
|
683
716
|
const totalOperations = this.stats.hits + this.stats.misses;
|
|
684
717
|
const hitRate = totalOperations > 0 ? this.stats.hits / totalOperations : 0;
|
|
685
718
|
try {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
}
|
|
689
|
-
const info = await this.client.info("memory");
|
|
719
|
+
const client = await this.ensureConnected();
|
|
720
|
+
const info = await client.info("memory");
|
|
690
721
|
const memoryRegex = /used_memory:(\d+)/;
|
|
691
722
|
const memoryMatch = memoryRegex.exec(info);
|
|
692
723
|
const memoryUsed = memoryMatch && memoryMatch[1] ? parseInt(memoryMatch[1], 10) : void 0;
|
|
693
|
-
const keyCount = await
|
|
724
|
+
const keyCount = await client.dbsize();
|
|
694
725
|
return {
|
|
695
726
|
hits: this.stats.hits,
|
|
696
727
|
misses: this.stats.misses,
|
|
@@ -730,11 +761,9 @@ var ValkeyGlideProvider = class {
|
|
|
730
761
|
*/
|
|
731
762
|
async get(key, _options) {
|
|
732
763
|
try {
|
|
733
|
-
|
|
734
|
-
throw new Error("Not connected");
|
|
735
|
-
}
|
|
764
|
+
const client = await this.ensureConnected();
|
|
736
765
|
const cacheKey = this.buildKey(key);
|
|
737
|
-
const value = await
|
|
766
|
+
const value = await client.get(cacheKey);
|
|
738
767
|
if (value === null) {
|
|
739
768
|
this.stats.misses++;
|
|
740
769
|
if (this.enableLogging) {
|
|
@@ -763,9 +792,7 @@ var ValkeyGlideProvider = class {
|
|
|
763
792
|
*/
|
|
764
793
|
async set(key, value, options) {
|
|
765
794
|
try {
|
|
766
|
-
|
|
767
|
-
throw new Error("Not connected");
|
|
768
|
-
}
|
|
795
|
+
const client = await this.ensureConnected();
|
|
769
796
|
const cacheKey = this.buildKey(key);
|
|
770
797
|
const ttlSeconds = options?.ttl || this.defaultTTL;
|
|
771
798
|
const entry = {
|
|
@@ -774,7 +801,7 @@ var ValkeyGlideProvider = class {
|
|
|
774
801
|
ttl: ttlSeconds,
|
|
775
802
|
metadata: options?.metadata
|
|
776
803
|
};
|
|
777
|
-
await
|
|
804
|
+
await client.set(cacheKey, JSON.stringify(entry), {
|
|
778
805
|
expiry: {
|
|
779
806
|
type: "EX",
|
|
780
807
|
count: ttlSeconds
|
|
@@ -799,11 +826,9 @@ var ValkeyGlideProvider = class {
|
|
|
799
826
|
*/
|
|
800
827
|
async delete(key) {
|
|
801
828
|
try {
|
|
802
|
-
|
|
803
|
-
throw new Error("Not connected");
|
|
804
|
-
}
|
|
829
|
+
const client = await this.ensureConnected();
|
|
805
830
|
const cacheKey = this.buildKey(key);
|
|
806
|
-
const result = await
|
|
831
|
+
const result = await client.del([
|
|
807
832
|
cacheKey
|
|
808
833
|
]);
|
|
809
834
|
this.stats.deletes++;
|
|
@@ -825,11 +850,9 @@ var ValkeyGlideProvider = class {
|
|
|
825
850
|
*/
|
|
826
851
|
async has(key) {
|
|
827
852
|
try {
|
|
828
|
-
|
|
829
|
-
throw new Error("Not connected");
|
|
830
|
-
}
|
|
853
|
+
const client = await this.ensureConnected();
|
|
831
854
|
const cacheKey = this.buildKey(key);
|
|
832
|
-
const exists = await
|
|
855
|
+
const exists = await client.exists([
|
|
833
856
|
cacheKey
|
|
834
857
|
]);
|
|
835
858
|
return exists === 1;
|
|
@@ -844,11 +867,9 @@ var ValkeyGlideProvider = class {
|
|
|
844
867
|
*/
|
|
845
868
|
async ttl(key) {
|
|
846
869
|
try {
|
|
847
|
-
|
|
848
|
-
throw new Error("Not connected");
|
|
849
|
-
}
|
|
870
|
+
const client = await this.ensureConnected();
|
|
850
871
|
const cacheKey = this.buildKey(key);
|
|
851
|
-
return await
|
|
872
|
+
return await client.ttl(cacheKey);
|
|
852
873
|
} catch (error) {
|
|
853
874
|
this.stats.errors++;
|
|
854
875
|
logger.error(`[ValkeyGlideProvider:${this.namespace}] Error getting TTL:`, error);
|
|
@@ -860,11 +881,9 @@ var ValkeyGlideProvider = class {
|
|
|
860
881
|
*/
|
|
861
882
|
async expire(key, ttl) {
|
|
862
883
|
try {
|
|
863
|
-
|
|
864
|
-
throw new Error("Not connected");
|
|
865
|
-
}
|
|
884
|
+
const client = await this.ensureConnected();
|
|
866
885
|
const cacheKey = this.buildKey(key);
|
|
867
|
-
return await
|
|
886
|
+
return await client.expire(cacheKey, ttl);
|
|
868
887
|
} catch (error) {
|
|
869
888
|
this.stats.errors++;
|
|
870
889
|
logger.error(`[ValkeyGlideProvider:${this.namespace}] Error setting expiration:`, error);
|
|
@@ -880,11 +899,9 @@ var ValkeyGlideProvider = class {
|
|
|
880
899
|
return result;
|
|
881
900
|
}
|
|
882
901
|
try {
|
|
883
|
-
|
|
884
|
-
throw new Error("Not connected");
|
|
885
|
-
}
|
|
902
|
+
const client = await this.ensureConnected();
|
|
886
903
|
const cacheKeys = keys.map((key) => this.buildKey(key));
|
|
887
|
-
const values = await
|
|
904
|
+
const values = await client.mget(cacheKeys);
|
|
888
905
|
for (let i = 0; i < keys.length; i++) {
|
|
889
906
|
const key = keys[i];
|
|
890
907
|
if (!key) continue;
|
|
@@ -917,9 +934,7 @@ var ValkeyGlideProvider = class {
|
|
|
917
934
|
return true;
|
|
918
935
|
}
|
|
919
936
|
try {
|
|
920
|
-
|
|
921
|
-
throw new Error("Not connected");
|
|
922
|
-
}
|
|
937
|
+
const client = await this.ensureConnected();
|
|
923
938
|
const ttlSeconds = options?.ttl || this.defaultTTL;
|
|
924
939
|
const keyValuePairs = {};
|
|
925
940
|
for (const [key, value] of entries) {
|
|
@@ -932,9 +947,9 @@ var ValkeyGlideProvider = class {
|
|
|
932
947
|
};
|
|
933
948
|
keyValuePairs[cacheKey] = JSON.stringify(entry);
|
|
934
949
|
}
|
|
935
|
-
await
|
|
950
|
+
await client.mset(keyValuePairs);
|
|
936
951
|
for (const cacheKey of Object.keys(keyValuePairs)) {
|
|
937
|
-
await
|
|
952
|
+
await client.expire(cacheKey, ttlSeconds);
|
|
938
953
|
}
|
|
939
954
|
this.stats.sets += entries.size;
|
|
940
955
|
if (this.enableLogging) {
|
|
@@ -958,11 +973,9 @@ var ValkeyGlideProvider = class {
|
|
|
958
973
|
return 0;
|
|
959
974
|
}
|
|
960
975
|
try {
|
|
961
|
-
|
|
962
|
-
throw new Error("Not connected");
|
|
963
|
-
}
|
|
976
|
+
const client = await this.ensureConnected();
|
|
964
977
|
const cacheKeys = keys.map((key) => this.buildKey(key));
|
|
965
|
-
const result = await
|
|
978
|
+
const result = await client.del(cacheKeys);
|
|
966
979
|
this.stats.deletes += result;
|
|
967
980
|
if (this.enableLogging) {
|
|
968
981
|
logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch delete`, {
|
|
@@ -982,15 +995,13 @@ var ValkeyGlideProvider = class {
|
|
|
982
995
|
*/
|
|
983
996
|
async clearPattern(pattern) {
|
|
984
997
|
try {
|
|
985
|
-
|
|
986
|
-
throw new Error("Not connected");
|
|
987
|
-
}
|
|
998
|
+
const client = await this.ensureConnected();
|
|
988
999
|
const searchPattern = this.buildKey(pattern);
|
|
989
1000
|
const keys = await this.getKeys(searchPattern);
|
|
990
1001
|
if (keys.length === 0) {
|
|
991
1002
|
return 0;
|
|
992
1003
|
}
|
|
993
|
-
const result = await
|
|
1004
|
+
const result = await client.del(keys);
|
|
994
1005
|
if (this.enableLogging) {
|
|
995
1006
|
logger.debug(`[ValkeyGlideProvider:${this.namespace}] Pattern cleared`, {
|
|
996
1007
|
pattern,
|
|
@@ -1009,9 +1020,7 @@ var ValkeyGlideProvider = class {
|
|
|
1009
1020
|
*/
|
|
1010
1021
|
async keys(options) {
|
|
1011
1022
|
try {
|
|
1012
|
-
|
|
1013
|
-
throw new Error("Not connected");
|
|
1014
|
-
}
|
|
1023
|
+
await this.ensureConnected();
|
|
1015
1024
|
const searchPattern = this.buildKey(options.pattern);
|
|
1016
1025
|
const keys = await this.getKeys(searchPattern);
|
|
1017
1026
|
const prefix = `${this.namespace}:`;
|
|
@@ -1037,13 +1046,11 @@ var ValkeyGlideProvider = class {
|
|
|
1037
1046
|
*/
|
|
1038
1047
|
async clear() {
|
|
1039
1048
|
try {
|
|
1040
|
-
|
|
1041
|
-
throw new Error("Not connected");
|
|
1042
|
-
}
|
|
1049
|
+
const client = await this.ensureConnected();
|
|
1043
1050
|
const pattern = this.buildKey("*");
|
|
1044
1051
|
const keys = await this.getKeys(pattern);
|
|
1045
1052
|
if (keys.length > 0) {
|
|
1046
|
-
await
|
|
1053
|
+
await client.del(keys);
|
|
1047
1054
|
if (this.enableLogging) {
|
|
1048
1055
|
logger.info(`[ValkeyGlideProvider:${this.namespace}] Cleared ${keys.length} keys`);
|
|
1049
1056
|
}
|
|
@@ -1060,11 +1067,9 @@ var ValkeyGlideProvider = class {
|
|
|
1060
1067
|
*/
|
|
1061
1068
|
async increment(key, amount = 1) {
|
|
1062
1069
|
try {
|
|
1063
|
-
|
|
1064
|
-
throw new Error("Not connected");
|
|
1065
|
-
}
|
|
1070
|
+
const client = await this.ensureConnected();
|
|
1066
1071
|
const cacheKey = this.buildKey(key);
|
|
1067
|
-
return await
|
|
1072
|
+
return await client.incrBy(cacheKey, amount);
|
|
1068
1073
|
} catch (error) {
|
|
1069
1074
|
this.stats.errors++;
|
|
1070
1075
|
logger.error(`[ValkeyGlideProvider:${this.namespace}] Error incrementing:`, error);
|
|
@@ -1076,11 +1081,9 @@ var ValkeyGlideProvider = class {
|
|
|
1076
1081
|
*/
|
|
1077
1082
|
async decrement(key, amount = 1) {
|
|
1078
1083
|
try {
|
|
1079
|
-
|
|
1080
|
-
throw new Error("Not connected");
|
|
1081
|
-
}
|
|
1084
|
+
const client = await this.ensureConnected();
|
|
1082
1085
|
const cacheKey = this.buildKey(key);
|
|
1083
|
-
return await
|
|
1086
|
+
return await client.decrBy(cacheKey, amount);
|
|
1084
1087
|
} catch (error) {
|
|
1085
1088
|
this.stats.errors++;
|
|
1086
1089
|
logger.error(`[ValkeyGlideProvider:${this.namespace}] Error decrementing:`, error);
|
|
@@ -1409,5 +1412,5 @@ async function closeAllCaches() {
|
|
|
1409
1412
|
__name(closeAllCaches, "closeAllCaches");
|
|
1410
1413
|
|
|
1411
1414
|
export { CacheFactory, CacheProviderType, MemoryCacheProvider, ValkeyGlideProvider, cache_exports, closeAllCaches, createCache, getCache, getValkeyClient };
|
|
1412
|
-
//# sourceMappingURL=chunk-
|
|
1413
|
-
//# sourceMappingURL=chunk-
|
|
1415
|
+
//# sourceMappingURL=chunk-Q6N74R6S.js.map
|
|
1416
|
+
//# sourceMappingURL=chunk-Q6N74R6S.js.map
|