|
1 | | -import { KvAdapter, SetCommandOptions } from '../types'; |
2 | | - |
3 | | -import { MemoryKvAdapter } from './memory'; |
| 1 | +import { getCache } from '@vercel/functions'; |
4 | 2 |
|
5 | | -const memoryKv = new MemoryKvAdapter(); |
| 3 | +import { KvAdapter, SetCommandOptions } from '../types'; |
6 | 4 |
|
7 | 5 | export class RuntimeCacheAdapter implements KvAdapter { |
8 | | - private memoryKv = memoryKv; |
| 6 | + private cache = getCache(); |
9 | 7 |
|
10 | 8 | async mget<Data>(...keys: string[]): Promise<Array<Data | null>> { |
11 | | - // First check memory cache for immediate reads |
12 | | - const memoryValues = await this.memoryKv.mget<Data>(...keys); |
13 | | - |
14 | | - // Check if all values are found in memory cache |
15 | | - const allFoundInMemory = memoryValues.every((value) => value !== null); |
16 | | - |
17 | | - if (allFoundInMemory) { |
18 | | - this.logger( |
19 | | - `MGET - Keys: ${keys.toString()} - Source: MEMORY - Values found: ${memoryValues.length}`, |
20 | | - ); |
21 | | - |
22 | | - return memoryValues; |
23 | | - } |
24 | | - |
25 | | - // Otherwise, fetch missing values from runtime cache |
26 | 9 | this.logger( |
27 | | - `MGET - Keys: ${keys.toString()} - Source: RUNTIME_CACHE - Memory hits: ${memoryValues.filter((v) => v !== null).length}/${keys.length}`, |
| 10 | + `MGET - Keys: ${keys.toString()} - Source: RUNTIME_CACHE - Fetching ${keys.length} keys`, |
28 | 11 | ); |
29 | 12 |
|
30 | 13 | try { |
31 | | - // Use dynamic import to load the getCache function only when needed |
32 | | - const { getCache } = await import('@vercel/functions'); |
33 | | - const cache = getCache(); |
34 | | - |
35 | 14 | const values = await Promise.all( |
36 | | - keys.map(async (key, index) => { |
37 | | - // Use memory value if available, otherwise fetch from runtime cache |
38 | | - if (memoryValues[index] !== null && memoryValues[index] !== undefined) { |
39 | | - return memoryValues[index]; |
40 | | - } |
41 | | - |
| 15 | + keys.map(async (key) => { |
42 | 16 | try { |
43 | 17 | // Use the Runtime Cache API |
44 | | - const cachedValue = await cache.get(key); |
| 18 | + const cachedValue = await this.cache.get(key); |
45 | 19 |
|
46 | 20 | if (cachedValue !== null) { |
47 | 21 | this.logger(`RUNTIME_CACHE GET - Key: ${key} - Found: true`); |
48 | | - |
49 | 22 | return cachedValue; |
50 | 23 | } |
51 | 24 |
|
52 | 25 | this.logger(`RUNTIME_CACHE GET - Key: ${key} - Found: false`); |
53 | | - |
54 | 26 | return null; |
55 | 27 | } catch (error) { |
56 | 28 | this.logger( |
57 | 29 | `RUNTIME_CACHE GET ERROR - Key: ${key} - Error: ${error instanceof Error ? error.message : 'Unknown error'}`, |
58 | 30 | ); |
59 | | - |
60 | 31 | return null; |
61 | 32 | } |
62 | 33 | }), |
63 | 34 | ); |
64 | 35 |
|
65 | | - // Store the runtime cache values in memory cache for future reads |
66 | | - await Promise.all( |
67 | | - values.map(async (value, index) => { |
68 | | - const key = keys[index]; |
69 | | - |
70 | | - if (!key || value === null || memoryValues[index] !== null) { |
71 | | - return; |
72 | | - } |
73 | | - |
74 | | - await this.memoryKv.set(key, value); |
75 | | - this.logger(`MEMORY SET - Key: ${key} - Cached from runtime`); |
76 | | - }), |
77 | | - ); |
78 | | - |
79 | 36 | // eslint-disable-next-line @typescript-eslint/consistent-type-assertions |
80 | 37 | return values as Array<Data | null>; |
81 | 38 | } catch (error) { |
82 | 39 | this.logger( |
83 | | - `RUNTIME_CACHE ACCESS ERROR - Falling back to memory only: ${error instanceof Error ? error.message : 'Unknown error'}`, |
| 40 | + `RUNTIME_CACHE ACCESS ERROR - Returning null values: ${error instanceof Error ? error.message : 'Unknown error'}`, |
84 | 41 | ); |
85 | 42 |
|
86 | | - return memoryValues; |
| 43 | + // Return null for all keys if Runtime Cache is unavailable |
| 44 | + return keys.map(() => null); |
87 | 45 | } |
88 | 46 | } |
89 | 47 |
|
90 | | - async set<Data>(key: string, value: Data, opts?: SetCommandOptions): Promise<Data | null> { |
91 | | - this.logger(`SET - Key: ${key} - Setting in both memory and runtime cache`); |
92 | | - |
93 | | - // Set in memory cache immediately for fast subsequent reads |
94 | | - await this.memoryKv.set(key, value, opts); |
| 48 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 49 | + async set<Data>(key: string, value: Data, _opts?: SetCommandOptions): Promise<Data | null> { |
| 50 | + this.logger(`SET - Key: ${key} - Setting in runtime cache`); |
95 | 51 |
|
96 | | - // Set in runtime cache for persistence across requests |
97 | 52 | try { |
98 | | - // Use dynamic import to load the getCache function only when needed |
99 | | - const { getCache } = await import('@vercel/functions'); |
100 | | - const cache = getCache(); |
101 | | - |
102 | | - await cache.set(key, value); |
| 53 | + await this.cache.set(key, value); |
103 | 54 | this.logger(`RUNTIME_CACHE SET - Key: ${key} - Success`); |
104 | 55 | } catch (error) { |
105 | 56 | this.logger( |
106 | | - `RUNTIME_CACHE SET ERROR - Key: ${key} - Error: ${error instanceof Error ? error.message : 'Unknown error'} - Value still cached in memory`, |
| 57 | + `RUNTIME_CACHE SET ERROR - Key: ${key} - Error: ${error instanceof Error ? error.message : 'Unknown error'}`, |
107 | 58 | ); |
108 | 59 | } |
109 | 60 |
|
|
0 commit comments