Files
zhuyongxin 8bd758dbaf docs(devflow): 补充 Phase 1 项目记忆文档
创建 Phase 1 基础设施搭建的完整 devflow 文档:

- brief.md: 项目背景、目标、范围、技术选型、关键决策
- decisions.md: 6 个架构决策记录 (ADR)
  - ADR-001: Flyway 数据库版本管理
  - ADR-002: 枚举类型存储为 VARCHAR
  - ADR-003: Redis JSON 序列化
  - ADR-004: Spring Data JPA 命名约定
  - ADR-005: 会话 TTL 可配置
  - ADR-006: 包名暂时混用
- evidence.md: 测试证据、性能指标、编译验证、数据库结构
  - 27 个测试全部通过
  - 性能指标达标
  - 提交记录追踪
- acceptance.md: 验收标准、测试结果、遗留问题
  - 20/33 任务完成
  - 部分验收通过

更新全局文档:
- devflow/index.md: 新增 phase1-infrastructure 项目索引
- devflow/glossary/CONTEXT.md: 新增 8 个术语和 4 条业务规则

Progress: 20/33 tasks completed (61%)
2026-06-23 14:44:43 +08:00

5.1 KiB
Raw Permalink Blame History

Phase 1 基础设施搭建 — Decisions

ADR-001: 采用 Flyway 管理数据库版本

状态: 已接受
日期: 2026-06-23
决策者: zhuyongxin

背景

项目需要版本化管理数据库表结构,支持多环境部署和团队协作。

决策

采用 Flyway 作为数据库迁移工具,JPA ddl-auto 设置为 validate。

理由

  • Flyway 提供版本化 SQL 脚本管理
  • validate 模式确保代码与数据库结构一致,防止意外修改
  • 迁移脚本可版本控制,支持回滚和审计
  • 与 Spring Boot 深度集成,配置简单

后果

  • 表结构修改必须通过 SQL 迁移脚本
  • 开发环境首次启动需要执行 Flyway 迁移
  • 生产环境部署自动执行未执行的迁移脚本

ADR-002: 枚举类型存储为 VARCHAR

状态: 已接受
日期: 2026-06-23
决策者: zhuyongxin

背景

JPA 实体类使用 Java 枚举(FaultCategory、DiagnosisStatus、SourceType),数据库列类型为 VARCHAR,Hibernate 校验报错类型不匹配。

决策

在 JPA 实体中明确指定 columnDefinition = "VARCHAR":

@Enumerated(EnumType.STRING)
@Column(name = "fault_category", length = 32, columnDefinition = "VARCHAR(32)")
private FaultCategory faultCategory;

理由

  • MySQL 的 ENUM 类型限制灵活性(新增枚举值需要 ALTER TABLE)
  • VARCHAR 支持动态扩展枚举值
  • @Enumerated(EnumType.STRING) 存储枚举名称,可读性好
  • columnDefinition 明确告知 Hibernate 期望的数据库类型

后果

  • 数据库列存储字符串值(如 "EXTERNAL_API")
  • 枚举值修改不影响数据库结构
  • 需要在应用层校验枚举值合法性

ADR-003: Redis 会话管理采用 JSON 序列化

状态: 已接受
日期: 2026-06-23
决策者: zhuyongxin

背景

SessionContext 包含复杂对象(List、LocalDateTime),需要选择合适的序列化方案存储到 Redis。

决策

使用 GenericJackson2JsonRedisSerializer + JavaTimeModule:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.activateDefaultTyping(
    LaissezFaireSubTypeValidator.instance,
    ObjectMapper.DefaultTyping.NON_FINAL,
    JsonTypeInfo.As.PROPERTY
);

理由

  • JSON 格式可读性强,便于调试
  • 支持 Java 8 时间类型(LocalDateTime)
  • 支持多态反序列化(通过 @class 类型信息)
  • 跨语言友好(如需要其他服务读取 Redis 数据)

后果

  • Redis 中存储的是 JSON 字符串
  • 增加了 @class 元数据字段
  • 序列化性能略低于二进制方案(Kryo、Protobuf)
  • 对象结构变更需要考虑兼容性

ADR-004: Repository 方法遵循 Spring Data JPA 命名约定

状态: 已接受
日期: 2026-06-23
决策者: zhuyongxin

背景

Repository 需要提供多种查询方法(按 ID、按业务字段、按时间范围等),需要选择查询定义方式。

决策

使用 Spring Data JPA 方法命名约定,不手写 @Query:

Optional<DiagnosisRecord> findByDiagnosisId(String diagnosisId);
List<DiagnosisRecord> findByFaultCategoryAndErrorCode(FaultCategory category, String errorCode);
Page<DiagnosisRecord> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end, Pageable pageable);

理由

  • 方法名即查询语义,自解释
  • 无需手写 SQL/JPQL,减少语法错误
  • Spring Data JPA 自动生成查询实现
  • 支持分页、排序等高级特性

后果

  • 复杂查询(多表连接、子查询)需要手写 @Query
  • 方法名可能很长(多条件组合查询)
  • 依赖 Spring Data JPA 的命名解析规则

ADR-005: 会话 TTL 可配置,默认由调用方指定

状态: 已接受
日期: 2026-06-23
决策者: zhuyongxin

背景

不同场景的会话过期时间需求不同(短诊断 5 分钟,长会话 1 小时)。

决策

createSession 方法接受 ttlSeconds 参数,由调用方指定过期时间:

String createSession(SessionContext context, long ttlSeconds);

理由

  • 灵活控制不同场景的会话时长
  • 避免硬编码过期时间
  • 支持动态刷新(refreshSession 方法)

后果

  • 调用方需要明确指定 TTL
  • 需要在业务层统一管理 TTL 策略
  • Redis 自动清理过期会话,无需手动删除

ADR-006: 包名暂时混用,Task 4 统一重构

状态: 临时接受
日期: 2026-06-23
决策者: zhuyongxin

背景

  • 枚举类在 com.superbiz.agent.domain.enums
  • 新建实体类在 org.example.domain.entity
  • 新建 Repository 在 org.example.repository

决策

暂时通过跨包 import 解决编译问题,Task 4 统一重构为 com.superbiz.agent.*。

理由

  • Phase 1 重点是功能实现和测试验证
  • 包名重构涉及全局修改,风险较高
  • Task 4 专门负责代码结构重构,一次性解决

后果

  • 当前包名混乱,影响可维护性
  • IDE 导航和代码搜索不友好
  • Task 4 必须完成,否则技术债累积