216 lines
13 KiB
Markdown
216 lines
13 KiB
Markdown
# 会话记录:从库数据源注解实现
|
||
|
||
## 元数据
|
||
- 需求编号:2026-01-24-003
|
||
- 创建时间:2026-01-24
|
||
- 创建人:SSOT 架构师
|
||
- 状态:进行中
|
||
|
||
## 阶段执行记录
|
||
|
||
### 阶段 1:需求定义
|
||
- **状态**:已完成
|
||
- **需求文档**:[2026-01-24-003-从库数据源注解实现.md](../requirements/2026-01-24-003-从库数据源注解实现.md)
|
||
- **关键决策**:
|
||
- 使用现有的 `@DataSource` 注解和 `DataSourceType.SLAVE` 枚举
|
||
- 在 `DataSourceAspect` 切面中添加简单的路由逻辑
|
||
- 从 `SalesforceConfigCacheManager` 获取当前激活环境
|
||
- 根据当前激活环境的编码,构造从库数据源名称(如 `slave_dev`)
|
||
- 如果从库数据源不存在,回退到主库数据源
|
||
- 为 4 个 public 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
|
||
### 阶段 2:方案设计
|
||
- **状态**:已完成
|
||
- **设计文档**:[2026-01-24-003-从库数据源注解实现.md](../design/2026-01-24-003-从库数据源注解实现.md)
|
||
- **关键设计决策**:
|
||
- **系统架构**:使用现有的 `@DataSource` 注解和 `DataSourceAspect` 切面,通过简单的路由逻辑实现从库数据源的自动切换
|
||
- **模块架构**:涉及 `datai-common`、`datai-framework`、`datai-scenes-datai-scene-salesforce-datai-salesforce-setting`、`datai-scenes-datai-scene-salesforce-datai-salesforce-integration` 四个模块
|
||
- **数据流**:Controller → Service → DataSourceAspect → SalesforceConfigCacheManager → DataSourceManager → Database
|
||
- **技术选型**:Spring AOP、Spring Framework、AspectJ、MyBatis Plus、Druid、Lombok
|
||
- **核心算法**:数据源路由算法,时间复杂度 O(1),空间复杂度 O(1)
|
||
- **集成方案**:与 `SalesforceConfigCacheManager`、`DataSourceManager`、`DynamicDataSourceContextHolder` 集成
|
||
- **异常处理**:所有异常都应该被捕获并记录日志,从库数据源切换失败时,自动回退到主库数据源
|
||
- **性能优化**:利用 `SalesforceConfigCacheManager` 和 `DataSourceManager` 的缓存机制,避免频繁的数据源切换
|
||
- **安全设计**:确保从库数据源的访问权限正确配置,防止数据源切换导致的数据泄露
|
||
- **需要添加注解的方法**:8 个 public 方法,涵盖表结构创建、元数据同步、对象数据写入、实时同步
|
||
|
||
### 阶段 3:方案决策
|
||
- **状态**:已完成
|
||
- **决策文档**:[2026-01-24-003-从库数据源注解实现-技术选型.md](../decisions/adr/2026-01-24-003-从库数据源注解实现-技术选型.md)
|
||
- **关键决策**:
|
||
- **采用方案**:扩展 @DataSource 注解 + DataSourceAspect 动态路由
|
||
- **技术方案**:修改 DataSourceAspect 切面,添加动态路由逻辑,从 SalesforceConfigCacheManager 获取当前激活环境编码,构造从库数据源名称,检查从库是否存在,存在则切换到从库,不存在则回退到主库
|
||
- **备选方案**:
|
||
- 方案一:扩展 @DataSource 注解 + DataSourceAspect 动态路由(已选择)
|
||
- 方案二:创建新的 @EnvironmentSlave 注解(未选择)
|
||
- 方案三:在 Service 层手动切换数据源(未选择)
|
||
- 方案四:使用自定义注解 + 自定义数据源路由器(未选择)
|
||
- **影响分析**:系统架构、开发流程、运维管理、性能等方面的影响分析
|
||
- **风险评估**:技术风险、业务风险、实施风险的识别和缓解措施
|
||
- **验收标准**:功能验收、性能验收、日志验收、测试验收
|
||
|
||
### 阶段 4:数据库结构
|
||
- **状态**:已完成
|
||
- **关键决策**:
|
||
- 本需求不涉及数据库表结构的修改,不需要创建新的数据表
|
||
- 不需要生成 SQL 脚本
|
||
|
||
### 阶段 5:提示词生成
|
||
- **状态**:已完成
|
||
- **提示词文档**:[2026-01-24-003-prompt-从库数据源注解实现.md](../prompts/2026-01-24-003-prompt-从库数据源注解实现.md)
|
||
- **关键内容**:
|
||
- **目标**:基于现有的 `@DataSource` 注解和 `DataSourceAspect` 切面,实现从库数据源的动态切换功能
|
||
- **输出格式**:Java 代码、代码文件路径和文件名、修改说明、测试建议
|
||
- **约束**:技术栈限制、性能要求、安全性要求、兼容性要求、代码规范、异常处理
|
||
- **Rule Set**:必须使用 Canvas 中定义的类名和方法名、必须遵循 Canvas 中定义的调用关系、必须参考 Canvas 中的流程图逻辑等 18 条具体规则
|
||
- **验收标准**:功能完整性、代码正确性、文档准确性、性能指标
|
||
- **风险**:输出质量风险、技术实现风险、时间成本风险、其他潜在风险
|
||
|
||
### 阶段 6:代码生成
|
||
- **状态**:已完成
|
||
- **代码修改**:
|
||
- **DataSourceAspect.java**:
|
||
- 文件路径:`d:\idea_demo\datai\datai-framework\src\main\java\com\datai\framework\aspectj\DataSourceAspect.java`
|
||
- 修改内容:
|
||
- 修改 `around` 方法,当检测到 `DataSourceType.SLAVE` 时,调用 `getCurrentEnvironmentSlaveDataSourceName()` 方法
|
||
- 添加 `getCurrentEnvironmentSlaveDataSourceName()` 方法,实现动态路由逻辑
|
||
- 添加 `getCurrentEnvironmentCode()` 方法,通过反射从 `SalesforceConfigCacheManager` Bean 中获取当前激活环境编码
|
||
- 实现逻辑:通过反射调用 `SalesforceConfigCacheManager.getCurrentEnvironmentCode()` 方法获取当前激活环境编码,构造从库数据源名称,检查从库是否存在,存在则切换到从库,不存在则回退到主库
|
||
|
||
- **DataiIntegrationObjectServiceImpl.java**:
|
||
- 文件路径:`d:\idea_demo\datai\datai-scenes\datai-scene-salesforce\datai-salesforce-integration\src\main\java\com\datai\integration\service\impl\DataiIntegrationObjectServiceImpl.java`
|
||
- 修改内容:
|
||
- 添加 `@DataSource` 和 `DataSourceType` 导入
|
||
- 为 `createObjectStructure(Integer id)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
- 为 `syncSingleObjectData(Integer id)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
- 为 `syncMultipleObjectData(Integer[] ids)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
|
||
- **DataiIntegrationBatchServiceImpl.java**:
|
||
- 文件路径:`d:\idea_demo\datai\datai-scenes\datai-scene-salesforce\datai-salesforce-integration\src\main\java\com\datai\integration\service\impl\DataiIntegrationBatchServiceImpl.java`
|
||
- 修改内容:
|
||
- 添加 `@DataSource` 和 `DataSourceType` 导入
|
||
- 为 `syncBatchData(Integer id)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
|
||
- **DataiIntegrationMetadataChangeServiceImpl.java**:
|
||
- 文件路径:`d:\idea_demo\datai\datai-scenes\datai-scene-salesforce\datai-salesforce-integration\src\main\java\com\datai\integration\service\impl\DataiIntegrationMetadataChangeServiceImpl.java`
|
||
- 修改内容:
|
||
- 添加 `@DataSource` 和 `DataSourceType` 导入
|
||
- 为 `syncToLocalDatabase(Long id)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
- 为 `syncBatchToLocalDatabase(Long[] ids)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
|
||
- **DataSynchronizerImpl.java**:
|
||
- 文件路径:`d:\idea_demo\datai\datai-scenes\datai-scene-salesforce\datai-salesforce-integration\src\main\java\com\datai\integration\realtime\impl\DataSynchronizerImpl.java`
|
||
- 修改内容:
|
||
- 添加 `@DataSource` 和 `DataSourceType` 导入
|
||
- 为 `synchronizeData(String objectType, String recordId, String changeType, Map<String, Object> changeData, Date changeDate)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
- 为 `batchSynchronizeData(List<SyncData> syncDataList)` 方法添加 `@DataSource(DataSourceType.SLAVE)` 注解
|
||
|
||
- **测试建议**:
|
||
- 测试从库数据源存在时,成功切换到从库数据源
|
||
- 测试从库数据源不存在时,成功回退到主库数据源
|
||
- 测试环境编码为空时,成功回退到主库数据源
|
||
- 测试数据源切换时间 < 10ms
|
||
- 测试不影响业务方法的执行时间
|
||
|
||
### 阶段 7:会话记录
|
||
- **状态**:已完成
|
||
- **记录内容**:
|
||
- 记录了从库数据源注解实现的完整开发过程
|
||
- 记录了代码修改的详细信息和测试建议
|
||
- 记录了技术实现的关键决策和优化过程
|
||
- 记录了反射调用 `SalesforceConfigCacheManager` 的实现方式
|
||
- 记录了性能优化的具体措施(缓存 Bean 和 Method 对象)
|
||
|
||
### 阶段 8:变更日志
|
||
- **状态**:已完成
|
||
- **变更日志文档**:[2026-01-24-003-changelog.md](../changelogs/2026-01-24-003-changelog.md)
|
||
- **关键内容**:
|
||
- 记录了从库数据源注解实现的完整变更信息
|
||
- 记录了 DataSourceAspect 动态路由的实现细节
|
||
- 记录了 8 个方法的注解添加情况
|
||
- 记录了技术特性、测试建议、兼容性说明、风险评估和后续优化建议
|
||
|
||
### 阶段 9:闭环复盘和接口文档
|
||
- **状态**:已完成
|
||
- **复盘文档**:[2026-01-24-003-retro.md](../retros/2026-01-24-003-retro.md)
|
||
- **关键内容**:
|
||
- 总结了从库数据源注解实现的完整开发过程
|
||
- 分析了成功经验、改进点和问题
|
||
- 制定了行动计划,旨在提高后续开发的效率和质量
|
||
- 提取了有效的 Prompt 技巧和避免的坑
|
||
- 对比了目标与实际产出,确认所有目标都已实现
|
||
- **API 文档**:[2026-01-24-003-api-从库数据源注解实现.md](../api-docs/integration/2026-01-24-003-api-从库数据源注解实现.md)
|
||
- **关键内容**:
|
||
- 记录了 8 个修改的内部方法
|
||
- 记录了数据源切换逻辑、性能优化和降级机制
|
||
- 记录了数据源命名规则和事务支持
|
||
- 记录了使用示例和注意事项
|
||
|
||
### 阶段 10:代码提交
|
||
- **状态**:已完成
|
||
- **提交信息**:
|
||
- Commit ID:2d8f9c0aa240aa45dcf47438bcce36dbc13b3b62
|
||
- Commit Message:feat: 实现从库数据源注解功能 (REQ-003)
|
||
- 变更统计:23 files changed, 2036 insertions(+), 307 deletions(-)
|
||
- **提交内容**:
|
||
- 扩展 @DataSource 注解,支持从库数据源的动态切换
|
||
- 在 DataSourceAspect 切面中添加动态路由逻辑,通过反射调用 SalesforceConfigCacheManager.getCurrentEnvironmentCode() 方法获取当前激活环境编码
|
||
- 构造从库数据源名称(slave_环境编码),检查从库是否存在,存在则切换到从库,不存在则回退到主库
|
||
- 缓存 SalesforceConfigCacheManager Bean 和 getCurrentEnvironmentCode Method 对象,优化性能
|
||
- 为 8 个方法添加 @DataSource(DataSourceType.SLAVE) 注解
|
||
- 创建需求文档、设计文档、决策记录、提示词文档、会话记录、变更日志、复盘文档和 API 文档
|
||
- 更新 CHANGELOG.md 和索引文档
|
||
|
||
## 关键技术点
|
||
|
||
### 1. @DataSource 注解
|
||
- 位置:`com.datai.common.annotation.DataSource`
|
||
- 支持枚举方式:`DataSourceType.MASTER` 或 `DataSourceType.SLAVE`
|
||
- 支持字符串方式:直接指定数据源名称
|
||
- 优先级:方法上的注解优先于类上的注解
|
||
|
||
### 2. DataSourceType 枚举
|
||
- 位置:`com.datai.common.enums.DataSourceType`
|
||
- 包含:`MASTER`、`SLAVE`
|
||
|
||
### 3. DataSourceAspect 切面
|
||
- 位置:`com.datai.framework.aspectj.DataSourceAspect`
|
||
- 需要修改:添加 `SalesforceConfigCacheManager` 依赖注入,添加 `getCurrentEnvironmentSlaveDataSourceName` 方法
|
||
|
||
### 4. SalesforceConfigCacheManager
|
||
- 位置:`com.datai.setting.config.SalesforceConfigCacheManager`
|
||
- 方法:`getCurrentEnvironmentCode()` - 获取当前激活环境编码
|
||
|
||
### 5. DataSourceManager
|
||
- 位置:`com.datai.framework.manager.DataSourceManager`
|
||
- 方法:`isDataSourceLoaded(String dsName)` - 检查数据源是否已加载
|
||
|
||
### 6. DynamicDataSourceContextHolder
|
||
- 位置:`com.datai.framework.datasource.DynamicDataSourceContextHolder`
|
||
- 方法:`setDataSourceType(String dsType)` - 设置数据源类型
|
||
- 方法:`clearDataSourceType()` - 清除数据源类型
|
||
- 特性:使用 ThreadLocal 维护数据源变量,支持嵌套数据源切换(使用 Stack 结构)
|
||
|
||
## 需要使用从库的方法列表
|
||
|
||
### DataiIntegrationObjectServiceImpl
|
||
- `createObjectStructure(Integer id)` - 创建对象表结构
|
||
- `syncSingleObjectData(Integer id)` - 同步单个对象数据
|
||
- `syncMultipleObjectData(Integer[] ids)` - 同步多个对象数据
|
||
|
||
### DataiIntegrationBatchServiceImpl
|
||
- `syncBatchData(Integer id)` - 同步批次数据
|
||
|
||
### DataiIntegrationMetadataChangeServiceImpl
|
||
- `syncToLocalDatabase(Long id)` - 同步元数据变更到本地数据库
|
||
- `syncBatchToLocalDatabase(Long[] ids)` - 批量同步元数据变更到本地数据库
|
||
|
||
### DataSynchronizerImpl
|
||
- `synchronizeData(String objectType, String recordId, String changeType, Map<String, Object> changeData, Date changeDate)` - 同步实时数据
|
||
- `batchSynchronizeData(List<SyncData> syncDataList)` - 批量同步实时数据
|
||
|
||
## 相关文档
|
||
|
||
- [需求文档](../requirements/2026-01-24-003-从库数据源注解实现.md)
|
||
- [设计文档](../design/2026-01-24-003-从库数据源注解实现.md)
|