diff --git a/src/common/store.ts b/src/common/store.ts index ff6e6a59..9d804f28 100644 --- a/src/common/store.ts +++ b/src/common/store.ts @@ -1,190 +1,22 @@ -export type StoreValueType = string | number | boolean | object | null; - -export type StoreValue = { - value: T; - expiresAt?: number; -}; - class Store { - // 使用Map存储键值对 - private store: Map; - // 定时清理器 - private cleanerTimer: NodeJS.Timeout; - // 用于分批次扫描的游标 - private scanCursor: number = 0; + private store = new Map(); - /** - * Store - * @param cleanInterval 清理间隔 - * @param scanLimit 扫描限制(每次最多检查的键数) - */ - constructor ( - cleanInterval: number = 1000, // 默认1秒执行一次 - private scanLimit: number = 100 // 每次最多检查100个键 - ) { - this.store = new Map(); - this.cleanerTimer = setInterval(() => this.cleanupExpired(), cleanInterval); - } - - /** - * 设置键值对 - * @param key 键 - * @param value 值 - * @param ttl 过期时间 - * @returns void - * @example store.set('key', 'value', 60) - */ - set(key: string, value: T, ttl?: number): void { - if (ttl && ttl <= 0) { - this.del(key); - return; - } - const expiresAt = ttl ? Date.now() + ttl * 1000 : undefined; - this.store.set(key, { value, expiresAt }); - } - - /** - * 清理过期键 - */ - private cleanupExpired (): void { - const now = Date.now(); - const keys = Array.from(this.store.keys()); - let scanned = 0; - - // 分批次扫描 - while (scanned < this.scanLimit && this.scanCursor < keys.length) { - const key = keys[this.scanCursor++]; - const entry = this.store.get(key!)!; - - if (entry.expiresAt && entry.expiresAt < now) { - this.store.delete(key!); - } - - scanned++; - } - - // 重置游标(环形扫描) - if (this.scanCursor >= keys.length) { - this.scanCursor = 0; + set (key: string, value: T, ttl?: number): void { + this.store.set(key, value); + if (ttl) { + setTimeout(() => this.store.delete(key), ttl * 1000); } } - /** - * 获取键值 - * @param key 键 - * @returns T | null - * @example store.get('key') - */ - get(key: string): T | null { - this.checkKeyExpiry(key); // 每次访问都检查 - const entry = this.store.get(key); - return entry ? (entry.value as T) : null; + get (key: string): T | null { + return this.store.get(key) ?? null; } - /** - * 检查键是否过期 - * @param key 键 - */ - private checkKeyExpiry (key: string): void { - const entry = this.store.get(key); - if (entry?.expiresAt && entry.expiresAt < Date.now()) { - this.store.delete(key); - } - } - - /** - * 检查键是否存在 - * @param keys 键 - * @returns number - * @example store.exists('key1', 'key2') - */ exists (...keys: string[]): number { - return keys.filter((key) => { - this.checkKeyExpiry(key); - return this.store.has(key); - }).length; - } - - /** - * 关闭存储器 - */ - shutdown (): void { - clearInterval(this.cleanerTimer); - this.store.clear(); - } - - /** - * 删除键 - * @param keys 键 - * @returns number - * @example store.del('key1', 'key2') - */ - del (...keys: string[]): number { - return keys.reduce((count, key) => (this.store.delete(key) ? count + 1 : count), 0); - } - - /** - * 设置键的过期时间 - * @param key 键 - * @param seconds 过期时间(秒) - * @returns boolean - * @example store.expire('key', 60) - */ - expire (key: string, seconds: number): boolean { - const entry = this.store.get(key); - if (!entry) return false; - - entry.expiresAt = Date.now() + seconds * 1000; - return true; - } - - /** - * 获取键的过期时间 - * @param key 键 - * @returns number | null - * @example store.ttl('key') - */ - ttl (key: string): number | null { - const entry = this.store.get(key); - if (!entry) return null; - - if (!entry.expiresAt) return -1; - const remaining = entry.expiresAt - Date.now(); - return remaining > 0 ? Math.floor(remaining / 1000) : -2; - } - - /** - * 键值数字递增 - * @param key 键 - * @returns number - * @example store.incr('key') - */ - incr (key: string): number { - const current = this.get(key); - - if (current === null) { - this.set(key, 1, 60); - return 1; - } - - let numericValue: number; - if (typeof current === 'number') { - numericValue = current; - } else if (typeof current === 'string') { - if (!/^-?\d+$/.test(current)) { - throw new Error('ERR value is not an integer'); - } - numericValue = parseInt(current, 10); - } else { - throw new Error('ERR value is not an integer'); - } - - const newValue = numericValue + 1; - this.set(key, newValue, 60); - return newValue; + return keys.filter(key => this.store.has(key)).length; } } const store = new Store(); -export default store; +export default store; \ No newline at end of file diff --git a/src/webui/src/helper/Data.ts b/src/webui/src/helper/Data.ts index a585565e..283d6f56 100644 --- a/src/webui/src/helper/Data.ts +++ b/src/webui/src/helper/Data.ts @@ -57,7 +57,7 @@ export const WebUiDataRuntime = { return false; } - store.incr(key); + store.set(key, count + 1); return true; },