@maestro-js/cache 1.0.0-alpha.18 → 1.0.0-alpha.2
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/index.d.ts +3 -4
- package/dist/index.js +27 -47
- package/package.json +4 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Log } from '@maestro-js/log';
|
|
2
2
|
import Redis$1, { Redis } from 'ioredis';
|
|
3
3
|
|
|
4
|
+
type DurationString = `${number} ${'day' | 'days' | 'hour' | 'hours' | 'minute' | 'minutes' | 'second' | 'seconds'}`;
|
|
5
|
+
|
|
4
6
|
/** Contract that every cache backend (Redis, MockRedis, etc.) must implement */
|
|
5
7
|
interface CacheDriver {
|
|
6
8
|
/** Checks whether `key` exists in the store */
|
|
@@ -60,9 +62,6 @@ declare function redisCacheDriver({ url, port, operationTimeout, connectTimeout,
|
|
|
60
62
|
connection: Redis$1;
|
|
61
63
|
};
|
|
62
64
|
|
|
63
|
-
type DurationString = `${number} ${'day' | 'days' | 'hour' | 'hours' | 'minute' | 'minutes' | 'second' | 'seconds'}`;
|
|
64
|
-
|
|
65
|
-
type CacheDurationString = DurationString;
|
|
66
65
|
/**
|
|
67
66
|
* Creates a new Cache service instance with the provided driver configuration.
|
|
68
67
|
*/
|
|
@@ -164,7 +163,7 @@ declare namespace Cache {
|
|
|
164
163
|
/** Pluggable backend implementation — see `Cache.drivers` for built-in options */
|
|
165
164
|
type Driver = CacheDriver;
|
|
166
165
|
/** Duration string like `'5 minutes'` or `'1 hour'` */
|
|
167
|
-
type DurationString =
|
|
166
|
+
type DurationString = DurationString;
|
|
168
167
|
/** TTL options for `remember` — a number (seconds), `null` (forever), a duration string, or an object with `ttl` and `swr` */
|
|
169
168
|
type RememberOptions = number | null | DurationString | {
|
|
170
169
|
ttl: number | DurationString | null;
|
package/dist/index.js
CHANGED
|
@@ -3,37 +3,27 @@ import assert from "assert";
|
|
|
3
3
|
import { ServiceRegistry } from "@maestro-js/service-registry";
|
|
4
4
|
|
|
5
5
|
// src/mock-redis-cache-driver.ts
|
|
6
|
+
import EventEmitter from "events";
|
|
6
7
|
import { randomUUID } from "crypto";
|
|
8
|
+
import { Log } from "@maestro-js/log";
|
|
7
9
|
import MockRedis from "ioredis-mock";
|
|
8
10
|
import "ioredis";
|
|
9
11
|
function mockRedisCacheDriver({
|
|
10
12
|
logger: loggerInput,
|
|
11
13
|
keyPrefix = ""
|
|
12
14
|
}) {
|
|
13
|
-
const logger = loggerInput;
|
|
15
|
+
const logger = loggerInput ?? Log.create();
|
|
14
16
|
const redis = new MockRedis();
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
queue.push(callback);
|
|
19
|
-
lockWaiters.set(lockId, queue);
|
|
20
|
-
}
|
|
21
|
-
function removeWaiter(lockId, callback) {
|
|
22
|
-
const queue = lockWaiters.get(lockId);
|
|
23
|
-
if (queue) {
|
|
24
|
-
const index = queue.indexOf(callback);
|
|
25
|
-
if (index >= 0) queue.splice(index, 1);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function notifyNextWaiter(lockId) {
|
|
29
|
-
const queue = lockWaiters.get(lockId);
|
|
30
|
-
if (queue && queue.length > 0) {
|
|
31
|
-
const next = queue.shift();
|
|
32
|
-
next();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
17
|
+
const lockEmitter = new EventEmitter();
|
|
18
|
+
const channelPrefix = [keyPrefix, "maestro.events."].join("");
|
|
19
|
+
const cacheLockChannelName = `${channelPrefix}cache-locks`;
|
|
35
20
|
redis.on("error", (error) => {
|
|
36
|
-
logger
|
|
21
|
+
logger.error(error);
|
|
22
|
+
});
|
|
23
|
+
redis.on("message", (channel, message) => {
|
|
24
|
+
if (channel === cacheLockChannelName) {
|
|
25
|
+
lockEmitter.emit(message);
|
|
26
|
+
}
|
|
37
27
|
});
|
|
38
28
|
return {
|
|
39
29
|
async has(key) {
|
|
@@ -115,7 +105,7 @@ function mockRedisCacheDriver({
|
|
|
115
105
|
let waitingForAcquire = false;
|
|
116
106
|
const cleanup = () => {
|
|
117
107
|
settled = true;
|
|
118
|
-
|
|
108
|
+
lockEmitter.off(id, onRelease);
|
|
119
109
|
clearInterval(fallbackPoll);
|
|
120
110
|
};
|
|
121
111
|
const timeout = setTimeout(() => {
|
|
@@ -127,7 +117,7 @@ function mockRedisCacheDriver({
|
|
|
127
117
|
reject(new Error(`Could not acquire lock: ${name}`));
|
|
128
118
|
}, seconds * 1e3);
|
|
129
119
|
const onRelease = async () => {
|
|
130
|
-
if (settled
|
|
120
|
+
if (settled) return;
|
|
131
121
|
acquiring = true;
|
|
132
122
|
const acquired = await tryLock();
|
|
133
123
|
acquiring = false;
|
|
@@ -142,7 +132,7 @@ function mockRedisCacheDriver({
|
|
|
142
132
|
reject(new Error(`Could not acquire lock: ${name}`));
|
|
143
133
|
}
|
|
144
134
|
};
|
|
145
|
-
|
|
135
|
+
lockEmitter.on(id, onRelease);
|
|
146
136
|
const fallbackPoll = setInterval(onRelease, 250);
|
|
147
137
|
onRelease();
|
|
148
138
|
});
|
|
@@ -159,12 +149,14 @@ function mockRedisCacheDriver({
|
|
|
159
149
|
callId
|
|
160
150
|
);
|
|
161
151
|
if (released === 1) {
|
|
162
|
-
|
|
152
|
+
lockEmitter.emit(id);
|
|
153
|
+
await redis.publish(cacheLockChannelName, id);
|
|
163
154
|
}
|
|
164
155
|
}
|
|
165
156
|
async function forceRelease() {
|
|
166
157
|
await redis.del(id);
|
|
167
|
-
|
|
158
|
+
lockEmitter.emit(id);
|
|
159
|
+
await redis.publish(cacheLockChannelName, id);
|
|
168
160
|
}
|
|
169
161
|
return { get, release, forceRelease, isAvailable, block };
|
|
170
162
|
}
|
|
@@ -172,10 +164,11 @@ function mockRedisCacheDriver({
|
|
|
172
164
|
}
|
|
173
165
|
|
|
174
166
|
// src/redis-cache-driver.ts
|
|
175
|
-
import
|
|
167
|
+
import EventEmitter2 from "events";
|
|
176
168
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
177
169
|
import Redis2 from "ioredis";
|
|
178
170
|
import RedisTimeout from "ioredis-timeout";
|
|
171
|
+
import { Log as Log2 } from "@maestro-js/log";
|
|
179
172
|
function redisCacheDriver({
|
|
180
173
|
url,
|
|
181
174
|
port,
|
|
@@ -184,39 +177,26 @@ function redisCacheDriver({
|
|
|
184
177
|
keyPrefix = "",
|
|
185
178
|
logger: loggerInput
|
|
186
179
|
}) {
|
|
187
|
-
const logger = loggerInput;
|
|
180
|
+
const logger = loggerInput ?? Log2.create();
|
|
188
181
|
const redis = new Redis2(port, url, {
|
|
189
182
|
connectTimeout,
|
|
190
183
|
keyPrefix
|
|
191
184
|
});
|
|
192
|
-
const
|
|
193
|
-
connectTimeout,
|
|
194
|
-
keyPrefix
|
|
195
|
-
});
|
|
196
|
-
const lockEmitter = new EventEmitter();
|
|
185
|
+
const lockEmitter = new EventEmitter2();
|
|
197
186
|
const channelPrefix = [keyPrefix, "maestro.events."].join("");
|
|
198
187
|
const cacheLockChannelName = `${channelPrefix}cache-locks`;
|
|
199
188
|
redis.on("connect", () => {
|
|
200
|
-
logger
|
|
189
|
+
logger.info("connected!");
|
|
201
190
|
RedisTimeout.timeout("set", operationTimeout, redis);
|
|
202
191
|
RedisTimeout.timeout("get", operationTimeout, redis);
|
|
203
192
|
RedisTimeout.timeout("exists", operationTimeout, redis);
|
|
204
193
|
RedisTimeout.timeout("del", operationTimeout, redis);
|
|
205
194
|
RedisTimeout.timeout("publish", operationTimeout, redis);
|
|
206
|
-
RedisTimeout.timeout("eval", operationTimeout, redis);
|
|
207
195
|
});
|
|
208
196
|
redis.on("error", (error) => {
|
|
209
|
-
logger
|
|
210
|
-
});
|
|
211
|
-
subscriber.on("connect", () => {
|
|
212
|
-
subscriber.subscribe(cacheLockChannelName).catch((err) => {
|
|
213
|
-
logger?.error(`Failed to subscribe to ${cacheLockChannelName}: %s`, err.message);
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
subscriber.on("error", (error) => {
|
|
217
|
-
logger?.error(error);
|
|
197
|
+
logger.error(error);
|
|
218
198
|
});
|
|
219
|
-
|
|
199
|
+
redis.on("message", (channel, message) => {
|
|
220
200
|
if (channel === cacheLockChannelName) {
|
|
221
201
|
lockEmitter.emit(message);
|
|
222
202
|
}
|
|
@@ -313,7 +293,7 @@ function redisCacheDriver({
|
|
|
313
293
|
reject(new Error(`Could not acquire lock: ${name}`));
|
|
314
294
|
}, seconds * 1e3);
|
|
315
295
|
const onRelease = async () => {
|
|
316
|
-
if (settled
|
|
296
|
+
if (settled) return;
|
|
317
297
|
acquiring = true;
|
|
318
298
|
const acquired = await tryLock();
|
|
319
299
|
acquiring = false;
|
package/package.json
CHANGED
|
@@ -13,16 +13,13 @@
|
|
|
13
13
|
"ioredis-timeout": "^1.5.0",
|
|
14
14
|
"ioredis-mock": "^8.2.0",
|
|
15
15
|
"@types/ioredis-mock": "^8.2.6",
|
|
16
|
-
"@maestro-js/
|
|
17
|
-
|
|
18
|
-
"peerDependencies": {
|
|
19
|
-
"@maestro-js/log": "1.0.0-alpha.18"
|
|
16
|
+
"@maestro-js/log": "1.0.0-alpha.2",
|
|
17
|
+
"@maestro-js/service-registry": "1.0.0-alpha.2"
|
|
20
18
|
},
|
|
21
19
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^22.19.11"
|
|
23
|
-
"@maestro-js/log": "1.0.0-alpha.18"
|
|
20
|
+
"@types/node": "^22.19.11"
|
|
24
21
|
},
|
|
25
|
-
"version": "1.0.0-alpha.
|
|
22
|
+
"version": "1.0.0-alpha.2",
|
|
26
23
|
"publishConfig": {
|
|
27
24
|
"access": "restricted"
|
|
28
25
|
},
|