# Story 010.005: system-config-custom-routes-cache-refresh ## Status Completed ## Story **As a** 系统管理员, **I want** 用自定义路由替代通用CRUD路由,实现缓存自动刷新, **so that** 在管理后台更新系统配置时能自动刷新相应的key的Redis缓存 ## Acceptance Criteria 1. 参照packages/orders-module-mt/src/routes/user/orders.mt.ts中的聚合写法 2. 创建自定义路由替代现有的通用CRUD路由 3. 在配置创建、更新、删除操作时自动刷新对应key的Redis缓存 4. 保持API接口兼容性,不影响现有客户端调用 5. 验证缓存刷新机制正确工作,确保数据一致性 6. 所有现有功能测试通过,无回归 ## Tasks / Subtasks - [x] 任务 1 (AC: 1, 2): 创建系统配置自定义路由目录结构 - [x] 创建 `packages/core-module-mt/system-config-module-mt/src/routes/custom/` 目录 - [x] 参照订单模块聚合写法,创建自定义路由文件 [对照: packages/orders-module-mt/src/routes/user/orders.mt.ts] - [x] 创建自定义路由聚合文件 - [x] 任务 2 (AC: 2, 3): 实现创建配置的自定义路由 - [x] 创建 `packages/core-module-mt/system-config-module-mt/src/routes/custom/create-system-config.mt.ts` - [x] 参照createOrderRoutes实现POST路由 [对照: packages/orders-module-mt/src/routes/user/create-order.mt.ts] - [x] 调用SystemConfigServiceMt的setConfig方法 [对照: packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts:128-158] - [x] 在路由处理中自动刷新对应配置键的Redis缓存 - [x] 保持与现有CRUD路由相同的请求/响应格式 [对照: packages/core-module-mt/system-config-module-mt/src/routes/system-config.routes.mt.ts] - [x] **确保多租户隔离**: 从上下文中提取tenantId,确保只刷新当前租户的缓存 - [x] 任务 3 (AC: 2, 3): 实现更新配置的自定义路由 - [x] 创建 `packages/core-module-mt/system-config-module-mt/src/routes/custom/update-system-config.mt.ts` - [x] 参照createOrderRoutes模式实现PUT路由 [对照: packages/orders-module-mt/src/routes/user/create-order.mt.ts] - [x] 调用SystemConfigServiceMt的update方法 [对照: packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts:189-199] - [x] 在路由处理中自动刷新对应配置键的Redis缓存 - [x] 保持与现有CRUD路由相同的请求/响应格式 [对照: packages/core-module-mt/system-config-module-mt/src/routes/system-config.routes.mt.ts] - [x] **确保多租户隔离**: 验证更新操作只影响当前租户的配置和缓存 - [x] 任务 4 (AC: 2, 3): 实现删除配置的自定义路由 - [x] 创建 `packages/core-module-mt/system-config-module-mt/src/routes/custom/delete-system-config.mt.ts` - [x] 参照createOrderRoutes模式实现DELETE路由 [对照: packages/orders-module-mt/src/routes/user/create-order.mt.ts] - [x] 调用SystemConfigServiceMt的delete方法 [对照: packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts:204-217] - [x] 在路由处理中自动刷新对应配置键的Redis缓存 - [x] 保持与现有CRUD路由相同的请求/响应格式 [对照: packages/core-module-mt/system-config-module-mt/src/routes/system-config.routes.mt.ts] - [x] **确保多租户隔离**: 验证删除操作只删除当前租户的配置和缓存 - [x] 任务 5 (AC: 1, 2): 重构系统配置路由聚合 - [x] 修改 `packages/core-module-mt/system-config-module-mt/src/routes/system-config.routes.mt.ts` - [x] 参照订单模块聚合写法,将自定义路由与CRUD路由聚合 [对照: packages/orders-module-mt/src/routes/user/orders.mt.ts:34-38] - [x] 保持现有API接口兼容性 - [x] **确保多租户中间件正确应用**: 保持authMiddleware和tenantOptions配置 - [x] 任务 6 (AC: 4, 5): 验证缓存刷新机制 - [x] 创建缓存刷新验证测试 - [x] 验证创建配置时缓存正确刷新 - [x] 验证更新配置时缓存正确刷新 - [x] 验证删除配置时缓存正确刷新 - [x] **验证多租户缓存隔离**: 确保不同租户的配置缓存完全隔离 - [x] 任务 7 (AC: 6): 更新现有集成测试文件 - [x] 修改 `packages/core-module-mt/system-config-module-mt/tests/integration/system-config.routes.integration.test.ts` - [x] 添加自定义路由的集成测试 - [x] 验证自定义路由与CRUD路由的兼容性 - [x] 验证缓存刷新机制 - [x] 验证多租户隔离 - [x] 任务 8 (AC: 6): 验证现有功能无回归 - [x] 运行现有系统配置模块测试 [对照: packages/core-module-mt/system-config-module-mt/tests/integration/system-config.routes.integration.test.ts] - [x] 验证认证和支付模块集成正常 [对照: packages/core-module-mt/auth-module-mt/src/services/mini-auth.service.mt.ts] - [x] 验证管理后台UI包集成正常 [对照: packages/system-config-management-ui-mt/src/api/systemConfigClient.ts] - [x] 运行所有相关集成测试 ## Dev Notes ### 技术栈信息 [Source: architecture/tech-stack.md] - **运行时**: Node.js 20.18.3 - **框架**: Hono 4.8.5 (Web框架和API路由) - **数据库**: PostgreSQL 17 (通过TypeORM) - **ORM**: TypeORM 0.3.25 (实体管理) - **验证**: Zod + @hono/zod-openapi - **缓存**: Redis 7 (系统配置缓存) ### 项目结构信息 [Source: architecture/source-tree.md] - **包位置**: `packages/core-module-mt/system-config-module-mt/` - **包架构层次**: 多租户核心包中的业务模块 - **文件组织**: - `src/entities/` - 实体定义 (使用 `.mt.ts` 后缀) - `src/schemas/` - Zod Schema定义 (使用 `.mt.ts` 后缀) - `src/services/` - 服务实现 (使用 `.mt.ts` 后缀) - `src/routes/` - API路由 (使用 `.mt.ts` 后缀) - `src/routes/custom/` - 自定义路由 (新增) - `tests/` - 测试文件 - **现有模块参考**: - `auth-module-mt/` - 认证模块 - `user-module-mt/` - 用户模块 - `file-module-mt/` - 文件模块 - `orders-module-mt/` - 订单模块 (聚合写法参考) ### 订单模块聚合写法参考 [Source: packages/orders-module-mt/src/routes/user/orders.mt.ts] ```typescript // 订单模块的聚合写法示例 const userOrderRoutes = new OpenAPIHono() .route('/', createOrderRoutes) .route('/', cancelOrderRoutes) .route('/', userOrderCrudRoutes); ``` ### 系统配置服务缓存方法 [Source: packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts] - **setConfig**: 设置配置值,自动清除缓存 - **update**: 重写方法,在更新时清除缓存 - **deleteConfig**: 删除配置,自动清除缓存 - **getConfigByKey**: 获取配置值,带缓存逻辑 - **getConfigsByKeys**: 批量获取配置,带缓存逻辑 ### Redis缓存键格式 [Source: packages/shared-utils/src/utils/redis.util.ts] - **缓存键格式**: `system_config:{tenantId}:{configKey}` - **默认TTL**: 1小时 (3600秒) - **空值缓存TTL**: 5分钟 (300秒) ### 现有系统配置路由结构 [Source: packages/core-module-mt/system-config-module-mt/src/routes/system-config.routes.mt.ts] 当前使用通用CRUD路由: ```typescript const systemConfigCrudRoutes = createCrudRoutes({ entity: SystemConfigMt, createSchema: CreateSystemConfigSchema, updateSchema: UpdateSystemConfigSchema, getSchema: SystemConfigSchema, listSchema: SystemConfigSchema, searchFields: ['configKey', 'description'], middleware: [authMiddleware], tenantOptions: { enabled: true, tenantIdField: 'tenantId', autoExtractFromContext: true } }); ``` ### 共享CRUD集成模式 [Source: packages/shared-crud/src/services/generic-crud.service.ts] - **继承模式**: 继承 `GenericCrudService` 抽象类 - **租户配置**: 通过 `tenantOptions` 配置租户隔离 - **用户跟踪**: 通过 `userTracking` 配置用户跟踪 - **核心方法**: `getList()`, `getById()`, `create()`, `update()`, `delete()` ### 多租户隔离关键要求 **强制多租户隔离要求**: - **租户ID提取**: 所有自定义路由必须从上下文中提取tenantId [对照: packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts:11-13] - **缓存键隔离**: Redis缓存键必须包含tenantId前缀 `system_config:{tenantId}:{configKey}` [对照: packages/shared-utils/src/utils/redis.util.ts:68] - **数据库查询隔离**: 所有数据库查询必须包含tenantId条件 [对照: packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts:40] - **操作范围限制**: 创建、更新、删除操作只能影响当前租户的配置 - **缓存刷新隔离**: 缓存刷新操作只能清除当前租户的缓存 ### 先前故事实施经验 从Epic 010的前4个故事中提取的关键经验: - **缓存穿透保护**: 实现空值缓存机制防止缓存穿透攻击 [Source: docs/stories/010.002.system-config-redis-cache.story.md] - **多租户隔离**: 修复了多租户隔离概念,强制要求tenantId参数 [Source: docs/stories/010.002.system-config-redis-cache.story.md] - **TypeORM语法**: 修复了`{ configKey: missingKeys }`语法错误,改为`{ configKey: In(missingKeys) }` [Source: docs/stories/010.002.system-config-redis-cache.story.md] - **包导出配置**: 修复了system-config-module-mt包导出配置问题 [Source: docs/stories/010.003.system-config-auth-payment-integration.story.md] ### 测试 #### 测试标准 [Source: architecture/testing-strategy.md] - **测试框架**: Vitest + hono/testing - **测试位置**: `packages/core-module-mt/system-config-module-mt/tests/` - **测试类型**: 单元测试 + 集成测试 - **覆盖率目标**: 单元测试 ≥ 80%,集成测试 ≥ 60% #### 测试文件结构 - `tests/integration/` - 集成测试 - `system-config.routes.integration.test.ts` - 现有路由集成测试 - `system-config-custom-routes.integration.test.ts` - 新增自定义路由集成测试 #### 测试要求 - 验证自定义路由与CRUD路由聚合正确 - 验证缓存刷新机制正确工作 - **验证多租户缓存隔离**: 确保不同租户的配置缓存完全隔离 - **验证多租户数据隔离**: 确保操作只影响当前租户的数据 - **验证租户ID提取**: 确保从上下文中正确提取tenantId - 验证API接口兼容性 - 验证现有功能无回归 ## Change Log | Date | Version | Description | Author | |------|---------|-------------|--------| | 2025-11-22 | 1.0 | 初始故事创建 | Bob (Scrum Master) | | 2025-11-22 | 1.1 | 添加对照文件路径标注,强调多租户隔离要求 | Bob (Scrum Master) | ## Dev Agent Record ### Agent Model Used - Claude Code (d8d-model) ### Debug Log References - 修复认证模块导入路径问题:从 `@d8d/auth-module-mt` 改为 `@d8d/core-module-mt/auth-module-mt` - 修复测试文件类型错误:参数类型不匹配,将 `config.id.toString()` 改为字符串参数 - 修复删除路由响应状态码:从200改为204 - 修复缓存刷新机制:重写 `SystemConfigServiceMt` 的 `delete` 方法 - 修复OpenAPI响应定义:为所有错误响应添加 `content` 字段 - 修复类型错误:错误响应格式符合 `ErrorSchema` 要求 ### Completion Notes List 1. 成功创建自定义路由目录结构:`src/routes/custom/` 2. 实现三个自定义路由:创建、更新、删除,均自动处理缓存刷新 3. 重构路由聚合:将通用CRUD路由设为 `readOnly: true` 4. 重写 `SystemConfigServiceMt.delete()` 方法确保缓存刷新 5. 更新集成测试:添加自定义路由缓存刷新验证和多租户隔离测试 6. 所有13个集成测试通过,类型检查通过 7. 确保多租户隔离:从上下文中提取 `tenantId`,缓存键包含租户前缀 ### File List **创建的文件:** - `packages/core-module-mt/system-config-module-mt/src/routes/custom/create-system-config.mt.ts` - `packages/core-module-mt/system-config-module-mt/src/routes/custom/update-system-config.mt.ts` - `packages/core-module-mt/system-config-module-mt/src/routes/custom/delete-system-config.mt.ts` **修改的文件:** - `packages/core-module-mt/system-config-module-mt/src/routes/system-config.routes.mt.ts` - `packages/core-module-mt/system-config-module-mt/src/services/system-config.service.mt.ts` - `packages/core-module-mt/system-config-module-mt/tests/integration/system-config.routes.integration.test.ts` ## QA Results - ✅ **所有13个集成测试通过** - ✅ **类型检查通过** - ✅ **缓存自动刷新功能正常工作** - ✅ **多租户隔离正常工作** - ✅ **API兼容性保持** - ✅ **无功能回归**