Files
ecm_sync_system/docs/sync_flow.md
T
2026-03-20 14:38:56 +08:00

6.0 KiB
Raw Blame History

同步流程(pipeline -> strategy -> datasource

1. 全流程主线

  1. pipeline 装配组件并加载持久化。
  2. pipeline 为 datasource 绑定 collection,但不在 bootstrap 阶段全量拉取业务数据。
  3. pipeline 在每个 node_type 开始执行前,单独加载该 node_type 的最新数据。
  4. pipeline 调用 strategy.bind()
  5. pipeline 调用 strategy.create() / strategy.update() 生成动作节点。
  6. pipeline 调用 datasource.sync_all() 执行动作并回写执行状态。
  7. pipeline 输出统计并持久化。

2. reset 时序

2.1 加载时 resetphase1 语义)

  • common/collection.py::load_from_persistence() 执行。
  • 语义:仅恢复持久化状态(不在此阶段做状态归并)。

2.2 加载后 cleanupphase2 语义)

  • pipeline 调用 BaseSyncStrategy.run_reset()
  • 实际实现:strategy_ops/reset_ops.py::run_phase2_cleanup()
  • 核心事件:E01S16 -> S00/S15)。
  • S16 表示“持久化加载输入态”:本轮从持久化恢复出的节点集合(可包含上轮遗留节点,也可包含上轮已稳定节点)。
  • 判定:
    • is_create_zombie=true -> S15,节点删除(并尝试解绑);
    • is_create_zombie=false -> S00,节点归并为 UNCHECKED/NONE/PENDING 并清空 error

2.2.1 enable_persistence 与 bootstrap 关系

  • enable_persistence=true:先 load_from_persistence(),再对加载出的节点执行 E01S16 域内处理)。
  • enable_persistence=false:本轮没有持久化输入,S16/E01 不参与;随后 Stage1 新加载节点直接进入本轮 bind/create/update/sync 主流程。

2.3 加载异常隔离(S17

  • 持久化中若出现非法枚举值(action/status/binding_status),节点标记为 bootstrap_blockedS17 语义)。
  • 这类节点保留 error,用于人工排查。
  • 这类节点不会进入 E01,也不会参与 bind/create/update/sync 自动流程。

3. bind 流程(strategy_ops

  • 入口:strategy_ops/bind_ops.py::run_bind()
  • 入口状态:S00

核心绑定判定

  • phase_core_state() 内触发 E10
  • 有绑定记录:根据本端/对端有效性进入 S01/S03/S04
  • 无绑定记录:进入 S02

依赖检查

  • phase_dependency_check() -> check_dependencies_for_nodes() 内触发 E15
  • data_present=false -> S03
  • dep_satisfied=false -> S05
  • depend_fields 为空 -> S04(无法自动处理,阻断后续自动创建)。

自动绑定

  • phase_auto_binding() 内触发 E16
  • ONE_TO_ONE -> S01AMBIGUOUS/KEY_MISSING/DATA_MISSING -> S04KEY_ID_RESOLVE_FAIL -> S05
  • ZERO + create_enabled=true -> S13PEER_CREATING/NONE/PENDING,待对侧创建中间态);ZERO + create_enabled=false -> S04
  • auto_bind=false 时,E16 直接落 S04(自动绑定未启用),不会进入自动创建路径。

4. create/update 准备

create

  • 入口:strategy_ops/create_ops.py::run_create()
  • 运行时事件:E20E21/E22 为配置保留分支,当前 strategy 未接入自动执行)
  • 运行时入口状态:S13
  • 说明:E16 负责识别“需自动创建”并将源节点置为 S13;业务代码执行对侧 spawn+bind 后,再通过 E20S13 提交到 S01(成功);若 spawn 失败,E20 不迁移并保留在 S13 等待人工/重试。
  • data_id 约束:
    • S13/S01 要求源节点 data_id 存在(data_id_exist=true)。
    • 新创建目标节点在 S06/S10C 阶段允许 data_id 为空;CREATE SUCCESSS11C)必须携带非空 result_data_id,否则事件直接报错。

update

  • 入口:strategy_ops/update_ops.py::run_update()
  • 事件:E30
  • 入口状态(source 节点):S01
  • target_has_data_id=falseupdate_id_resolve_ok=false -> S08
  • has_diff=true -> S07

post-create 归并

  • 入口:pipeline/full_sync_pipeline.py::normalize_create_success_to_update_entry()
  • 事件:E41
  • 语义:CREATE 执行成功后,节点先落 S11CSUCCESS),再归并 S11C -> S01,作为同轮 update 起点。

5. 执行回写(datasource

  • 入口:datasource/datasource.py
  • 事件:E40C_START/E40CE40U_START/E40UE40D_START/E40D
  • 当前约束:delete stage 尚未接入 strategy 主流程;若运行时检测到 S09/DELETE 节点,DataSource 会显式抛错阻断(避免散落删除执行)。
  • 执行准备入口状态:
    • CREATE: S06
    • UPDATE: S07
    • DELETE: S09
  • S10 为执行中状态(由本轮执行产生),执行流转固定为“入口 -> S10 -> 终态”,不再出现入口直接到成功/失败。
  • 结果:
    • SUCCESS -> S11C | S11U | S11D(按动作)
    • FAILED -> S12C | S12U | S12D(按动作)
    • IN_PROGRESS -> S10C | S10U | S10D(按动作,支持异步 polling 闭环)
    • SKIPPED + action=UPDATE -> S14

6. 各阶段入口状态总表

阶段 入口状态 说明
Reset(E01) S16 create_zombie -> S15;其余 -> S00
Bind(E10/E15/E16) S00 bind 三段统一从 S00 进入
Create Prepare(E20/E21/E22) S02 / S13 配置入口含 S02/S13;当前 strategy 运行时只处理 S13E20 提交,S02 分支保留未接入
Post-create Ready(E41) S11C CREATE 成功节点归并到 S01,进入同轮 update
Update Prepare(E30) S01 仅从 NORMAL 继续判定(create 成功先经 E41 归并)
Sync Execute(E40C/U/D) S06 / S07 / S09 / S10C / S10U / S10D 执行与回写:按动作分事件;入口先进入 S10*,再由 S10* 进入 S11*/S12*;轮询返回 IN_PROGRESS 时只记录任务进度,不新增状态迁移;仅 UPDATE 可走 S14
隔离(人工) S17 不参与自动阶段,仅人工处理

7. 不变量保障

  • 每次事件落地后,engine/events.py::_apply_decision() 会执行 runtime.check_invariants()
  • 违反 invariant 直接抛错,终止当前路径。