@reactionary/core 0.9.5 → 0.9.7

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.
@@ -1,16 +1,41 @@
1
- import { Redis } from "@upstash/redis";
1
+ import { createClient } from "redis";
2
2
  import { getReactionaryCacheMeter } from "../metrics/metrics.js";
3
3
  class RedisCache {
4
4
  redis;
5
+ connectPromise;
5
6
  meter = getReactionaryCacheMeter();
6
- constructor() {
7
- this.redis = Redis.fromEnv();
7
+ constructor(redisUrl = process.env["REDIS_URL"]) {
8
+ if (!redisUrl) {
9
+ throw new Error("REDIS_URL is required");
10
+ }
11
+ this.redis = createClient({
12
+ url: redisUrl
13
+ });
14
+ this.redis.on("error", (err) => {
15
+ console.error("Redis error", err);
16
+ });
17
+ }
18
+ async client() {
19
+ if (!this.connectPromise) {
20
+ this.connectPromise = this.redis.connect();
21
+ }
22
+ return this.connectPromise;
8
23
  }
9
24
  async get(key, schema) {
10
25
  if (!key) {
11
26
  return null;
12
27
  }
13
- const unvalidated = await this.redis.get(key);
28
+ const redis = await this.client();
29
+ const serialized = await redis.get(key);
30
+ if (serialized === null) {
31
+ return null;
32
+ }
33
+ let unvalidated;
34
+ try {
35
+ unvalidated = JSON.parse(serialized);
36
+ } catch {
37
+ return null;
38
+ }
14
39
  const parsed = schema.safeParse(unvalidated);
15
40
  if (parsed.success) {
16
41
  this.meter.hits.add(1, {
@@ -24,34 +49,45 @@ class RedisCache {
24
49
  if (!key) {
25
50
  return;
26
51
  }
52
+ const redis = await this.client();
27
53
  const serialized = JSON.stringify(value);
28
- const multi = this.redis.multi();
29
- multi.set(key, serialized, { ex: options.ttlSeconds });
54
+ const multi = redis.multi();
55
+ multi.set(key, serialized, {
56
+ EX: options.ttlSeconds
57
+ });
30
58
  for (const depId of options.dependencyIds) {
31
- multi.sadd(`dep:${depId}`, key);
59
+ multi.sAdd(`dep:${depId}`, key);
32
60
  }
33
- this.meter.items.record(await this.redis.dbsize(), {
61
+ await multi.exec();
62
+ this.meter.items.record(await redis.dbSize(), {
34
63
  "labels.cache_type": "redis"
35
64
  });
36
- await multi.exec();
37
65
  }
38
66
  async invalidate(dependencyIds) {
67
+ const redis = await this.client();
39
68
  for (const id of dependencyIds) {
40
69
  const depKey = `dep:${id}`;
41
- const keys = await this.redis.smembers(depKey);
70
+ const keys = await redis.sMembers(depKey);
42
71
  if (keys.length > 0) {
43
- await this.redis.del(...keys);
72
+ await redis.del(keys);
44
73
  }
45
- await this.redis.del(depKey);
74
+ await redis.del(depKey);
46
75
  }
47
- this.meter.items.record(await this.redis.dbsize(), {
76
+ this.meter.items.record(await redis.dbSize(), {
48
77
  "labels.cache_type": "redis"
49
78
  });
50
79
  }
51
80
  async clear() {
52
- this.meter.items.record(await this.redis.dbsize(), {
81
+ const redis = await this.client();
82
+ this.meter.items.record(await redis.dbSize(), {
53
83
  "labels.cache_type": "redis"
54
84
  });
85
+ await redis.flushDb();
86
+ }
87
+ async close() {
88
+ if (this.redis.isOpen) {
89
+ await this.redis.quit();
90
+ }
55
91
  }
56
92
  }
57
93
  export {
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@reactionary/core",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./src/index.d.ts",
7
7
  "dependencies": {
8
8
  "zod": "4.1.9",
9
- "@upstash/redis": "^1.34.9",
10
9
  "@opentelemetry/api": "^1.9.0",
11
10
  "node-object-hash": "^3.1.1",
12
11
  "vitest": "^4.0.9",
13
- "@nx/vite": "22.4.5"
12
+ "@nx/vite": "22.4.5",
13
+ "redis": "^5.12.1"
14
14
  },
15
15
  "sideEffects": false
16
16
  }
@@ -1,12 +1,15 @@
1
- import { Redis } from '@upstash/redis';
1
+ import { createClient } from 'redis';
2
2
  import type { Cache, CacheEntryOptions } from './cache.interface.js';
3
3
  import type * as z from 'zod';
4
4
  export declare class RedisCache implements Cache {
5
- protected redis: Redis;
5
+ protected redis: ReturnType<typeof createClient>;
6
+ protected connectPromise?: Promise<ReturnType<typeof createClient>>;
6
7
  protected meter: import("../metrics/metrics.js").ReactionaryCacheMetrics;
7
- constructor();
8
+ constructor(redisUrl?: string | undefined);
9
+ protected client(): Promise<ReturnType<typeof createClient>>;
8
10
  get<T>(key: string, schema: z.ZodType<T>): Promise<T | null>;
9
11
  put(key: string, value: unknown, options: CacheEntryOptions): Promise<void>;
10
12
  invalidate(dependencyIds: Array<string>): Promise<void>;
11
13
  clear(): Promise<void>;
14
+ close(): Promise<void>;
12
15
  }