Skip to content

Commit 30caa5f

Browse files
author
Nathan Booker
committed
feat: replace Vercel KV adapter with Vercel Runtime Cache API
1 parent 7c449c2 commit 30caa5f

8 files changed

Lines changed: 167 additions & 216 deletions

File tree

.changeset/chatty-forks-sniff.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@bigcommerce/catalyst-core": minor
3+
---
4+
5+
Implement Vercel Runtime Cache API as replacement for Vercel KV adapter

core/lib/kv/adapters/bc.ts

Lines changed: 0 additions & 101 deletions
This file was deleted.

core/lib/kv/adapters/upstash.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,14 @@ import { Redis } from '@upstash/redis';
22

33
import { KvAdapter, SetCommandOptions } from '../types';
44

5-
import { MemoryKvAdapter } from './memory';
6-
7-
const memoryKv = new MemoryKvAdapter();
8-
95
export class UpstashKvAdapter implements KvAdapter {
106
private upstashKv = Redis.fromEnv();
11-
private memoryKv = memoryKv;
127

138
async mget<Data>(...keys: string[]) {
14-
const memoryValues = await this.memoryKv.mget<Data>(...keys);
15-
16-
return memoryValues.length ? memoryValues : this.upstashKv.mget<Data[]>(keys);
9+
return this.upstashKv.mget<Data[]>(keys);
1710
}
1811

1912
async set<Data>(key: string, value: Data, opts?: SetCommandOptions) {
20-
await this.memoryKv.set(key, value, opts);
21-
2213
const response = await this.upstashKv.set(key, value, opts);
2314

2415
if (response === 'OK') {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { getCache } from '@vercel/functions';
2+
3+
import { KvAdapter, SetCommandOptions } from '../types';
4+
5+
export class RuntimeCacheAdapter implements KvAdapter {
6+
private cache = getCache();
7+
8+
async mget<Data>(...keys: string[]): Promise<Array<Data | null>> {
9+
this.logger(
10+
`MGET - Keys: ${keys.toString()} - Source: RUNTIME_CACHE - Fetching ${keys.length} keys`,
11+
);
12+
13+
try {
14+
const values = await Promise.all(
15+
keys.map(async (key) => {
16+
try {
17+
// Use the Runtime Cache API
18+
const cachedValue = await this.cache.get(key);
19+
20+
if (cachedValue !== null) {
21+
this.logger(`RUNTIME_CACHE GET - Key: ${key} - Found: true`);
22+
23+
return cachedValue;
24+
}
25+
26+
this.logger(`RUNTIME_CACHE GET - Key: ${key} - Found: false`);
27+
28+
return null;
29+
} catch (error) {
30+
this.logger(
31+
`RUNTIME_CACHE GET ERROR - Key: ${key} - Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
32+
);
33+
34+
return null;
35+
}
36+
}),
37+
);
38+
39+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
40+
return values as Array<Data | null>;
41+
} catch (error) {
42+
this.logger(
43+
`RUNTIME_CACHE ACCESS ERROR - Returning null values: ${error instanceof Error ? error.message : 'Unknown error'}`,
44+
);
45+
46+
// Return null for all keys if Runtime Cache is unavailable
47+
return keys.map(() => null);
48+
}
49+
}
50+
51+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
52+
async set<Data>(key: string, value: Data, _opts?: SetCommandOptions): Promise<Data | null> {
53+
this.logger(`SET - Key: ${key} - Setting in runtime cache`);
54+
55+
try {
56+
await this.cache.set(key, value);
57+
this.logger(`RUNTIME_CACHE SET - Key: ${key} - Success`);
58+
} catch (error) {
59+
this.logger(
60+
`RUNTIME_CACHE SET ERROR - Key: ${key} - Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
61+
);
62+
}
63+
64+
return value;
65+
}
66+
67+
private logger(message: string) {
68+
// Check if logging is enabled using the same logic as the main KV class
69+
const loggingEnabled =
70+
(process.env.NODE_ENV !== 'production' && process.env.KV_LOGGER !== 'false') ||
71+
process.env.KV_LOGGER === 'true';
72+
73+
if (loggingEnabled) {
74+
// eslint-disable-next-line no-console
75+
console.log(`[BigCommerce] Runtime Cache ${message}`);
76+
}
77+
}
78+
}

core/lib/kv/adapters/vercel.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

core/lib/kv/index.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,11 @@ class KV<Adapter extends KvAdapter> implements KvAdapter {
8282
}
8383

8484
async function createKVAdapter() {
85-
if (process.env.BC_KV_REST_API_URL && process.env.BC_KV_REST_API_TOKEN) {
86-
const { BcKvAdapter } = await import('./adapters/bc');
85+
// Prioritize Runtime Cache for Vercel environments
86+
if (process.env.VERCEL === '1') {
87+
const { RuntimeCacheAdapter } = await import('./adapters/vercel-runtime-cache');
8788

88-
return new BcKvAdapter();
89-
}
90-
91-
if (process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN) {
92-
const { VercelKvAdapter } = await import('./adapters/vercel');
93-
94-
return new VercelKvAdapter();
89+
return new RuntimeCacheAdapter();
9590
}
9691

9792
if (process.env.UPSTASH_REDIS_REST_URL && process.env.UPSTASH_REDIS_REST_TOKEN) {

core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"@t3-oss/env-core": "^0.13.6",
3535
"@upstash/redis": "^1.35.0",
3636
"@vercel/analytics": "^1.5.0",
37-
"@vercel/kv": "^3.0.0",
37+
"@vercel/functions": "^2.2.3",
3838
"@vercel/speed-insights": "^1.2.0",
3939
"clsx": "^2.1.1",
4040
"content-security-policy-builder": "^2.3.0",
@@ -50,7 +50,7 @@
5050
"lodash.debounce": "^4.0.8",
5151
"lru-cache": "^11.1.0",
5252
"lucide-react": "^0.474.0",
53-
"next": "15.4.2-canary.10",
53+
"next": "15.5.1-canary.4",
5454
"next-auth": "5.0.0-beta.25",
5555
"next-intl": "^4.1.0",
5656
"nuqs": "^2.4.3",

0 commit comments

Comments
 (0)