@akinon/next 1.96.0-snapshot-ZERO-35861-20250908151109 → 1.96.0-snapshot-ZERO-3620-20250915165755
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/CHANGELOG.md +1395 -45
- package/__tests__/next-config.test.ts +1 -10
- package/__tests__/redirect.test.ts +319 -0
- package/api/cache.ts +5 -39
- package/api/image-proxy.ts +75 -0
- package/api/similar-product-list.ts +84 -0
- package/api/similar-products.ts +120 -0
- package/components/accordion.tsx +20 -5
- package/components/file-input.tsx +65 -3
- package/components/input.tsx +2 -0
- package/components/link.tsx +16 -12
- package/components/modal.tsx +32 -16
- package/components/plugin-module.tsx +30 -3
- package/data/client/checkout.ts +5 -4
- package/data/server/basket.ts +72 -0
- package/data/server/category.ts +50 -32
- package/data/server/flatpage.ts +17 -16
- package/data/server/form.ts +1 -4
- package/data/server/landingpage.ts +16 -12
- package/data/server/list.ts +24 -15
- package/data/server/menu.ts +2 -5
- package/data/server/product.ts +67 -41
- package/data/server/special-page.ts +16 -12
- package/data/server/widget.ts +1 -4
- package/data/urls.ts +5 -1
- package/hocs/server/with-segment-defaults.tsx +5 -2
- package/hooks/use-localization.ts +2 -3
- package/jest.config.js +7 -1
- package/lib/cache-handler.mjs +87 -365
- package/lib/cache.ts +25 -252
- package/middlewares/complete-gpay.ts +2 -1
- package/middlewares/complete-masterpass.ts +2 -1
- package/middlewares/default.ts +50 -13
- package/middlewares/locale.ts +9 -1
- package/middlewares/pretty-url.ts +1 -2
- package/middlewares/redirection-payment.ts +2 -1
- package/middlewares/saved-card-redirection.ts +2 -1
- package/middlewares/three-d-redirection.ts +2 -1
- package/middlewares/url-redirection.ts +8 -14
- package/package.json +3 -4
- package/plugins.d.ts +8 -0
- package/plugins.js +3 -1
- package/redux/middlewares/checkout.ts +5 -1
- package/types/commerce/order.ts +1 -0
- package/types/index.ts +34 -2
- package/utils/app-fetch.ts +7 -2
- package/utils/redirect-ignore.ts +35 -0
- package/utils/redirect.ts +31 -6
- package/with-pz-config.js +1 -5
package/lib/cache-handler.mjs
CHANGED
|
@@ -3,261 +3,7 @@ import createLruHandler from '@neshca/cache-handler/local-lru';
|
|
|
3
3
|
import createRedisHandler from '@neshca/cache-handler/redis-strings';
|
|
4
4
|
import { createClient } from 'redis';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
(async () => {
|
|
9
|
-
try {
|
|
10
|
-
const { compress, decompress } = await import('@mongodb-js/zstd');
|
|
11
|
-
zstd = { compress, decompress, type: 'native' };
|
|
12
|
-
} catch (_) {
|
|
13
|
-
zstd = false;
|
|
14
|
-
}
|
|
15
|
-
})();
|
|
16
|
-
|
|
17
|
-
const getZstd = () => {
|
|
18
|
-
return zstd;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const compressValue = async (value) => {
|
|
22
|
-
try {
|
|
23
|
-
if (value && typeof value === 'object' && value.value !== undefined) {
|
|
24
|
-
const nestedValue = value.value;
|
|
25
|
-
const serializedNestedValue =
|
|
26
|
-
typeof nestedValue === 'string'
|
|
27
|
-
? nestedValue
|
|
28
|
-
: JSON.stringify(nestedValue);
|
|
29
|
-
const originalSize = Buffer.byteLength(serializedNestedValue, 'utf8');
|
|
30
|
-
|
|
31
|
-
if (originalSize < 1024) {
|
|
32
|
-
const result = {
|
|
33
|
-
...value,
|
|
34
|
-
tags: Array.isArray(value.tags) ? value.tags : []
|
|
35
|
-
};
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const zstdLib = getZstd();
|
|
40
|
-
let compressed;
|
|
41
|
-
|
|
42
|
-
if (zstdLib && zstdLib !== false) {
|
|
43
|
-
const inputBuffer = Buffer.from(serializedNestedValue, 'utf8');
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
typeof zstdLib.compress === 'function' &&
|
|
47
|
-
zstdLib.compress.constructor.name === 'AsyncFunction'
|
|
48
|
-
) {
|
|
49
|
-
compressed = await zstdLib.compress(inputBuffer, 3);
|
|
50
|
-
} else {
|
|
51
|
-
compressed = zstdLib.compress(inputBuffer, 3);
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
return {
|
|
55
|
-
...value,
|
|
56
|
-
tags: Array.isArray(value.tags) ? value.tags : []
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const compressedBase64 = Buffer.from(compressed).toString('base64');
|
|
61
|
-
|
|
62
|
-
const result = {
|
|
63
|
-
...value,
|
|
64
|
-
tags: Array.isArray(value.tags) ? value.tags : [],
|
|
65
|
-
lifespan: {
|
|
66
|
-
...value.lifespan,
|
|
67
|
-
expireAge: value.lifespan?.revalidate || value.lifespan?.expireAge,
|
|
68
|
-
expireAt:
|
|
69
|
-
value.lifespan?.lastModifiedAt && value.lifespan?.revalidate
|
|
70
|
-
? value.lifespan.lastModifiedAt + value.lifespan.revalidate
|
|
71
|
-
: value.lifespan?.expireAt
|
|
72
|
-
},
|
|
73
|
-
value: {
|
|
74
|
-
__compressed: true,
|
|
75
|
-
__method: 'zstd',
|
|
76
|
-
__originalSize: originalSize,
|
|
77
|
-
__compressedSize: compressed.length,
|
|
78
|
-
__data: compressedBase64
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const serializedValue =
|
|
86
|
-
typeof value === 'string' ? value : JSON.stringify(value);
|
|
87
|
-
const originalSize = Buffer.byteLength(serializedValue, 'utf8');
|
|
88
|
-
|
|
89
|
-
if (originalSize < 1024) {
|
|
90
|
-
if (
|
|
91
|
-
value &&
|
|
92
|
-
typeof value === 'object' &&
|
|
93
|
-
value.lastModified === undefined &&
|
|
94
|
-
value.lifespan === undefined &&
|
|
95
|
-
value.value === undefined
|
|
96
|
-
) {
|
|
97
|
-
return {
|
|
98
|
-
...value,
|
|
99
|
-
tags: value.tags || [],
|
|
100
|
-
lastModified: Date.now(),
|
|
101
|
-
lifespan: {
|
|
102
|
-
expireAt: Math.floor(Date.now() / 1000) + 3600
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
if (
|
|
107
|
-
value &&
|
|
108
|
-
typeof value === 'object' &&
|
|
109
|
-
value.lifespan &&
|
|
110
|
-
value.lifespan.revalidate
|
|
111
|
-
) {
|
|
112
|
-
return {
|
|
113
|
-
...value,
|
|
114
|
-
lifespan: {
|
|
115
|
-
...value.lifespan,
|
|
116
|
-
expireAge: value.lifespan.revalidate,
|
|
117
|
-
expireAt:
|
|
118
|
-
value.lifespan.lastModifiedAt && value.lifespan.revalidate
|
|
119
|
-
? value.lifespan.lastModifiedAt + value.lifespan.revalidate
|
|
120
|
-
: value.lifespan.expireAt
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
return value;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const zstdLib = getZstd();
|
|
128
|
-
let compressed;
|
|
129
|
-
|
|
130
|
-
if (zstdLib && zstdLib !== false) {
|
|
131
|
-
const inputBuffer = Buffer.from(serializedValue, 'utf8');
|
|
132
|
-
|
|
133
|
-
if (
|
|
134
|
-
typeof zstdLib.compress === 'function' &&
|
|
135
|
-
zstdLib.compress.constructor.name === 'AsyncFunction'
|
|
136
|
-
) {
|
|
137
|
-
compressed = await zstdLib.compress(inputBuffer, 3);
|
|
138
|
-
} else {
|
|
139
|
-
compressed = zstdLib.compress(inputBuffer, 3);
|
|
140
|
-
}
|
|
141
|
-
} else {
|
|
142
|
-
if (
|
|
143
|
-
value &&
|
|
144
|
-
typeof value === 'object' &&
|
|
145
|
-
value.lastModified === undefined &&
|
|
146
|
-
value.lifespan === undefined &&
|
|
147
|
-
value.value === undefined
|
|
148
|
-
) {
|
|
149
|
-
return {
|
|
150
|
-
...value,
|
|
151
|
-
tags: value.tags || [],
|
|
152
|
-
lastModified: Date.now(),
|
|
153
|
-
lifespan: {
|
|
154
|
-
expireAt: Math.floor(Date.now() / 1000) + 3600
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
return value;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const compressedBase64 = Buffer.from(compressed).toString('base64');
|
|
162
|
-
|
|
163
|
-
const compressedResult = {
|
|
164
|
-
__compressed: true,
|
|
165
|
-
__method: 'zstd',
|
|
166
|
-
__originalSize: originalSize,
|
|
167
|
-
__compressedSize: compressed.length,
|
|
168
|
-
__data: compressedBase64,
|
|
169
|
-
tags: [],
|
|
170
|
-
lastModified: Date.now(),
|
|
171
|
-
lifespan: { expireAt: Math.floor(Date.now() / 1000) + 3600 }
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
return compressedResult;
|
|
175
|
-
} catch (_) {
|
|
176
|
-
return value;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
const decompressValue = async (compressedData) => {
|
|
181
|
-
try {
|
|
182
|
-
if (
|
|
183
|
-
compressedData &&
|
|
184
|
-
typeof compressedData === 'object' &&
|
|
185
|
-
compressedData.value &&
|
|
186
|
-
typeof compressedData.value === 'object' &&
|
|
187
|
-
compressedData.value.__compressed
|
|
188
|
-
) {
|
|
189
|
-
const compressedNestedValue = compressedData.value;
|
|
190
|
-
const compressedBuffer = Buffer.from(
|
|
191
|
-
compressedNestedValue.__data,
|
|
192
|
-
'base64'
|
|
193
|
-
);
|
|
194
|
-
let decompressed;
|
|
195
|
-
|
|
196
|
-
if (compressedNestedValue.__method === 'zstd') {
|
|
197
|
-
const zstdLib = getZstd();
|
|
198
|
-
if (zstdLib && zstdLib !== false) {
|
|
199
|
-
if (
|
|
200
|
-
typeof zstdLib.decompress === 'function' &&
|
|
201
|
-
zstdLib.decompress.constructor.name === 'AsyncFunction'
|
|
202
|
-
) {
|
|
203
|
-
const decompressedBuffer = await zstdLib.decompress(
|
|
204
|
-
compressedBuffer
|
|
205
|
-
);
|
|
206
|
-
decompressed = decompressedBuffer.toString('utf8');
|
|
207
|
-
} else {
|
|
208
|
-
decompressed = zstdLib
|
|
209
|
-
.decompress(compressedBuffer)
|
|
210
|
-
.toString('utf8');
|
|
211
|
-
}
|
|
212
|
-
} else {
|
|
213
|
-
throw new Error('zstd not available for decompression');
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return {
|
|
218
|
-
...compressedData,
|
|
219
|
-
value: JSON.parse(decompressed)
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (
|
|
224
|
-
compressedData &&
|
|
225
|
-
typeof compressedData === 'object' &&
|
|
226
|
-
compressedData.__compressed
|
|
227
|
-
) {
|
|
228
|
-
const compressedBuffer = Buffer.from(compressedData.__data, 'base64');
|
|
229
|
-
let decompressed;
|
|
230
|
-
|
|
231
|
-
if (compressedData.__method === 'zstd') {
|
|
232
|
-
const zstdLib = getZstd();
|
|
233
|
-
if (zstdLib && zstdLib !== false) {
|
|
234
|
-
if (
|
|
235
|
-
typeof zstdLib.decompress === 'function' &&
|
|
236
|
-
zstdLib.decompress.constructor.name === 'AsyncFunction'
|
|
237
|
-
) {
|
|
238
|
-
const decompressedBuffer = await zstdLib.decompress(
|
|
239
|
-
compressedBuffer
|
|
240
|
-
);
|
|
241
|
-
decompressed = decompressedBuffer.toString('utf8');
|
|
242
|
-
} else {
|
|
243
|
-
decompressed = zstdLib
|
|
244
|
-
.decompress(compressedBuffer)
|
|
245
|
-
.toString('utf8');
|
|
246
|
-
}
|
|
247
|
-
} else {
|
|
248
|
-
throw new Error('zstd not available for decompression');
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return JSON.parse(decompressed);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return compressedData;
|
|
256
|
-
} catch (error) {
|
|
257
|
-
return compressedData;
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
6
|
+
// Cache configuration
|
|
261
7
|
const CACHE_CONFIG = {
|
|
262
8
|
lru: {
|
|
263
9
|
maxItemCount: 2000
|
|
@@ -276,6 +22,7 @@ const CACHE_CONFIG = {
|
|
|
276
22
|
version: process.env.ACC_APP_VERSION || ''
|
|
277
23
|
};
|
|
278
24
|
|
|
25
|
+
// Use global to persist across module reloads in development
|
|
279
26
|
const globalForRedis = global;
|
|
280
27
|
if (!globalForRedis.redisClient) {
|
|
281
28
|
globalForRedis.redisClient = null;
|
|
@@ -284,22 +31,42 @@ if (!globalForRedis.redisClient) {
|
|
|
284
31
|
globalForRedis.connectionAttempts = 0;
|
|
285
32
|
}
|
|
286
33
|
|
|
34
|
+
// Logging configuration
|
|
35
|
+
const debugValue = process.env.NEXT_PRIVATE_DEBUG_CACHE;
|
|
36
|
+
const debug = debugValue === 'true' || debugValue === '1';
|
|
37
|
+
|
|
38
|
+
let console_log;
|
|
39
|
+
if (debug) {
|
|
40
|
+
// eslint-disable-next-line no-console
|
|
41
|
+
console_log = (...args) => console.log('[Cache Handler]', ...args);
|
|
42
|
+
} else {
|
|
43
|
+
console_log = () => {};
|
|
44
|
+
}
|
|
45
|
+
|
|
287
46
|
async function getRedisClient() {
|
|
47
|
+
// If client exists and is ready, return it
|
|
288
48
|
if (globalForRedis.redisClient?.isReady) {
|
|
49
|
+
console_log('Reusing existing Redis connection');
|
|
289
50
|
return globalForRedis.redisClient;
|
|
290
51
|
}
|
|
291
52
|
|
|
53
|
+
// If we're already connecting, wait a bit and retry
|
|
292
54
|
if (globalForRedis.isConnecting) {
|
|
293
55
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
294
56
|
return getRedisClient();
|
|
295
57
|
}
|
|
296
58
|
|
|
59
|
+
// Start new connection
|
|
297
60
|
globalForRedis.isConnecting = true;
|
|
298
61
|
globalForRedis.connectionAttempts++;
|
|
299
62
|
|
|
300
63
|
try {
|
|
301
64
|
const redisUrl = `redis://${CACHE_CONFIG.host}:${CACHE_CONFIG.port}/${CACHE_CONFIG.bucket}`;
|
|
302
65
|
|
|
66
|
+
if (globalForRedis.connectionAttempts === 1) {
|
|
67
|
+
console_log('Creating Redis connection:', redisUrl);
|
|
68
|
+
}
|
|
69
|
+
|
|
303
70
|
const redisClient = createClient({
|
|
304
71
|
url: redisUrl,
|
|
305
72
|
socket: {
|
|
@@ -320,6 +87,7 @@ async function getRedisClient() {
|
|
|
320
87
|
});
|
|
321
88
|
|
|
322
89
|
redisClient.on('error', (error) => {
|
|
90
|
+
// Only log the first connection error to avoid spam
|
|
323
91
|
if (!globalForRedis.hasLoggedConnectionError) {
|
|
324
92
|
if (error.code === 'ECONNREFUSED') {
|
|
325
93
|
console.warn(
|
|
@@ -333,10 +101,12 @@ async function getRedisClient() {
|
|
|
333
101
|
});
|
|
334
102
|
|
|
335
103
|
redisClient.on('connect', () => {
|
|
104
|
+
console_log('Redis connected');
|
|
336
105
|
globalForRedis.hasLoggedConnectionError = false;
|
|
337
106
|
});
|
|
338
107
|
|
|
339
108
|
redisClient.on('ready', () => {
|
|
109
|
+
console_log('Redis ready');
|
|
340
110
|
globalForRedis.hasLoggedConnectionError = false;
|
|
341
111
|
});
|
|
342
112
|
|
|
@@ -345,6 +115,16 @@ async function getRedisClient() {
|
|
|
345
115
|
return redisClient;
|
|
346
116
|
} catch (error) {
|
|
347
117
|
if (!globalForRedis.hasLoggedConnectionError) {
|
|
118
|
+
if (error.code === 'ECONNREFUSED') {
|
|
119
|
+
console.warn(
|
|
120
|
+
'[Cache Handler] Could not connect to Redis - using local cache only'
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
console.error(
|
|
124
|
+
'[Cache Handler] Failed to connect to Redis:',
|
|
125
|
+
error.message
|
|
126
|
+
);
|
|
127
|
+
}
|
|
348
128
|
globalForRedis.hasLoggedConnectionError = true;
|
|
349
129
|
}
|
|
350
130
|
globalForRedis.redisClient = null;
|
|
@@ -355,10 +135,13 @@ async function getRedisClient() {
|
|
|
355
135
|
}
|
|
356
136
|
|
|
357
137
|
CacheHandler.onCreation(async () => {
|
|
138
|
+
console_log('Initializing cache handlers...');
|
|
139
|
+
|
|
358
140
|
let client;
|
|
359
141
|
try {
|
|
360
142
|
client = await getRedisClient();
|
|
361
143
|
} catch (error) {
|
|
144
|
+
// Error already logged in getRedisClient, just return local handler
|
|
362
145
|
return {
|
|
363
146
|
handlers: [createLruHandler(CACHE_CONFIG.lru)]
|
|
364
147
|
};
|
|
@@ -367,161 +150,98 @@ CacheHandler.onCreation(async () => {
|
|
|
367
150
|
const redisHandler = createRedisHandler({
|
|
368
151
|
client,
|
|
369
152
|
timeoutMs: CACHE_CONFIG.redis.timeoutMs,
|
|
370
|
-
keyExpirationStrategy: '
|
|
153
|
+
keyExpirationStrategy: 'EXAT'
|
|
371
154
|
});
|
|
372
155
|
|
|
373
156
|
const localHandler = createLruHandler(CACHE_CONFIG.lru);
|
|
374
157
|
|
|
375
|
-
|
|
376
|
-
const versionPrefix = `${
|
|
158
|
+
// Pre-compute version prefix if exists
|
|
159
|
+
const versionPrefix = CACHE_CONFIG.version ? `${CACHE_CONFIG.version}:` : '';
|
|
377
160
|
|
|
378
|
-
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
});
|
|
161
|
+
// Create optimized functions for each scenario
|
|
162
|
+
const versionKeyString = versionPrefix
|
|
163
|
+
? (key) => `${versionPrefix}${key}`
|
|
164
|
+
: (key) => key;
|
|
383
165
|
|
|
166
|
+
const versionKeyObject = versionPrefix
|
|
167
|
+
? (key) => ({ ...key, key: `${versionPrefix}${key.key}` })
|
|
168
|
+
: (key) => key;
|
|
169
|
+
|
|
170
|
+
// Main version key function that routes to optimized paths
|
|
384
171
|
const versionKey = (key) => {
|
|
385
172
|
return typeof key === 'string'
|
|
386
173
|
? versionKeyString(key)
|
|
387
174
|
: versionKeyObject(key);
|
|
388
175
|
};
|
|
389
176
|
|
|
177
|
+
// Create a custom handler that checks local first, then Redis
|
|
390
178
|
const customHandler = {
|
|
391
179
|
name: 'custom-local-then-redis',
|
|
392
180
|
get: async (key, context) => {
|
|
393
181
|
const vKey = versionKey(key);
|
|
182
|
+
console_log(
|
|
183
|
+
'GET called for key:',
|
|
184
|
+
typeof vKey === 'string' ? vKey : vKey?.key
|
|
185
|
+
);
|
|
394
186
|
|
|
187
|
+
// Check local cache first
|
|
188
|
+
console_log('Checking local cache...');
|
|
395
189
|
const localResult = await localHandler.get(vKey, context);
|
|
396
190
|
|
|
397
191
|
if (localResult) {
|
|
398
|
-
|
|
399
|
-
localResult &&
|
|
400
|
-
typeof localResult === 'object' &&
|
|
401
|
-
(localResult.__compressed ||
|
|
402
|
-
(localResult.value && localResult.value.__compressed) ||
|
|
403
|
-
localResult.compressed !== undefined)
|
|
404
|
-
) {
|
|
405
|
-
try {
|
|
406
|
-
const decompressed = await decompressValue(localResult);
|
|
407
|
-
return typeof decompressed === 'string'
|
|
408
|
-
? JSON.parse(decompressed)
|
|
409
|
-
: decompressed;
|
|
410
|
-
} catch (_) {
|
|
411
|
-
return localResult;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
192
|
+
console_log('Found in local cache');
|
|
415
193
|
return localResult;
|
|
416
194
|
}
|
|
417
195
|
|
|
196
|
+
console_log('Not found in local, checking Redis...');
|
|
418
197
|
try {
|
|
419
198
|
const redisResult = await redisHandler.get(vKey, context);
|
|
420
199
|
|
|
421
200
|
if (redisResult) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (typeof redisResult === 'string') {
|
|
425
|
-
try {
|
|
426
|
-
finalResult = JSON.parse(redisResult);
|
|
427
|
-
} catch (parseError) {
|
|
428
|
-
finalResult = redisResult;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (
|
|
433
|
-
finalResult &&
|
|
434
|
-
typeof finalResult === 'object' &&
|
|
435
|
-
(finalResult.__compressed ||
|
|
436
|
-
(finalResult.value && finalResult.value.__compressed) ||
|
|
437
|
-
finalResult.compressed !== undefined)
|
|
438
|
-
) {
|
|
439
|
-
try {
|
|
440
|
-
const decompressed = await decompressValue(finalResult);
|
|
441
|
-
finalResult =
|
|
442
|
-
typeof decompressed === 'string'
|
|
443
|
-
? JSON.parse(decompressed)
|
|
444
|
-
: decompressed;
|
|
445
|
-
} catch (_) {
|
|
446
|
-
return finalResult;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
201
|
+
console_log('Found in Redis');
|
|
202
|
+
// Sync back to local cache for faster future access
|
|
450
203
|
try {
|
|
451
|
-
await localHandler.set(vKey,
|
|
452
|
-
|
|
453
|
-
|
|
204
|
+
await localHandler.set(vKey, redisResult, context);
|
|
205
|
+
console_log('Synced to local cache');
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console_log('Failed to sync to local:', error.message);
|
|
454
208
|
}
|
|
455
|
-
return
|
|
209
|
+
return redisResult;
|
|
456
210
|
}
|
|
457
|
-
} catch (
|
|
458
|
-
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console_log('Redis error:', error.message);
|
|
459
213
|
}
|
|
460
214
|
|
|
215
|
+
console_log('Not found in any cache');
|
|
461
216
|
return undefined;
|
|
462
217
|
},
|
|
463
218
|
set: async (key, value, context) => {
|
|
464
219
|
const vKey = versionKey(key);
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
(
|
|
475
|
-
|
|
476
|
-
} catch (error) {
|
|
477
|
-
compressedValue = value;
|
|
478
|
-
shouldUseCompressed = false;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
let redisSetResult;
|
|
482
|
-
|
|
483
|
-
if (shouldUseCompressed) {
|
|
484
|
-
try {
|
|
485
|
-
await redisHandler.set(vKey, compressedValue, context);
|
|
486
|
-
|
|
487
|
-
redisSetResult = { status: 'fulfilled' };
|
|
488
|
-
} catch (compressionError) {
|
|
489
|
-
try {
|
|
490
|
-
await redisHandler.set(vKey, value, context);
|
|
491
|
-
|
|
492
|
-
redisSetResult = { status: 'fulfilled' };
|
|
493
|
-
} catch (fallbackError) {
|
|
494
|
-
redisSetResult = { status: 'rejected', reason: fallbackError };
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
} else {
|
|
498
|
-
try {
|
|
499
|
-
await redisHandler.set(vKey, value, context);
|
|
500
|
-
redisSetResult = { status: 'fulfilled' };
|
|
501
|
-
} catch (error) {
|
|
502
|
-
redisSetResult = { status: 'rejected', reason: error };
|
|
503
|
-
return redisSetResult;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
let localSetResult;
|
|
508
|
-
try {
|
|
509
|
-
await localHandler.set(vKey, value, context);
|
|
510
|
-
localSetResult = { status: 'fulfilled' };
|
|
511
|
-
} catch (error) {
|
|
512
|
-
localSetResult = { status: 'rejected', reason: error };
|
|
513
|
-
return localSetResult;
|
|
514
|
-
}
|
|
220
|
+
console_log(
|
|
221
|
+
'SET called for key:',
|
|
222
|
+
typeof vKey === 'string' ? vKey : vKey?.key
|
|
223
|
+
);
|
|
224
|
+
// Set to both caches
|
|
225
|
+
await Promise.allSettled([
|
|
226
|
+
localHandler.set(vKey, value, context),
|
|
227
|
+
redisHandler
|
|
228
|
+
.set(vKey, value, context)
|
|
229
|
+
.catch((error) => console_log('Redis SET error:', error.message))
|
|
230
|
+
]);
|
|
515
231
|
},
|
|
516
232
|
delete: async (key, context) => {
|
|
517
233
|
const vKey = versionKey(key);
|
|
518
|
-
|
|
234
|
+
console_log(
|
|
235
|
+
'DELETE called for key:',
|
|
236
|
+
typeof vKey === 'string' ? vKey : vKey?.key
|
|
237
|
+
);
|
|
519
238
|
await Promise.allSettled([
|
|
520
239
|
localHandler.delete?.(vKey, context),
|
|
521
240
|
redisHandler.delete?.(vKey, context)
|
|
522
241
|
]);
|
|
523
242
|
},
|
|
524
243
|
revalidateTag: async (tags, context) => {
|
|
244
|
+
console_log('REVALIDATE_TAG called for tags:', tags);
|
|
525
245
|
await Promise.allSettled([
|
|
526
246
|
localHandler.revalidateTag?.(tags, context),
|
|
527
247
|
redisHandler.revalidateTag?.(tags, context)
|
|
@@ -529,6 +249,8 @@ CacheHandler.onCreation(async () => {
|
|
|
529
249
|
}
|
|
530
250
|
};
|
|
531
251
|
|
|
252
|
+
console_log('[Cache Handler] Handlers initialized successfully');
|
|
253
|
+
|
|
532
254
|
return {
|
|
533
255
|
handlers: [customHandler]
|
|
534
256
|
};
|