section-sync-orchestration.md 7.5 KB

Section 同步改造后的调用链路

一、目标说明

本次改造将 section 同步从“controller 直接调用专用批处理 service”的方式,收敛为“controller + 公共编排 service + 业务处理器”的统一批量同步架构。

目标收益:

  • 统一批次校验、分片、并发、错误归集和状态汇总逻辑
  • 业务类只保留 section 专属的校验、映射和单分片下发逻辑
  • 为后续 course/classroom 等同步类型复用同一套编排链路

二、改造后的主调用链

1. HTTP 入口

文件:ruoyi-server/ruoyi-server-sync/src/main/java/org/dromara/server/sync/controller/SyncReceiveController.java

入口方法:

  • syncSections(BatchSyncRequest<SectionRecordRequest> request)

职责:

  1. 接收 /api/sync/receive/sections 请求
  2. 设置 request.businessType = SyncResourceConstants.SECTION
  3. 调用 CommonBatchSyncService.sync(request)
  4. 返回 BatchSyncResult

2. 公共批量编排层

文件:ruoyi-server/ruoyi-server-sync/src/main/java/org/dromara/server/sync/business/batch/CommonBatchSyncService.java

主方法:

  • sync(BatchSyncRequest<T> request)

职责:

  1. 校验 requestrecords
  2. 根据 businessType 获取业务处理器
  3. 创建批次记录 SyncBatchTrackerService.start(...)
  4. 逐条校验并转换记录
  5. 收集校验失败错误
  6. 将有效记录按 100 条分片
  7. 单片串行执行,多片按每轮最多 5 片并发执行
  8. 聚合所有分片的成功数与错误明细
  9. 保存错误明细并结束批次
  10. 返回统一 BatchSyncResult

关键内部方法:

  • getHandler(...):根据 businessType 获取处理器
  • partition(...):按固定大小切分分片
  • executeChunks(...):执行分片,同步或并发
  • buildResult(...):构造最终返回结果
  • resolveStatus(...):计算批次状态

3. 业务处理器抽象

文件:ruoyi-server/ruoyi-server-sync/src/main/java/org/dromara/server/sync/business/batch/BatchSyncBusinessHandler.java

作用: 定义公共编排层与具体业务处理器之间的统一契约。

核心方法:

  • getBusinessType()
  • getApiName()
  • getResourceType()
  • resolveTenantId(...)
  • validateRecord(...)
  • getBizKey(...)
  • toDispatchDto(...)
  • dispatchChunk(...)

4. section 业务处理器

文件:ruoyi-server/ruoyi-server-sync/src/main/java/org/dromara/server/sync/business/batch/SectionBatchSyncService.java

注册方式:

  • @Service(SyncResourceConstants.SECTION)

实现接口:

  • BatchSyncBusinessHandler<SectionRecordRequest, RemoteSectionSyncBatchDto>

职责拆分:

  1. validateRecord(...)
    • 校验 section 单条记录的必填字段
  2. getBizKey(...)
    • 提取 sectionId 作为错误定位主键
  3. toDispatchDto(...)
    • 将请求对象转换为 RemoteSectionSyncBatchDto
  4. dispatchChunk(...)
    • 执行单个分片的远端 section 同步
    • 解析远端返回结果
    • 转换远端错误为本地 SyncBatchErrorRecord
  5. syncSections(...)
    • 兼容旧入口,内部委托给 CommonBatchSyncService

5. 远端 Dubbo 接口

接口文件:ruoyi-api/ruoyi-api-ecs/src/main/java/org/dromara/ecs/api/RemoteSectionSyncService.java

实现文件:ruoyi-modules/ruoyi-ecs/src/main/java/org/dromara/ecs/dubbo/RemoteSectionSyncServiceImpl.java

调用方法:

  • syncSectionBatch(List<RemoteSectionSyncBatchDto> records)

职责:

  1. 接收 server-sync 下发的 section 分片数据
  2. 转换为 ECS 内部 DTO
  3. 调用 ISyncSectionService.receiveSectionBatch(...)
  4. 返回远端批量处理结果 RemoteBatchSyncResultDto

6. ECS 内部同步服务

文件:ruoyi-modules/ruoyi-ecs/src/main/java/org/dromara/ecs/service/sync/SyncSectionServiceImpl.java

核心方法:

  • receiveSectionBatch(...)
  • processSection(...)

