import { Injectable, Inject, Logger } from '@nestjs/common'; import type { CacheInterface, CacheOptions, CacheHelper, GroupCacheInterface, } from './cache.interface'; /** * 缓存服务 * 基于 NestJS 官方示例实现 * 参考: https://docs.nestjs.cn/fundamentals/dependency-injection * 对应 Java: CachedService */ @Injectable() export class CacheService implements CacheInterface { private readonly logger = new Logger(CacheService.name); constructor( @Inject('CACHE_PROVIDER') private readonly cacheProvider: CacheInterface, @Inject('GROUP_CACHE_PROVIDER') private readonly groupCacheProvider: GroupCacheInterface, ) {} /** * 获取缓存 */ async get(key: string): Promise { try { return await this.cacheProvider.get(key); } catch (error) { this.logger.error(`Failed to get cache key: ${key}`, error); return null; } } /** * 设置缓存 */ async set(key: string, value: any, ttl?: number): Promise { try { await this.cacheProvider.set(key, value, ttl); } catch (error) { this.logger.error(`Failed to set cache key: ${key}`, error); } } /** * 删除缓存 */ async del(key: string): Promise { try { await this.cacheProvider.del(key); } catch (error) { this.logger.error(`Failed to delete cache key: ${key}`, error); } } /** * 批量删除缓存 */ async delMany(keys: string[]): Promise { try { await this.cacheProvider.delMany(keys); } catch (error) { this.logger.error( `Failed to delete cache keys: ${keys.join(', ')}`, error, ); } } /** * 检查缓存是否存在 */ async exists(key: string): Promise { try { return await this.cacheProvider.exists(key); } catch (error) { this.logger.error(`Failed to check cache key: ${key}`, error); return false; } } /** * 设置过期时间 */ async expire(key: string, ttl: number): Promise { try { await this.cacheProvider.expire(key, ttl); } catch (error) { this.logger.error(`Failed to set expire for cache key: ${key}`, error); } } /** * 获取过期时间 */ async ttl(key: string): Promise { try { return await this.cacheProvider.ttl(key); } catch (error) { this.logger.error(`Failed to get ttl for cache key: ${key}`, error); return -1; } } /** * 获取所有键 */ async keys(pattern?: string): Promise { try { return await this.cacheProvider.keys(pattern); } catch (error) { this.logger.error( `Failed to get cache keys with pattern: ${pattern}`, error, ); return []; } } /** * 清空所有缓存 */ async flush(): Promise { try { await this.cacheProvider.flush(); } catch (error) { this.logger.error('Failed to flush cache', error); } } /** * 获取缓存统计信息 */ async stats() { try { return await this.cacheProvider.stats(); } catch (error) { this.logger.error('Failed to get cache stats', error); return { hits: 0, misses: 0, keys: 0, memory: 0, uptime: 0, }; } } /** * 缓存装饰器实现 * 对应 Java: cache(String key, CacheHelper cacheHelper) */ async cache(key: string, cacheHelper: CacheHelper): Promise { return this.cacheWithOptions({ key }, cacheHelper); } /** * 带选项的缓存 * 对应 Java: cache(boolean cache, String key, CacheHelper cacheHelper) */ async cacheWithOptions( options: CacheOptions, cacheHelper: CacheHelper, ): Promise { const { key, ttl, enabled = true, condition } = options; if (!enabled || !key) { return await cacheHelper.execute(key || ''); } try { // 尝试从缓存获取 let result = await this.get(key); if (result === null) { // 缓存未命中,执行函数 result = await cacheHelper.execute(key); if (result !== null && result !== undefined) { // 检查缓存条件 if (!condition || condition([], result)) { await this.set(key, result, ttl); } } } return result; } catch (error) { this.logger.error(`Cache operation failed for key: ${key}`, error); // 降级到直接执行 return await cacheHelper.execute(key); } } /** * 记住结果(带参数) * 对应 Java: remember(List paramList, CacheHelper cacheHelper) */ async remember(paramList: any[], cacheHelper: CacheHelper): Promise { const key = this.computeUniqueKey(paramList); return this.cache(key, cacheHelper); } /** * 记住对象结果 * 对应 Java: rememberObject(List paramList, CacheHelper cacheHelper) */ async rememberObject( paramList: any[], cacheHelper: CacheHelper, ): Promise { return this.remember(paramList, cacheHelper); } /** * 分组缓存 * 对应 Java: tag(String group) */ tag(group: string) { return { set: (key: string, value: any, ttl?: number) => this.groupCacheProvider.set(group, key, value, ttl), get: (key: string) => this.groupCacheProvider.get(group, key), del: (key: string) => this.groupCacheProvider.del(group, key), clear: () => this.groupCacheProvider.clear(group), keys: () => this.groupCacheProvider.keys(group), }; } /** * 计算唯一键 * 对应 Java: CacheUtils.computeUniqueKey(paramList) */ private computeUniqueKey(paramList: any[]): string { if (!paramList || paramList.length === 0) { return 'empty'; } const keyParts = paramList.map((param) => { if (param === null || param === undefined) { return 'null'; } if (typeof param === 'object') { return JSON.stringify(param); } return String(param); }); return keyParts.join(':'); } /** * 批量操作 */ async mget(keys: string[]): Promise<(T | null)[]> { const results: (T | null)[] = []; for (const key of keys) { results.push(await this.get(key)); } return results; } /** * 批量设置 */ async mset( keyValuePairs: Array<{ key: string; value: any; ttl?: number }>, ): Promise { for (const { key, value, ttl } of keyValuePairs) { await this.set(key, value, ttl); } } /** * 原子递增 */ async incr(key: string, increment: number = 1): Promise { const current = (await this.get(key)) || 0; const newValue = current + increment; await this.set(key, newValue); return newValue; } /** * 原子递减 */ async decr(key: string, decrement: number = 1): Promise { return this.incr(key, -decrement); } /** * 设置哈希字段 */ async hset(key: string, field: string, value: any): Promise { const hash = (await this.get>(key)) || {}; hash[field] = value; await this.set(key, hash); } /** * 获取哈希字段 */ async hget(key: string, field: string): Promise { const hash = await this.get>(key); return hash ? hash[field] || null : null; } /** * 删除哈希字段 */ async hdel(key: string, field: string): Promise { const hash = await this.get>(key); if (hash) { delete hash[field]; await this.set(key, hash); } } /** * 获取哈希所有字段 */ async hgetall(key: string): Promise> { return (await this.get>(key)) || {}; } }