Skip to content

Commit 2ec8058

Browse files
committed
feat(cache): implement read and write handlers for Redis
Currently, the redis cache handler is reading and writing from the primary endpoint which is causing throttling from the primary instance. Instead, reads should come from read-only replicas and writes go to the primary. This changes the caching pattern to eventual consistency, but this is acceptable for the marketing sites. - Added separate read and write handlers for Redis caching. - Updated constructor to initialize handlers based on environment variables. - Modified methods to use new handlers for cache operations.
1 parent 8d917f4 commit 2ec8058

File tree

2 files changed

+48
-21
lines changed

2 files changed

+48
-21
lines changed

apps/marketing/cache-handler.mjs

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {RedisStringsHandler} from '@trieb.work/nextjs-turbo-redis-cache';
55
*/
66
class RedisCacheHandler {
77
static #instance = null;
8-
cachedHandler;
8+
writeCachedHandler;
9+
readCachedHandler;
910

1011
constructor() {
1112
if (RedisCacheHandler.#instance) {
@@ -14,27 +15,28 @@ class RedisCacheHandler {
1415
RedisCacheHandler.#instance = this;
1516

1617
const isRedisCacheEnabled =
17-
process.env.REDIS_URL && process.env.NODE_ENV === 'production';
18+
process.env.REDIS_READ_URL &&
19+
process.env.REDIS_WRITE_URL &&
20+
process.env.NODE_ENV === 'production';
1821

1922
if (isRedisCacheEnabled) {
2023
console.debug(`Using Redis cache`);
21-
this.cachedHandler = new RedisStringsHandler({
22-
database: 0,
23-
keyPrefix: 'marketing-sites::',
24-
sharedTagsKey: '__sharedTags__',
25-
// Enable TLS if the REDIS_URL starts with 'rediss://'
26-
...(process.env.REDIS_URL.startsWith('rediss://')
27-
? {
28-
socketOptions: {
29-
tls: true,
30-
},
31-
}
32-
: undefined),
33-
});
24+
this.writeCachedHandler = this.createCacheHandler(
25+
process.env.REDIS_WRITE_URL,
26+
);
27+
this.readCachedHandler = this.createCacheHandler(
28+
process.env.REDIS_READ_URL,
29+
);
3430
} else {
3531
console.warn('Redis cache disabled, using no-op handler');
3632
// Create a no-op handler if Redis is disabled
37-
this.cachedHandler = {
33+
this.readCachedHandler = {
34+
get: async () => null,
35+
set: async () => {},
36+
revalidateTag: async () => {},
37+
resetRequestCache: async () => {},
38+
};
39+
this.writeCachedHandler = {
3840
get: async () => null,
3941
set: async () => {},
4042
revalidateTag: async () => {},
@@ -43,36 +45,59 @@ class RedisCacheHandler {
4345
}
4446
}
4547

48+
createCacheHandler(endpoint) {
49+
return new RedisStringsHandler({
50+
database: 0,
51+
keyPrefix: 'marketing-sites::',
52+
sharedTagsKey: '__sharedTags__',
53+
redisUrl: endpoint,
54+
// Enable TLS if the endpoint starts with 'rediss://'
55+
...(endpoint.startsWith('rediss://')
56+
? {
57+
socketOptions: {
58+
tls: true,
59+
},
60+
}
61+
: undefined),
62+
});
63+
}
64+
4665
/**
4766
* @param {...Parameters<RedisStringsHandler['get']>} args
4867
* @returns {ReturnType<RedisStringsHandler['get']>}
4968
*/
5069
get(...args) {
51-
return this.cachedHandler.get(...args);
70+
return this.readCachedHandler.get(...args);
5271
}
5372

5473
/**
5574
* @param {...Parameters<RedisStringsHandler['set']>} args
5675
* @returns {ReturnType<RedisStringsHandler['set']>}
5776
*/
5877
set(...args) {
59-
return this.cachedHandler.set(...args);
78+
return this.writeCachedHandler.set(...args);
6079
}
6180

6281
/**
6382
* @param {...Parameters<RedisStringsHandler['revalidateTag']>} args
6483
* @returns {ReturnType<RedisStringsHandler['revalidateTag']>}
6584
*/
6685
revalidateTag(...args) {
67-
return this.cachedHandler.revalidateTag(...args);
86+
return Promise.all([
87+
this.readCachedHandler.revalidateTag(...args),
88+
this.writeCachedHandler.revalidateTag(...args),
89+
]);
6890
}
6991

7092
/**
7193
* @param {...Parameters<RedisStringsHandler['resetRequestCache']>} args
7294
* @returns {ReturnType<RedisStringsHandler['resetRequestCache']>}
7395
*/
7496
resetRequestCache(...args) {
75-
return this.cachedHandler.resetRequestCache(...args);
97+
return Promise.all([
98+
this.readCachedHandler.resetRequestCache(...args),
99+
this.writeCachedHandler.resetRequestCache(...args),
100+
]);
76101
}
77102
}
78103

apps/marketing/cicd/3-app/template.yml.erb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,8 +518,10 @@ Resources:
518518
Value: !Ref EnvironmentType
519519
- Name: NEXT_PUBLIC_INSTRUMENTATION_ENABLED
520520
Value: "true"
521-
- Name: REDIS_URL
521+
- Name: REDIS_WRITE_URL
522522
Value: !Sub "rediss://${RedisCluster.PrimaryEndPoint.Address}:6379"
523+
- Name: REDIS_READ_URL
524+
Value: !Sub "rediss://${RedisCluster.ReaderEndPoint.Address}:6379"
523525
# Do not verify that keyspace is available, as it is created by the RedisParameterGroup
524526
- Name: SKIP_KEYSPACE_CONFIG_CHECK
525527
Value: "true"

0 commit comments

Comments
 (0)