@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 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 = CacheDurationString;
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 lockWaiters = /* @__PURE__ */ new Map();
16
- function addWaiter(lockId, callback) {
17
- const queue = lockWaiters.get(lockId) ?? [];
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?.error(error);
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
- removeWaiter(id, onRelease);
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 || acquiring) return;
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
- addWaiter(id, onRelease);
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
- notifyNextWaiter(id);
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
- notifyNextWaiter(id);
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 EventEmitter from "events";
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 subscriber = new Redis2(port, url, {
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?.info("connected!");
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?.error(error);
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
- subscriber.on("message", (channel, message) => {
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 || acquiring) return;
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/service-registry": "1.0.0-alpha.18"
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.18",
22
+ "version": "1.0.0-alpha.2",
26
23
  "publishConfig": {
27
24
  "access": "restricted"
28
25
  },