Files
wwjcloud/src/common/cache/cache.service.ts
wanwu 2285206b3f feat: WWJCloud 企业级全栈框架 v0.3.5 完整更新
🚀 核心更新:
-  完善 NestJS 企业级架构设计
-  优化配置中心和基础设施层
-  增强第三方服务集成能力
-  完善多租户架构支持
- 🎯 对标 Java Spring Boot 和 PHP ThinkPHP

📦 新增文件:
- wwjcloud-nest 完整框架结构
- Docker 容器化配置
- 管理后台界面
- 数据库迁移脚本

🔑 Key: ebb38b43ec39f355f071294fd1cf9c42
2025-10-13 01:27:37 +08:00

329 lines
7.7 KiB
TypeScript

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<T = any>(key: string): Promise<T | null> {
try {
return await this.cacheProvider.get<T>(key);
} catch (error) {
this.logger.error(`Failed to get cache key: ${key}`, error);
return null;
}
}
/**
* 设置缓存
*/
async set(key: string, value: any, ttl?: number): Promise<void> {
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<void> {
try {
await this.cacheProvider.del(key);
} catch (error) {
this.logger.error(`Failed to delete cache key: ${key}`, error);
}
}
/**
* 批量删除缓存
*/
async delMany(keys: string[]): Promise<void> {
try {
await this.cacheProvider.delMany(keys);
} catch (error) {
this.logger.error(
`Failed to delete cache keys: ${keys.join(', ')}`,
error,
);
}
}
/**
* 检查缓存是否存在
*/
async exists(key: string): Promise<boolean> {
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<void> {
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<number> {
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<string[]> {
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<void> {
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<T> cacheHelper)
*/
async cache<T>(key: string, cacheHelper: CacheHelper<T>): Promise<T> {
return this.cacheWithOptions<T>({ key }, cacheHelper);
}
/**
* 带选项的缓存
* 对应 Java: cache(boolean cache, String key, CacheHelper<T> cacheHelper)
*/
async cacheWithOptions<T>(
options: CacheOptions,
cacheHelper: CacheHelper<T>,
): Promise<T> {
const { key, ttl, enabled = true, condition } = options;
if (!enabled || !key) {
return await cacheHelper.execute(key || '');
}
try {
// 尝试从缓存获取
let result = await this.get<T>(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<Object> paramList, CacheHelper<T> cacheHelper)
*/
async remember<T>(paramList: any[], cacheHelper: CacheHelper<T>): Promise<T> {
const key = this.computeUniqueKey(paramList);
return this.cache<T>(key, cacheHelper);
}
/**
* 记住对象结果
* 对应 Java: rememberObject(List<Object> paramList, CacheHelper<T> cacheHelper)
*/
async rememberObject<T>(
paramList: any[],
cacheHelper: CacheHelper<T>,
): Promise<T> {
return this.remember<T>(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: <T = any>(key: string) => this.groupCacheProvider.get<T>(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<T = any>(keys: string[]): Promise<(T | null)[]> {
const results: (T | null)[] = [];
for (const key of keys) {
results.push(await this.get<T>(key));
}
return results;
}
/**
* 批量设置
*/
async mset(
keyValuePairs: Array<{ key: string; value: any; ttl?: number }>,
): Promise<void> {
for (const { key, value, ttl } of keyValuePairs) {
await this.set(key, value, ttl);
}
}
/**
* 原子递增
*/
async incr(key: string, increment: number = 1): Promise<number> {
const current = (await this.get<number>(key)) || 0;
const newValue = current + increment;
await this.set(key, newValue);
return newValue;
}
/**
* 原子递减
*/
async decr(key: string, decrement: number = 1): Promise<number> {
return this.incr(key, -decrement);
}
/**
* 设置哈希字段
*/
async hset(key: string, field: string, value: any): Promise<void> {
const hash = (await this.get<Record<string, any>>(key)) || {};
hash[field] = value;
await this.set(key, hash);
}
/**
* 获取哈希字段
*/
async hget<T = any>(key: string, field: string): Promise<T | null> {
const hash = await this.get<Record<string, any>>(key);
return hash ? hash[field] || null : null;
}
/**
* 删除哈希字段
*/
async hdel(key: string, field: string): Promise<void> {
const hash = await this.get<Record<string, any>>(key);
if (hash) {
delete hash[field];
await this.set(key, hash);
}
}
/**
* 获取哈希所有字段
*/
async hgetall(key: string): Promise<Record<string, any>> {
return (await this.get<Record<string, any>>(key)) || {};
}
}