@akomalabs/kemono
Version:
A production-grade TypeScript API wrapper for the Kemono/Coomer platforms
133 lines • 3.81 kB
JavaScript
import Redis from 'ioredis';
/**
* In-memory cache implementation
*/
class MemoryCache {
cache;
constructor() {
this.cache = new Map();
}
async get(key) {
const item = this.cache.get(key);
if (!item)
return null;
if (Date.now() > item.expiry) {
this.cache.delete(key);
return null;
}
return item.value;
}
async set(key, value, ttl = 300) {
this.cache.set(key, {
value,
expiry: Date.now() + ttl * 1000,
});
}
async del(key) {
this.cache.delete(key);
}
}
/**
* Redis cache implementation
*/
class RedisCache {
client;
logger;
isConnected = false;
constructor(config, logger) {
if (!config || !config.host || !config.port) {
throw new Error('Invalid Redis configuration: host and port are required');
}
this.client = new Redis({
host: config.host,
port: config.port,
password: config.password,
retryStrategy: (times) => {
const delay = Math.min(times * 50, 2000);
return delay;
},
});
this.logger = logger;
this.client.on('connect', () => {
this.isConnected = true;
this.logger.info('Redis cache connected');
});
this.client.on('error', (err) => {
this.isConnected = false;
this.logger.error('Redis cache error:', err);
});
this.client.on('close', () => {
this.isConnected = false;
this.logger.warn('Redis cache connection closed');
});
}
async get(key) {
if (!this.isConnected) {
this.logger.warn('Redis cache not connected, falling back to null');
return null;
}
try {
return await this.client.get(key);
}
catch (error) {
this.logger.error('Redis get error:', error);
return null;
}
}
async set(key, value, ttl = 300) {
if (!this.isConnected) {
this.logger.warn('Redis cache not connected, skipping set operation');
return;
}
try {
await this.client.set(key, value, 'EX', ttl);
}
catch (error) {
this.logger.error('Redis set error:', error);
}
}
async del(key) {
if (!this.isConnected) {
this.logger.warn('Redis cache not connected, skipping delete operation');
return;
}
try {
await this.client.del(key);
}
catch (error) {
this.logger.error('Redis del error:', error);
}
}
}
/**
* Creates a cache instance based on the configuration
* @param config Cache configuration from KemonoConfig
* @param logger Logger instance
* @returns Cache instance
*/
export function createCache(config, logger) {
// Return no-op cache if caching is disabled or config is undefined
if (!config?.enabled) {
logger.info('Cache disabled, using no-op cache');
return {
get: async () => null,
set: async () => { },
del: async () => { },
};
}
// Try to create Redis cache if Redis config is provided
if (config.redis) {
try {
logger.info('Initializing Redis cache');
return new RedisCache(config.redis, logger);
}
catch (error) {
logger.error('Failed to initialize Redis cache, falling back to memory cache:', error);
return new MemoryCache();
}
}
// Default to memory cache
logger.info('Initializing memory cache');
return new MemoryCache();
}
//# sourceMappingURL=cache.js.map