# 可降级缓存系统实现计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 构建 `packages/cache` 包,实现 Redis 主存储 + Memory 内存降级的通用 K-V 缓存系统 **Architecture:** 分层适配器架构:`CacheDriver` 接口定义 get/set/del/exists/clear,`MemoryDriver` 和 `RedisDriver` 分别实现, `CacheManager` 按 drivers 数组顺序尝试调用方透明降级 **Tech Stack:** TypeScript, ioredis, Node.js --- ## 文件结构 ``` packages/cache/ ├── package.json ├── index.ts └── lib/ ├── types.ts ← CacheDriver 接口、CacheManagerOptions、CacheEntry ├── managers/ │ └── cache-manager.ts ← CacheManager 实现(降级逻辑) └── drivers/ ├── base.ts ← 抽象基类 AbstractCacheDriver ├── memory-driver.ts ← Map 实现 └── redis-driver.ts ← ioredis 实现 ``` --- ## Task 1: 项目脚手架 **Files:** - Create: `packages/cache/package.json` - Create: `packages/cache/index.ts` - Create: `packages/cache/tsconfig.json` - Create: `packages/cache/lib/types.ts` - [ ] **Step 1: 创建 package.json** ```json { "name": "cache", "version": "0.1.0", "type": "module", "exports": { ".": "./index.ts" }, "dependencies": { "ioredis": "^5.4.1" }, "devDependencies": { "@types/node": "^20.0.0" } } ``` Run: `ls packages/cache/package.json` Expected: 文件存在 - [ ] **Step 2: 创建 types.ts** ```typescript export interface CacheEntry { value: T expiresAt: number | null // Unix ms,null = 永不过期 } export interface CacheDriver { name: string get(key: string): Promise set(key: string, value: T, ttl?: number): Promise del(key: string): Promise exists(key: string): Promise clear(): Promise } export interface CacheManagerOptions { drivers: CacheDriver[] defaultTtl?: number } ``` Run: `cat packages/cache/lib/types.ts` Expected: 文件存在,CacheDriver、CacheManagerOptions、CacheEntry 导出 - [ ] **Step 3: 创建 index.ts 骨架** ```typescript export * from './lib/types' ``` Run: `cat packages/cache/index.ts` Expected: `export * from './lib/types'` - [ ] **Step 4: 提交** ```bash git add packages/cache/package.json packages/cache/index.ts packages/cache/tsconfig.json packages/cache/lib/types.ts git commit -m "feat(cache): scaffold package and define core types Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 2: MemoryDriver **Files:** - Create: `packages/cache/lib/drivers/memory-driver.ts` - [ ] **Step 1: 实现 MemoryDriver** ```typescript import type { CacheDriver } from '../types' interface MemoryEntry { value: unknown expiresAt: number | null } export class MemoryDriver implements CacheDriver { name = 'memory' private store = new Map() async get(key: string): Promise { const entry = this.store.get(key) if (!entry) return null if (entry.expiresAt !== null && entry.expiresAt < Date.now()) { this.store.delete(key) return null } return entry.value as T } async set(key: string, value: T, ttl = 0): Promise { const expiresAt = ttl > 0 ? Date.now() + ttl * 1000 : null this.store.set(key, { value, expiresAt }) } async del(key: string): Promise { this.store.delete(key) } async exists(key: string): Promise { const entry = this.store.get(key) if (!entry) return false if (entry.expiresAt !== null && entry.expiresAt < Date.now()) { this.store.delete(key) return false } return true } async clear(): Promise { this.store.clear() } } ``` Run: `cat packages/cache/lib/drivers/memory-driver.ts` Expected: 文件存在,类导出 - [ ] **Step 2: 更新 index.ts 导出 MemoryDriver** ```typescript export * from './lib/types' export { MemoryDriver } from './lib/drivers/memory-driver' ``` Run: `cat packages/cache/index.ts` Expected: 包含 MemoryDriver 导出 - [ ] **Step 3: 提交** ```bash git add packages/cache/lib/drivers/memory-driver.ts packages/cache/index.ts git commit -m "feat(cache): implement MemoryDriver Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 3: RedisDriver **Files:** - Create: `packages/cache/lib/drivers/redis-driver.ts` - [ ] **Step 1: 实现 RedisDriver** ```typescript import Redis from 'ioredis' import type { CacheDriver } from '../types' export interface RedisDriverOptions { host: string port: number password?: string db?: number } export class RedisDriver implements CacheDriver { name = 'redis' private redis: Redis constructor(options: RedisDriverOptions) { this.redis = new Redis({ host: options.host, port: options.port, password: options.password, db: options.db ?? 0, lazyConnect: true, }) } private serialize(value: T): string { return JSON.stringify(value) } private deserialize(data: string): T { return JSON.parse(data) as T } async get(key: string): Promise { const data = await this.redis.get(key) if (!data) return null return this.deserialize(data) } async set(key: string, value: T, ttl = 0): Promise { const serialized = this.serialize(value) if (ttl > 0) { await this.redis.set(key, serialized, 'EX', ttl) } else { await this.redis.set(key, serialized) } } async del(key: string): Promise { await this.redis.del(key) } async exists(key: string): Promise { const result = await this.redis.exists(key) return result === 1 } async clear(): Promise { await this.redis.flushdb() } async disconnect(): Promise { await this.redis.quit() } } ``` Run: `cat packages/cache/lib/drivers/redis-driver.ts` Expected: 文件存在,RedisDriver 导出,connect lazy - [ ] **Step 2: 更新 index.ts 导出 RedisDriver** ```typescript export * from './lib/types' export { MemoryDriver } from './lib/drivers/memory-driver' export { RedisDriver } from './lib/drivers/redis-driver' export type { RedisDriverOptions } from './lib/drivers/redis-driver' ``` Run: `cat packages/cache/index.ts` Expected: 包含 RedisDriver 导出 - [ ] **Step 3: 提交** ```bash git add packages/cache/lib/drivers/redis-driver.ts packages/cache/index.ts git commit -m "feat(cache): implement RedisDriver with ioredis Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 4: CacheManager **Files:** - Create: `packages/cache/lib/managers/cache-manager.ts` - [ ] **Step 1: 实现 CacheManager** ```typescript import type { CacheDriver, CacheManagerOptions } from '../types' export class CacheManager { private drivers: CacheDriver[] private defaultTtl: number constructor(options: CacheManagerOptions) { if (!options.drivers || options.drivers.length === 0) { throw new Error('[cache] at least one driver is required') } this.drivers = options.drivers this.defaultTtl = options.defaultTtl ?? 0 } async get(key: string): Promise { for (const driver of this.drivers) { try { const value = await driver.get(key) return value } catch (err) { console.warn(`[cache] ${driver.name} get failed:`, err) continue } } return null } async set(key: string, value: T, ttl?: number): Promise { const effectiveTtl = ttl ?? this.defaultTtl await Promise.all( this.drivers.map(async (driver) => { try { await driver.set(key, value, effectiveTtl) } catch (err) { console.warn(`[cache] ${driver.name} set failed:`, err) } }) ) } async del(key: string): Promise { await Promise.all( this.drivers.map(async (driver) => { try { await driver.del(key) } catch (err) { console.warn(`[cache] ${driver.name} del failed:`, err) } }) ) } async exists(key: string): Promise { for (const driver of this.drivers) { try { const exists = await driver.exists(key) if (exists) return true } catch (err) { console.warn(`[cache] ${driver.name} exists failed:`, err) continue } } return false } async clear(): Promise { await Promise.all( this.drivers.map(async (driver) => { try { await driver.clear() } catch (err) { console.warn(`[cache] ${driver.name} clear failed:`, err) } }) ) } } ``` Run: `cat packages/cache/lib/managers/cache-manager.ts` Expected: 文件存在,CacheManager 导出 - [ ] **Step 2: 更新 index.ts 导出 CacheManager** ```typescript export * from './lib/types' export { MemoryDriver } from './lib/drivers/memory-driver' export { RedisDriver } from './lib/drivers/redis-driver' export { CacheManager } from './lib/managers/cache-manager' export type { RedisDriverOptions } from './lib/drivers/redis-driver' ``` Run: `cat packages/cache/index.ts` Expected: 包含 CacheManager 导出 - [ ] **Step 3: 提交** ```bash git add packages/cache/lib/managers/cache-manager.ts packages/cache/index.ts git commit -m "feat(cache): implement CacheManager with fallback logic Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 5: createCache 工厂函数 **Files:** - Modify: `packages/cache/index.ts` - [ ] **Step 1: 实现 createCache 工厂函数** ```typescript import { CacheManager } from './lib/managers/cache-manager' import { MemoryDriver } from './lib/drivers/memory-driver' import { RedisDriver } from './lib/drivers/redis-driver' import type { CacheDriver, CacheManagerOptions } from './lib/types' import type { RedisDriverOptions } from './lib/drivers/redis-driver' export * from './lib/types' export { MemoryDriver } from './lib/drivers/memory-driver' export { RedisDriver } from './lib/drivers/redis-driver' export { CacheManager } from './lib/managers/cache-manager' export type { RedisDriverOptions } from './lib/drivers/redis-driver' export interface CacheFactoryOptions { redis?: RedisDriverOptions memory?: boolean defaultTtl?: number } export function createCache(options: CacheFactoryOptions): CacheManager { const drivers: CacheDriver[] = [] if (options.redis) { drivers.push(new RedisDriver(options.redis)) } if (options.memory !== false) { drivers.push(new MemoryDriver()) } if (drivers.length === 0) { throw new Error('[cache] at least one driver (redis or memory) is required') } return new CacheManager({ drivers, defaultTtl: options.defaultTtl }) } ``` Run: `cat packages/cache/index.ts` Expected: createCache 工厂函数存在 - [ ] **Step 2: 提交** ```bash git add packages/cache/index.ts git commit -m "feat(cache): add createCache factory function Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 6: 验证构建 - [ ] **Step 1: 安装依赖** Run: `cd /home/dash/coding/nuxt-app && bun add -w cache` Expected: ioredis 被添加到 packages/cache/package.json - [ ] **Step 2: 类型检查** Run: `cd packages/cache && npx tsc --noEmit` Expected: 无错误输出 - [ ] **Step 3: 提交** ```bash git add -A git commit -m "chore(cache): add dependencies and verify build Co-Authored-By: Claude Opus 4.7 " ``` --- ## 自检清单 - [ ] spec 覆盖:CacheDriver 接口 ✓ / MemoryDriver ✓ / RedisDriver ✓ / CacheManager ✓ / createCache ✓ / 降级逻辑 ✓ - [ ] 无 placeholder:无 TBD/TODO/类似占位符 - [ ] 类型一致性:get/set/del/exists/clear 方法签名在各驱动一致 ✓