update
This commit is contained in:
169
config/redis.js
Normal file
169
config/redis.js
Normal file
@@ -0,0 +1,169 @@
|
||||
const Redis = require('ioredis');
|
||||
const config = require('./config.json');
|
||||
|
||||
/**
|
||||
* Redis Connection - Direct connection to master
|
||||
* For Sentinel HA from external clients, we connect directly to the master port
|
||||
* and rely on manual failover by trying both ports
|
||||
*/
|
||||
const redisConfig = config.redis;
|
||||
|
||||
// Direct connection to master (port 11010)
|
||||
const redisClient = new Redis({
|
||||
host: redisConfig.cluster[0].host,
|
||||
port: redisConfig.cluster[0].port,
|
||||
password: redisConfig.password,
|
||||
db: redisConfig.db,
|
||||
keyPrefix: redisConfig.keyPrefix,
|
||||
connectTimeout: 10000,
|
||||
|
||||
retryStrategy: (times) => {
|
||||
if (times > 10) {
|
||||
console.log(`⚠️ Redis retry exhausted after ${times} attempts`);
|
||||
return null;
|
||||
}
|
||||
const delay = Math.min(times * 100, 3000);
|
||||
console.log(`🔄 Redis retry attempt ${times}, delay ${delay}ms`);
|
||||
return delay;
|
||||
},
|
||||
|
||||
// Reconnect on READONLY error (slave promoted)
|
||||
reconnectOnError: (err) => {
|
||||
if (err.message.includes('READONLY')) {
|
||||
console.log('⚠️ READONLY error detected - slave may have been promoted');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
enableOfflineQueue: true,
|
||||
maxRetriesPerRequest: null,
|
||||
enableReadyCheck: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Redis Event Handlers
|
||||
*/
|
||||
redisClient.on('connect', () => {
|
||||
console.log('✅ Redis client connected');
|
||||
});
|
||||
|
||||
redisClient.on('ready', () => {
|
||||
console.log('✅ Redis client ready');
|
||||
});
|
||||
|
||||
redisClient.on('error', (err) => {
|
||||
console.error('❌ Redis error:', err.message);
|
||||
});
|
||||
|
||||
redisClient.on('close', () => {
|
||||
console.log('⚠️ Redis client closed');
|
||||
});
|
||||
|
||||
redisClient.on('reconnecting', () => {
|
||||
console.log('🔄 Redis client reconnecting...');
|
||||
});
|
||||
|
||||
/**
|
||||
* Cache utility functions
|
||||
*/
|
||||
const cacheUtils = {
|
||||
/**
|
||||
* Get value from cache
|
||||
*/
|
||||
get: async (key) => {
|
||||
try {
|
||||
const value = await redisClient.get(key);
|
||||
return value ? JSON.parse(value) : null;
|
||||
} catch (error) {
|
||||
console.error(`Error getting cache for key ${key}:`, error.message);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set value to cache with TTL
|
||||
*/
|
||||
set: async (key, value, ttl = 3600) => {
|
||||
try {
|
||||
const serialized = JSON.stringify(value);
|
||||
await redisClient.setex(key, ttl, serialized);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Error setting cache for key ${key}:`, error.message);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete cache by key
|
||||
*/
|
||||
delete: async (key) => {
|
||||
try {
|
||||
await redisClient.del(key);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Error deleting cache for key ${key}:`, error.message);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete cache by pattern
|
||||
*/
|
||||
deletePattern: async (pattern) => {
|
||||
try {
|
||||
const keys = await redisClient.keys(pattern);
|
||||
if (keys.length > 0) {
|
||||
await redisClient.del(...keys);
|
||||
}
|
||||
return keys.length;
|
||||
} catch (error) {
|
||||
console.error(`Error deleting cache pattern ${pattern}:`, error.message);
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if key exists
|
||||
*/
|
||||
exists: async (key) => {
|
||||
try {
|
||||
const result = await redisClient.exists(key);
|
||||
return result === 1;
|
||||
} catch (error) {
|
||||
console.error(`Error checking cache existence for key ${key}:`, error.message);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get TTL for key
|
||||
*/
|
||||
ttl: async (key) => {
|
||||
try {
|
||||
return await redisClient.ttl(key);
|
||||
} catch (error) {
|
||||
console.error(`Error getting TTL for key ${key}:`, error.message);
|
||||
return -1;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Close Redis connection
|
||||
*/
|
||||
const closeRedisConnection = async () => {
|
||||
try {
|
||||
await redisClient.quit();
|
||||
console.log('✅ Redis connection closed gracefully');
|
||||
} catch (error) {
|
||||
console.error('❌ Error closing Redis connection:', error.message);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
redisClient,
|
||||
cacheUtils,
|
||||
closeRedisConnection,
|
||||
};
|
||||
Reference in New Issue
Block a user