mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
📡 refactor: Flush Redis Cache Script (#10087)
* 🔧 feat: Enhance Redis Configuration and Connection Handling in Cache Flush Utility
- Added support for Redis username, password, and CA certificate.
- Improved Redis client creation to handle both cluster and single instance configurations.
- Implemented a helper function to read the Redis CA certificate with error handling.
- Updated connection logic to include timeout and error handling for Redis connections.
* refactor: flush cache if redis URI is defined
This commit is contained in:
parent
bf2567bc8f
commit
3d1cedb85b
1 changed files with 86 additions and 13 deletions
|
|
@ -18,11 +18,38 @@ const fs = require('fs');
|
||||||
// Set up environment
|
// Set up environment
|
||||||
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
|
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
|
||||||
|
|
||||||
const { USE_REDIS, REDIS_URI, REDIS_KEY_PREFIX } = process.env;
|
const {
|
||||||
|
USE_REDIS,
|
||||||
|
REDIS_URI,
|
||||||
|
REDIS_USERNAME,
|
||||||
|
REDIS_PASSWORD,
|
||||||
|
REDIS_CA,
|
||||||
|
REDIS_KEY_PREFIX,
|
||||||
|
USE_REDIS_CLUSTER,
|
||||||
|
REDIS_USE_ALTERNATIVE_DNS_LOOKUP,
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
// Simple utility function
|
// Simple utility function
|
||||||
const isEnabled = (value) => value === 'true' || value === true;
|
const isEnabled = (value) => value === 'true' || value === true;
|
||||||
|
|
||||||
|
// Helper function to read Redis CA certificate
|
||||||
|
const getRedisCA = () => {
|
||||||
|
if (!REDIS_CA) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(REDIS_CA)) {
|
||||||
|
return fs.readFileSync(REDIS_CA, 'utf8');
|
||||||
|
} else {
|
||||||
|
console.warn(`⚠️ Redis CA certificate file not found: ${REDIS_CA}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Failed to read Redis CA certificate file '${REDIS_CA}':`, error.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async function showHelp() {
|
async function showHelp() {
|
||||||
console.log(`
|
console.log(`
|
||||||
LibreChat Cache Flush Utility
|
LibreChat Cache Flush Utility
|
||||||
|
|
@ -67,21 +94,67 @@ async function flushRedisCache(dryRun = false, verbose = false) {
|
||||||
console.log(` Prefix: ${REDIS_KEY_PREFIX || 'None'}`);
|
console.log(` Prefix: ${REDIS_KEY_PREFIX || 'None'}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Redis client directly
|
// Create Redis client using same pattern as main app
|
||||||
const Redis = require('ioredis');
|
const IoRedis = require('ioredis');
|
||||||
let redis;
|
let redis;
|
||||||
|
|
||||||
// Handle cluster vs single Redis
|
// Parse credentials from URI or use environment variables (same as redisClients.ts)
|
||||||
if (process.env.USE_REDIS_CLUSTER === 'true') {
|
const urls = (REDIS_URI || '').split(',').map((uri) => new URL(uri));
|
||||||
const hosts = REDIS_URI.split(',').map((uri) => {
|
const username = urls[0]?.username || REDIS_USERNAME;
|
||||||
const [host, port] = uri.split(':');
|
const password = urls[0]?.password || REDIS_PASSWORD;
|
||||||
return { host, port: parseInt(port) || 6379 };
|
const ca = getRedisCA();
|
||||||
});
|
|
||||||
redis = new Redis.Cluster(hosts);
|
// Redis options (matching redisClients.ts configuration)
|
||||||
|
const redisOptions = {
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
tls: ca ? { ca } : undefined,
|
||||||
|
connectTimeout: 10000,
|
||||||
|
maxRetriesPerRequest: 3,
|
||||||
|
enableOfflineQueue: true,
|
||||||
|
lazyConnect: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle cluster vs single Redis (same logic as redisClients.ts)
|
||||||
|
const useCluster = urls.length > 1 || isEnabled(USE_REDIS_CLUSTER);
|
||||||
|
|
||||||
|
if (useCluster) {
|
||||||
|
const clusterOptions = {
|
||||||
|
redisOptions,
|
||||||
|
enableOfflineQueue: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add DNS lookup for AWS ElastiCache if needed (same as redisClients.ts)
|
||||||
|
if (isEnabled(REDIS_USE_ALTERNATIVE_DNS_LOOKUP)) {
|
||||||
|
clusterOptions.dnsLookup = (address, callback) => callback(null, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
redis = new IoRedis.Cluster(
|
||||||
|
urls.map((url) => ({ host: url.hostname, port: parseInt(url.port, 10) || 6379 })),
|
||||||
|
clusterOptions,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
redis = new Redis(REDIS_URI);
|
// @ts-ignore - ioredis default export is constructable despite linter warning
|
||||||
|
redis = new IoRedis(REDIS_URI, redisOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for connection
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
reject(new Error('Connection timeout'));
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
redis.once('ready', () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
resolve(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
redis.once('error', (err) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (dryRun) {
|
if (dryRun) {
|
||||||
console.log('🔍 [DRY RUN] Would flush Redis cache');
|
console.log('🔍 [DRY RUN] Would flush Redis cache');
|
||||||
try {
|
try {
|
||||||
|
|
@ -105,7 +178,7 @@ async function flushRedisCache(dryRun = false, verbose = false) {
|
||||||
try {
|
try {
|
||||||
const keys = await redis.keys('*');
|
const keys = await redis.keys('*');
|
||||||
keyCount = keys.length;
|
keyCount = keys.length;
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
// Continue with flush even if we can't count keys
|
// Continue with flush even if we can't count keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,7 +282,7 @@ async function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let success = true;
|
let success = true;
|
||||||
const isRedisEnabled = isEnabled(USE_REDIS) && REDIS_URI;
|
const isRedisEnabled = isEnabled(USE_REDIS) || (REDIS_URI != null && REDIS_URI !== '');
|
||||||
|
|
||||||
// Flush the appropriate cache type
|
// Flush the appropriate cache type
|
||||||
if (isRedisEnabled) {
|
if (isRedisEnabled) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue