@zintrust/cache-redis 2.1.4 → 2.8.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 +13 -0
- package/dist/RedisProxyAdapter.js +3 -3
- package/dist/build-manifest.json +51 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +75 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -32,6 +32,19 @@ Then set your cache driver config (see docs for the full set of env vars):
|
|
|
32
32
|
CACHE_DRIVER=redis
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
## Cloudflare Workers
|
|
36
|
+
|
|
37
|
+
When the app runs in Cloudflare Workers or another runtime without Redis TCP access, use Redis RPC:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm i @zintrust/redis-rpc
|
|
41
|
+
|
|
42
|
+
USE_REDIS_PROXY=true
|
|
43
|
+
REDIS_RPC_URL=https://queues.example.com
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Run the backend with `zin redis-rpc` or `zin s redis-rpc`. The Redis cache driver will send `get`, `set`, `del`, `exists`, and `flushdb` through the core Redis RPC transport. The older Redis HTTP proxy remains available for simple command forwarding through `REDIS_PROXY_URL`.
|
|
47
|
+
|
|
35
48
|
## Docs
|
|
36
49
|
|
|
37
50
|
- https://zintrust.com/cache
|
|
@@ -2,15 +2,15 @@ import { Env } from '@zintrust/core/config';
|
|
|
2
2
|
import { ErrorFactory } from '@zintrust/core/errors';
|
|
3
3
|
import { createRedisConnection } from '@zintrust/core/redis';
|
|
4
4
|
const createProxyClient = () => {
|
|
5
|
-
if (Env.
|
|
6
|
-
throw ErrorFactory.createConfigError('Redis proxy
|
|
5
|
+
if (Env.USE_REDIS_PROXY !== true) {
|
|
6
|
+
throw ErrorFactory.createConfigError('Redis proxy transport requires USE_REDIS_PROXY=true. Add REDIS_RPC_URL for Redis RPC or REDIS_PROXY_URL/REDIS_PROXY_HOST for the legacy Redis HTTP proxy.');
|
|
7
7
|
}
|
|
8
8
|
return createRedisConnection({
|
|
9
9
|
host: Env.get('REDIS_HOST', 'localhost'),
|
|
10
10
|
port: Env.getInt('REDIS_PORT', 6379),
|
|
11
11
|
password: Env.get('REDIS_PASSWORD'),
|
|
12
12
|
db: Env.getInt('REDIS_DB', 0),
|
|
13
|
-
}, 3, { subsystem: 'cache'
|
|
13
|
+
}, 3, { subsystem: 'cache' });
|
|
14
14
|
};
|
|
15
15
|
export const RedisProxyAdapter = Object.freeze({
|
|
16
16
|
create() {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zintrust/cache-redis",
|
|
3
|
+
"version": "2.8.0",
|
|
4
|
+
"buildDate": "2026-06-25T14:58:58.204Z",
|
|
5
|
+
"buildEnvironment": {
|
|
6
|
+
"node": "v20.20.2",
|
|
7
|
+
"platform": "linux",
|
|
8
|
+
"arch": "x64"
|
|
9
|
+
},
|
|
10
|
+
"git": {
|
|
11
|
+
"commit": "4f1c19ee",
|
|
12
|
+
"branch": "master"
|
|
13
|
+
},
|
|
14
|
+
"package": {
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=20.0.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": [
|
|
19
|
+
"redis"
|
|
20
|
+
],
|
|
21
|
+
"peerDependencies": [
|
|
22
|
+
"@zintrust/core"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"files": {
|
|
26
|
+
"RedisProxyAdapter.d.ts": {
|
|
27
|
+
"size": 163,
|
|
28
|
+
"sha256": "91df2fbb1916b073c3bafa1dc253ab5ee8998cc924c3cd52308c09798c1d829f"
|
|
29
|
+
},
|
|
30
|
+
"RedisProxyAdapter.js": {
|
|
31
|
+
"size": 1851,
|
|
32
|
+
"sha256": "6cbca2f311ac0573e63a1cd60e7bfe8b3eaaedcf23696ec170b234b2fd56f5a9"
|
|
33
|
+
},
|
|
34
|
+
"index.d.ts": {
|
|
35
|
+
"size": 1000,
|
|
36
|
+
"sha256": "889b6f7ba479e62988d08472d823c41bb026c261992ba6ad65df2fc4048e6a72"
|
|
37
|
+
},
|
|
38
|
+
"index.js": {
|
|
39
|
+
"size": 10002,
|
|
40
|
+
"sha256": "7cfe9ed90d018da8c9bebe5eaed377023284e8b230d32e2b53587dedc22b5d1c"
|
|
41
|
+
},
|
|
42
|
+
"register.d.ts": {
|
|
43
|
+
"size": 184,
|
|
44
|
+
"sha256": "005e0163b4f5833a0096cfcba7d5851b6f21c0fea7d8faf01a913dc2808730ad"
|
|
45
|
+
},
|
|
46
|
+
"register.js": {
|
|
47
|
+
"size": 472,
|
|
48
|
+
"sha256": "0fa19f823df12b6b99973a893c1b975e767d183b0275e9b78a60e454ca63b6ca"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export interface CacheDriver {
|
|
|
4
4
|
delete(key: string): Promise<void>;
|
|
5
5
|
clear(): Promise<void>;
|
|
6
6
|
has(key: string): Promise<boolean>;
|
|
7
|
+
increment?(key: string, amount?: number): Promise<number>;
|
|
8
|
+
decrement?(key: string, amount?: number): Promise<number>;
|
|
9
|
+
getRedisClient?(): unknown;
|
|
7
10
|
}
|
|
8
11
|
export type RedisCacheConfig = {
|
|
9
12
|
driver: 'redis';
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,42 @@ const createCacheFailureState = () => {
|
|
|
30
30
|
},
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
|
-
const
|
|
33
|
+
const incrementValue = async (ensureClient, operations, failureState, defaultTtl, key, amount) => {
|
|
34
|
+
if (failureState.isDisabled())
|
|
35
|
+
return 0;
|
|
36
|
+
try {
|
|
37
|
+
const client = await ensureClient();
|
|
38
|
+
if (operations.increment)
|
|
39
|
+
return operations.increment(client, key, amount);
|
|
40
|
+
const current = Number(safeJsonParse((await operations.get(client, key)) ?? '0') ?? 0);
|
|
41
|
+
const next = current + amount;
|
|
42
|
+
await operations.set(client, key, JSON.stringify(next), defaultTtl);
|
|
43
|
+
return next;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
failureState.disableAfterFailure('SET', error);
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const decrementValue = async (ensureClient, operations, failureState, defaultTtl, key, amount) => {
|
|
51
|
+
if (failureState.isDisabled())
|
|
52
|
+
return 0;
|
|
53
|
+
try {
|
|
54
|
+
const client = await ensureClient();
|
|
55
|
+
if (operations.decrement)
|
|
56
|
+
return operations.decrement(client, key, amount);
|
|
57
|
+
const current = Number(safeJsonParse((await operations.get(client, key)) ?? '0') ?? 0);
|
|
58
|
+
const next = current - amount;
|
|
59
|
+
await operations.set(client, key, JSON.stringify(next), defaultTtl);
|
|
60
|
+
return next;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
failureState.disableAfterFailure('SET', error);
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
// Driver objects intentionally keep the cache method table in one sealed return value.
|
|
68
|
+
const createCacheOperations = (ensureClient, operations, defaultTtl, getRedisClient) => {
|
|
34
69
|
const failureState = createCacheFailureState();
|
|
35
70
|
return {
|
|
36
71
|
async get(key) {
|
|
@@ -96,6 +131,13 @@ const createCacheOperations = (ensureClient, operations, defaultTtl) => {
|
|
|
96
131
|
return false;
|
|
97
132
|
}
|
|
98
133
|
},
|
|
134
|
+
async increment(key, amount = 1) {
|
|
135
|
+
return incrementValue(ensureClient, operations, failureState, defaultTtl, key, amount);
|
|
136
|
+
},
|
|
137
|
+
async decrement(key, amount = 1) {
|
|
138
|
+
return decrementValue(ensureClient, operations, failureState, defaultTtl, key, amount);
|
|
139
|
+
},
|
|
140
|
+
...(getRedisClient ? { getRedisClient } : {}),
|
|
99
141
|
};
|
|
100
142
|
};
|
|
101
143
|
const createWorkersCacheDriver = (config) => {
|
|
@@ -107,7 +149,7 @@ const createWorkersCacheDriver = (config) => {
|
|
|
107
149
|
port: config.port,
|
|
108
150
|
password: config.password,
|
|
109
151
|
db: config.database ?? 0,
|
|
110
|
-
}, 3, { subsystem: 'cache'
|
|
152
|
+
}, 3, { subsystem: 'cache' });
|
|
111
153
|
if (!connected && typeof client.connect === 'function') {
|
|
112
154
|
await client.connect();
|
|
113
155
|
connected = true;
|
|
@@ -118,7 +160,7 @@ const createWorkersCacheDriver = (config) => {
|
|
|
118
160
|
get: (redisClient, key) => redisClient.get(key),
|
|
119
161
|
set: (redisClient, key, json, ttl) => {
|
|
120
162
|
if (Number.isFinite(ttl) && ttl > 0) {
|
|
121
|
-
return redisClient.set(key, json,
|
|
163
|
+
return redisClient.set(key, json, 'EX', ttl);
|
|
122
164
|
}
|
|
123
165
|
else {
|
|
124
166
|
return redisClient.set(key, json);
|
|
@@ -137,7 +179,31 @@ const createWorkersCacheDriver = (config) => {
|
|
|
137
179
|
return Promise.resolve();
|
|
138
180
|
},
|
|
139
181
|
exists: (redisClient, key) => redisClient.exists(key),
|
|
140
|
-
|
|
182
|
+
increment: async (redisClient, key, amount) => {
|
|
183
|
+
if (typeof redisClient.incrBy === 'function') {
|
|
184
|
+
return redisClient.incrBy(key, amount);
|
|
185
|
+
}
|
|
186
|
+
if (typeof redisClient.incrby === 'function') {
|
|
187
|
+
return redisClient.incrby(key, amount);
|
|
188
|
+
}
|
|
189
|
+
const current = Number((await redisClient.get(key)) ?? 0);
|
|
190
|
+
const next = current + amount;
|
|
191
|
+
await redisClient.set(key, String(next));
|
|
192
|
+
return next;
|
|
193
|
+
},
|
|
194
|
+
decrement: async (redisClient, key, amount) => {
|
|
195
|
+
if (typeof redisClient.decrBy === 'function') {
|
|
196
|
+
return redisClient.decrBy(key, amount);
|
|
197
|
+
}
|
|
198
|
+
if (typeof redisClient.decrby === 'function') {
|
|
199
|
+
return redisClient.decrby(key, amount);
|
|
200
|
+
}
|
|
201
|
+
const current = Number((await redisClient.get(key)) ?? 0);
|
|
202
|
+
const next = current - amount;
|
|
203
|
+
await redisClient.set(key, String(next));
|
|
204
|
+
return next;
|
|
205
|
+
},
|
|
206
|
+
}, config.ttl ?? 300, () => client);
|
|
141
207
|
};
|
|
142
208
|
const createNodeCacheDriver = (config) => {
|
|
143
209
|
let client;
|
|
@@ -172,10 +238,12 @@ const createNodeCacheDriver = (config) => {
|
|
|
172
238
|
},
|
|
173
239
|
clear: (redisClient) => redisClient.flushDb(),
|
|
174
240
|
exists: (redisClient, key) => redisClient.exists(key),
|
|
175
|
-
|
|
241
|
+
increment: (redisClient, key, amount) => redisClient.incrBy(key, amount),
|
|
242
|
+
decrement: (redisClient, key, amount) => redisClient.decrBy(key, amount),
|
|
243
|
+
}, config.ttl ?? 300, () => client);
|
|
176
244
|
};
|
|
177
245
|
const shouldUseProxy = () => {
|
|
178
|
-
return Env.
|
|
246
|
+
return Env.USE_REDIS_PROXY === true;
|
|
179
247
|
};
|
|
180
248
|
export const RedisCacheDriver = Object.freeze({
|
|
181
249
|
create(config) {
|
|
@@ -184,7 +252,7 @@ export const RedisCacheDriver = Object.freeze({
|
|
|
184
252
|
return createWorkersCacheDriver(config);
|
|
185
253
|
}
|
|
186
254
|
if (isWorkers && Cloudflare.isCloudflareSocketsEnabled() === false) {
|
|
187
|
-
throw ErrorFactory.createConfigError('Redis cache driver requires
|
|
255
|
+
throw ErrorFactory.createConfigError('Redis cache driver in Cloudflare Workers requires USE_REDIS_PROXY=true with REDIS_RPC_URL/REDIS_PROXY_URL, or ENABLE_CLOUDFLARE_SOCKETS=true.');
|
|
188
256
|
}
|
|
189
257
|
return isWorkers ? createWorkersCacheDriver(config) : createNodeCacheDriver(config);
|
|
190
258
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/cache-redis",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Redis cache driver for ZinTrust.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -42,4 +42,4 @@
|
|
|
42
42
|
"build": "tsc -p tsconfig.json",
|
|
43
43
|
"prepublishOnly": "npm run build"
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
}
|