职责:

  1. 先处理 delFlag=1 的删除组
  2. 再处理 delFlag=0 的新增/修改组
  3. 单条处理时:
    • 删除组:按 otherId 更新删除标记
    • 非删除组:按 otherId 判断新增或修改

7. 持久化层

文件:

  • ruoyi-modules/ruoyi-ecs/src/main/java/org/dromara/ecs/service/impl/EcsSectionServiceImpl.java
  • ruoyi-modules/ruoyi-ecs/src/main/java/org/dromara/ecs/mapper/EcsSectionMapper.java

职责:

  • queryByOtherId(...):查询已存在记录
  • insertByBo(...):新增课表
  • updateByBo(...):更新课表
  • updateDelFlagByOtherId(...):按 otherId + tenantId 更新删除标记

三、改造后的完整执行时序

  1. 外部系统调用 /api/sync/receive/sections
  2. SyncReceiveController.syncSections(...)
  3. 设置 businessType = SECTION
  4. CommonBatchSyncService.sync(...)
  5. SpringUtils.getBean("SECTION", BatchSyncBusinessHandler.class) 获取 SectionBatchSyncService
  6. SyncBatchTrackerService.start(...) 创建批次
  7. 公共层逐条校验 section 数据并转换为 RemoteSectionSyncBatchDto
  8. 公共层按 100 条切分分片
  9. 单分片同步执行;多分片每轮最多 5 片并发执行
  10. 每个分片调用 SectionBatchSyncService.dispatchChunk(...)
  11. dispatchChunk(...) 调用 RemoteSectionSyncService.syncSectionBatch(...)
  12. RemoteSectionSyncServiceImpl.syncSectionBatch(...) 转内部 DTO 后调用 SyncSectionServiceImpl.receiveSectionBatch(...)
  13. ECS 内部完成删除/新增/修改处理
  14. 分片结果返回到公共层
  15. 公共层聚合 success/error
  16. SyncBatchTrackerService.saveErrors(...) 保存错误明细
  17. SyncBatchTrackerService.finish(...) 更新批次状态
  18. controller 返回 BatchSyncResult

四、当前分片与并发规则

CommonBatchSyncService 中约定:

  • CHUNK_SIZE = 100
  • MAX_PARALLEL_CHUNKS = 5

执行规则:

  • 只有 1 个分片:当前线程同步执行
  • 多于 1 个分片:按窗口执行,每轮最多并发 5 个分片
  • 并发线程池复用 threadPoolTaskExecutor

五、错误归集规则

错误来源分两类:

1. 校验失败

发生位置:公共编排层

处理方式:

  • 不进入远端调用
  • 直接通过 SyncBatchTrackerService.error(...) 构造 VALIDATION_ERROR

2. 业务失败 / 远端失败

发生位置:section 分片处理器或远端服务

处理方式:

  • 转换为 BIZ_ERROR
  • 统一归集为 SyncBatchErrorRecord
  • 最后由 SyncBatchTrackerService.saveErrors(...) 批量保存

六、改造后 section 相关关键类

server-sync 侧

  • SyncReceiveController
  • CommonBatchSyncService
  • BatchSyncBusinessHandler
  • SectionBatchSyncService
  • SyncBatchTrackerService
  • BatchSyncRequest
  • BatchSyncResult
  • BatchChunkSyncResult

api / ecs 侧

  • RemoteSectionSyncService
  • RemoteSectionSyncServiceImpl
  • SyncSectionServiceImpl
  • EcsSectionServiceImpl
  • EcsSectionMapper

七、当前实现的边界说明

  1. 这次只迁移了 section,同步类如 train/trainee 仍保持原有方式
  2. 并发后的事务边界是“单分片”,不是“整批”
  3. section 下游的删除语义没有改变,仍由 ECS 内部服务控制
  4. 公共编排层只负责批次通用逻辑,不介入 section 的具体业务规则

八、后续可复用扩展方式

如果后续要接入新的同步类型,如 courseclassroom

  1. SyncResourceConstants 中增加业务类型常量
  2. 新增对应的业务处理器,实现 BatchSyncBusinessHandler
  3. 在 controller 中设置 businessType
  4. 直接复用 CommonBatchSyncService.sync(...)

这样就不需要重复实现批次校验、分片、并发、错误归集和批次跟踪逻辑。