Files
record-app-next/lib/cache/index.ts
2025-07-31 17:05:07 +08:00

152 lines
3.3 KiB
TypeScript

import { logger } from "../utils/logger";
export interface CacheOptions {
ttl?: number; // 生存时间(毫秒)
maxSize?: number; // 最大缓存项数
}
export interface CacheEntry<T> {
value: T;
timestamp: number;
ttl: number;
}
class Cache {
private cache = new Map<string, CacheEntry<unknown>>();
private maxSize: number;
private defaultTtl: number;
constructor(options: CacheOptions = {}) {
this.maxSize = options.maxSize || 1000;
this.defaultTtl = options.ttl || 5 * 60 * 1000; // 默认5分钟
}
set<T>(key: string, value: T, ttl?: number): void {
// 如果缓存已满,删除最旧的项
if (this.cache.size >= this.maxSize) {
this.evictOldest();
}
const entry: CacheEntry<T> = {
value,
timestamp: Date.now(),
ttl: ttl || this.defaultTtl,
};
this.cache.set(key, entry);
logger.debug("Cache set", { key, ttl: entry.ttl });
}
get<T>(key: string): T | null {
const entry = this.cache.get(key) as CacheEntry<T> | undefined;
if (!entry) {
logger.debug("Cache miss", { key });
return null;
}
// 检查是否过期
if (Date.now() - entry.timestamp > entry.ttl) {
this.cache.delete(key);
logger.debug("Cache expired", { key });
return null;
}
logger.debug("Cache hit", { key });
return entry.value;
}
has(key: string): boolean {
const entry = this.cache.get(key);
if (!entry) return false;
// 检查是否过期
if (Date.now() - entry.timestamp > entry.ttl) {
this.cache.delete(key);
return false;
}
return true;
}
delete(key: string): boolean {
const deleted = this.cache.delete(key);
if (deleted) {
logger.debug("Cache deleted", { key });
}
return deleted;
}
clear(): void {
this.cache.clear();
logger.info("Cache cleared");
}
size(): number {
return this.cache.size;
}
private evictOldest(): void {
let oldestKey: string | null = null;
let oldestTime = Date.now();
for (const [key, entry] of this.cache.entries()) {
if (entry.timestamp < oldestTime) {
oldestTime = entry.timestamp;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
logger.debug("Cache evicted oldest", { key: oldestKey });
}
}
// 清理过期项
cleanup(): void {
const now = Date.now();
let cleanedCount = 0;
for (const [key, entry] of this.cache.entries()) {
if (now - entry.timestamp > entry.ttl) {
this.cache.delete(key);
cleanedCount++;
}
}
if (cleanedCount > 0) {
logger.info("Cache cleanup completed", { cleanedCount });
}
}
// 获取缓存统计信息
getStats(): {
size: number;
maxSize: number;
hitRate: number;
missRate: number;
} {
return {
size: this.cache.size,
maxSize: this.maxSize,
hitRate: 0, // 需要实现命中率统计
missRate: 0, // 需要实现未命中率统计
};
}
}
// 创建全局缓存实例
export const cache = new Cache({
maxSize: 1000,
ttl: 5 * 60 * 1000, // 5分钟
});
// 定期清理过期项
if (typeof window === "undefined") {
// 仅在服务器端运行
setInterval(() => {
cache.cleanup();
}, 60 * 1000); // 每分钟清理一次
}