57 lines
1.4 KiB
TypeScript
57 lines
1.4 KiB
TypeScript
/**
|
|
* @ai-summary Redis client and caching service
|
|
* @ai-context Used by all features for caching external API responses
|
|
*/
|
|
import Redis from 'ioredis';
|
|
import { logger } from '../logging/logger';
|
|
import { appConfig } from './config-loader';
|
|
|
|
export const redis = new Redis(appConfig.getRedisUrl(), {
|
|
retryStrategy: (times) => Math.min(times * 50, 2000),
|
|
});
|
|
|
|
redis.on('connect', () => {
|
|
logger.info('Redis connected');
|
|
});
|
|
|
|
redis.on('error', (err) => {
|
|
logger.error('Redis error', { error: err.message });
|
|
});
|
|
|
|
export class CacheService {
|
|
private prefix = 'mvp:';
|
|
|
|
async get<T>(key: string): Promise<T | null> {
|
|
try {
|
|
const data = await redis.get(this.prefix + key);
|
|
return data ? JSON.parse(data) : null;
|
|
} catch (error) {
|
|
logger.error('Cache get error', { key, error });
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async set(key: string, value: any, ttl?: number): Promise<void> {
|
|
try {
|
|
const data = JSON.stringify(value);
|
|
if (ttl) {
|
|
await redis.setex(this.prefix + key, ttl, data);
|
|
} else {
|
|
await redis.set(this.prefix + key, data);
|
|
}
|
|
} catch (error) {
|
|
logger.error('Cache set error', { key, error });
|
|
}
|
|
}
|
|
|
|
async del(key: string): Promise<void> {
|
|
try {
|
|
await redis.del(this.prefix + key);
|
|
} catch (error) {
|
|
logger.error('Cache delete error', { key, error });
|
|
}
|
|
}
|
|
}
|
|
|
|
export const cacheService = new CacheService();
|