Commit 577ff7fe authored by ThinhNC's avatar ThinhNC

feat(infra): support REDIS_URL connection string and TLS for cloud Redis

parent 97360cba
...@@ -13,6 +13,7 @@ JWT_REFRESH_SECRET=change_me_refresh_secret ...@@ -13,6 +13,7 @@ JWT_REFRESH_SECRET=change_me_refresh_secret
JWT_ACCESS_EXPIRES_IN=1d JWT_ACCESS_EXPIRES_IN=1d
JWT_REFRESH_EXPIRES_IN=7d JWT_REFRESH_EXPIRES_IN=7d
REDIS_URL=redis://red-d2xxxxxxxxxxxxxxxxxx:6379
REDIS_HOST=localhost REDIS_HOST=localhost
REDIS_PORT=7379 REDIS_PORT=7379
REDIS_PASSWORD= REDIS_PASSWORD=
......
...@@ -28,23 +28,33 @@ export class CacheService { ...@@ -28,23 +28,33 @@ export class CacheService {
private initRedis() { private initRedis() {
try { try {
this.redis = new Redis({ const retryStrategy = (times: number) => {
host: envConfig.redis.host, if (times > 3) {
port: envConfig.redis.port, this.logger.warn('Failed to connect to Redis. Falling back to in-memory cache.');
password: envConfig.redis.password, this.isRedisConnected = false;
lazyConnect: true, this.redis?.disconnect();
maxRetriesPerRequest: 3, this.initMemoryCleanup();
retryStrategy: (times) => { return null;
if (times > 3) { }
this.logger.warn('Failed to connect to Redis. Falling back to in-memory cache.'); return Math.min(times * 100, 2000);
this.isRedisConnected = false; };
this.redis?.disconnect();
this.initMemoryCleanup(); if (envConfig.redis.url) {
return null; // Stop retrying this.redis = new Redis(envConfig.redis.url, {
} lazyConnect: true,
return Math.min(times * 100, 2000); maxRetriesPerRequest: 3,
}, retryStrategy,
}); });
} else {
this.redis = new Redis({
host: envConfig.redis.host,
port: envConfig.redis.port,
password: envConfig.redis.password,
lazyConnect: true,
maxRetriesPerRequest: 3,
retryStrategy,
});
}
this.redis.on('connect', () => { this.redis.on('connect', () => {
this.logger.info('Successfully connected to Redis.'); this.logger.info('Successfully connected to Redis.');
......
...@@ -150,9 +150,41 @@ export const envConfig = { ...@@ -150,9 +150,41 @@ export const envConfig = {
}, },
}, },
redis: { redis: {
host: process.env.REDIS_HOST || 'localhost', url: process.env.REDIS_URL || '',
port: parseInt(process.env.REDIS_PORT || '6379', 10), host: (() => {
password: process.env.REDIS_PASSWORD || undefined, if (process.env.REDIS_HOST) return process.env.REDIS_HOST;
if (process.env.REDIS_URL) {
try {
return new URL(process.env.REDIS_URL).hostname || 'localhost';
} catch {
return 'localhost';
}
}
return 'localhost';
})(),
port: (() => {
if (process.env.REDIS_PORT) return parseInt(process.env.REDIS_PORT, 10);
if (process.env.REDIS_URL) {
try {
const p = new URL(process.env.REDIS_URL).port;
return p ? parseInt(p, 10) : 6379;
} catch {
return 6379;
}
}
return 6379;
})(),
password: (() => {
if (process.env.REDIS_PASSWORD) return process.env.REDIS_PASSWORD;
if (process.env.REDIS_URL) {
try {
return new URL(process.env.REDIS_URL).password || undefined;
} catch {
return undefined;
}
}
return undefined;
})(),
enabled: process.env.REDIS_ENABLED !== 'false', enabled: process.env.REDIS_ENABLED !== 'false',
}, },
rateLimit: { rateLimit: {
......
...@@ -38,10 +38,12 @@ export class WebhookQueueService { ...@@ -38,10 +38,12 @@ export class WebhookQueueService {
return; return;
} }
const isTls = envConfig.redis.url.startsWith('rediss://');
const connection = { const connection = {
host: redisHost, host: redisHost,
port: redisPort, port: redisPort,
password: redisPassword, password: redisPassword,
tls: isTls ? {} : undefined,
maxRetriesPerRequest: null, maxRetriesPerRequest: null,
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment