Files
ecm_sync_system/docs/archive/from_root_docs/编排流程规范.md
T
strepsiades 4a9c444b10 first commit
2026-03-09 16:31:42 +08:00

23 KiB
Raw Blame History

同步编排流程规范 (Pipeline Specification)

本文档定义了完整的同步编排流程,包括各阶段的职责、节点状态转换和检查点。

详细的状态定义和转换规则,请参考: STATE_DEFINITIONS.md


流程概览

同步系统的完整执行流程分为 5 个阶段:

┌─────────────────────────────────────────────────────────────┐
│ Stage 0: 初始化 (Initialization)                            │
├─────────────────────────────────────────────────────────────┤
│ - 创建 Collection (Local/Remote)                            │
│ - 创建 BindingManager                                       │
│ - 注册 SyncStrategy (各业务类型)                            │
│ - 创建 DataSource (Local/Remote)                            │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ Stage 1: 数据加载 (Data Loading)                            │
├─────────────────────────────────────────────────────────────┤
│ 节点状态: binding_status=UNCHECKED, action=NONE, status=PENDING │
│ - Persistence.load_nodes() → 从持久化恢复                   │
│ - DataSource.load_all() → 从数据源加载                      │
│ - BindingManager.load_bindings() → 加载绑定关系             │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ Stage 2 & 3: 策略执行与同步 (按 node_type 顺序)              │
├─────────────────────────────────────────────────────────────┤
│ For each node_type in sync_order:                         │
│   ┌─────────────────────────────────────────────────┐      │
│   │ 2.1 bind()          → 绑定判定                  │      │
│   │ 2.2 create()        → 设置 CREATE action        │      │
│   │     └─ 内联 ID 解析 + 前置检查              │      │
│   │ 2.3 Commit Creates  → 立即同步 CREATE 节点      │      │
│   │     └─ DataSource.sync_all(poll_async=True)     │      │
│   │ 2.4 update()        → 设置 UPDATE action        │      │
│   │     └─ 内联 ID 解析 + 前置检查              │      │
│   │ 2.5 Commit Updates  → 立即同步 UPDATE 节点      │      │
│   │     └─ DataSource.sync_all(poll_async=True)     │      │
│   └─────────────────────────────────────────────────┘      │
│                                                             │
│ 说明:                                                       │
│ - 每个 node_type 完整同步后才处理下一个(保证依赖顺序)      │
│ - commit 操作内部包含异步轮询,无需独立轮询阶段              │
│ - sync_all() 自动过滤 action=CREATE/UPDATE 的节点           │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ Stage 4: 同步结果报告 (Summary Report)                   │
├─────────────────────────────────────────────────────────────┤
│ - 打印同步结果摘要                                         │
│   * 节点统计(按 action/status 分类)                         │
│   * 绑定关系统计                                             │
│   * 异常节点检查(data_id 缺失、绑定缺失等)         │
│ - 收集统计信息(成功/失败/残留问题)                       │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ Stage 5: 状态持久化 (State Persistence)                     │
├─────────────────────────────────────────────────────────────┤
│ - Collection.persist() → 保存节点状态                       │
│ - BindingManager.persist() → 保存绑定关系                   │
└─────────────────────────────────────────────────────────────┘
                            ↓
                      【流程完成】

各阶段节点状态

Stage 0: 初始化

输出: 所有组件实例化完成。


Stage 1: 数据加载

节点状态:

binding_status = BindingStatus.UNCHECKED  # 未判定
action = SyncAction.NONE                  # 无动作
status = SyncStatus.PENDING               # 待处理
data_id = <从数据源加载>                   # 已有业务ID
origin_data = <从数据源加载>               # 原始数据快照
data = <从数据源加载>                      # 当前数据
depend_ids = <从数据源加载>                # 依赖节点列表

关键点:

  • data_id 在加载时必定有值(来自数据源)
  • 只有待创建的新节点 data_id 才可能为 ""(空字符串)
  • 从持久化恢复时应重置所有 actionNONE
  • binding_status 初始值是 UNCHECKED,不是 None

Stage 2.1: Bind (状态判定)

状态转换: binding_status: UNCHECKED → NORMAL/MISSING/ABNORMAL/WARNING/DEPENDENCY_ERROR

可能的结果状态:

结果状态 含义 占比
NORMAL 有绑定,数据健康 大部分
MISSING 无绑定,孤儿节点 少量
ABNORMAL 有绑定,自身数据损坏 极少
WARNING 有绑定,对方数据损坏 极少
DEPENDENCY_ERROR 依赖未满足 少量

详细规则: 参考 STATE_DEFINITIONS.md § 1-3

补充约束:

  • 若依赖节点 binding_status = NORMALdata_id 为空(含 status = FAILED),视为依赖阻断。
  • 只要依赖节点已回填 data_id,即使其 status = FAILED,后续类型仍允许进入 Create/Update。
  • 自动绑定只在业务键完整且唯一时才尝试:
    • 若业务键字段缺失(如 serial_number = null),设置 binding_status = WARNING,并在 node.error 记录原因:Auto-bind skipped: missing fields ...
    • 若同一业务键出现多对多/多对一,设置 binding_status = WARNING,并在 node.error 记录原因:Auto-bind skipped: ambiguous candidates
    • 以上情况仅记录 Warning,不进行自动绑定。

Stage 2.2: Create (孤儿处理)

状态转换: action: NONE → CREATE (对 MISSING 节点)

补充约束:

  • binding_status = WARNING 的节点不会进入 CREATEcreate() 只查找 MISSING 节点)
  • 创建时会通过 IDResolver.resolve_and_validate() 二次验证依赖 ID,失败则设置 DEPENDENCY_ERROR

副作用:

  • 在对方 Collection 创建新节点
  • 新节点的 binding_status = NORMAL, action = CREATE, data_id = ""
  • 建立绑定记录
  • 原 MISSING 节点也变为 NORMAL

示例:

Before:
  local_node: binding_status=MISSING, action=NONE

After Create:
  local_node: binding_status=NORMAL, action=NONE
  remote_node (新建): binding_status=NORMAL, action=CREATE, data_id=""
  绑定记录: local_id ↔ remote_temp_id

Stage 2.3: Update (差异同步)

状态转换: action: NONE → UPDATE (对 NORMAL 且有差异的节点)

前提条件:

  • binding_status = NORMAL
  • status != FAILED(保护上次失败的状态和错误信息)
  • compute_diff() 判定有差异
  • 配置的 update_direction 决定哪一方节点设置 UPDATE

内联检查

  • 目标节点 data_id 为空 → status = PRECONDITION_FAILED
  • IDResolver.resolve_and_validate() 失败 → status = PRECONDITION_FAILED
  • Handler 校验后无实际变更字段 → action 降级为 NONE(不提交)

Stage 2 & 3: 策略执行与同步

执行顺序: 按 sync_order 顺序逐个处理 node_type

单个 node_type 的完整流程:

For node_type in sync_order:
  ┌─────────────────────────────────────────────┐
  │ 2.1 Bind - 绑定判定                         │
  │     - 设置 binding_status: NORMAL/MISSING/... │
  └─────────────────────────────────────────────┘
                    ↓
  ┌─────────────────────────────────────────────┐
  │ 2.2 Create - 创建策略                       │
  │     - 处理 MISSING 节点,设置 action=CREATE   │
  │     - 内联 ID 解析验证 (resolve_and_validate) │
  └─────────────────────────────────────────────┘
                    ↓
  ┌─────────────────────────────────────────────┐
  │ 2.3 Commit Creates - 立即同步 CREATE        │
  │     - DataSource.sync_all(poll_async=True)  │
  │     - 自动过滤 action=CREATE 的节点          │
  │     - 内部包含异步轮询(IN_PROGRESS→SUCCESS)│
  │     - ⭐ 执行 data_id 回填和绑定更新        │
  └─────────────────────────────────────────────┘
                    ↓
  ┌─────────────────────────────────────────────┐
  │ 2.4 Update - 更新策略                       │
  │     - 处理差异节点,设置 action=UPDATE       │
  │     - 内联 ID 解析验证 + data_id 检查       │
  │     - FAILED 节点自动跳过                  │
  └─────────────────────────────────────────────┘
                    ↓
  ┌─────────────────────────────────────────────┐
  │ 2.5 Commit Updates - 立即同步 UPDATE        │
  │     - DataSource.sync_all(poll_async=True)  │
  │     - 自动过滤 action=UPDATE 的节点          │
  │     - 内部包含异步轮询(IN_PROGRESS→SUCCESS)│
  └─────────────────────────────────────────────┘
                    ↓
              下一个 node_type

关键特性:

  1. 按类型顺序: 每个 node_type 完全同步后才处理下一个(保证依赖顺序)
  2. 立即提交: create/update 后立即同步,不等待所有策略执行完
  3. 内置轮询: sync_all(poll_async=True) 内部自动轮询异步任务
  4. data_id 回填: CREATE 成功后立即回填 data_id,下游依赖可用

同步状态转换:

同步接口(一步式):

action=CREATE, API 成功 → status=SUCCESS, data_id=<远程ID>
action=CREATE, API 失败 → status=FAILED, error=<错误信息>
action=UPDATE, API 成功 → status=SUCCESS
action=UPDATE, API 失败 → status=FAILED, error=<错误信息>
action=NONE → status=PENDING (不执行)

异步接口(两步式,内置轮询):

action=CREATE, 提交成功 → status=IN_PROGRESS, task_id=<任务ID>
status=IN_PROGRESS, 轮询中... → status=IN_PROGRESS (保持)
status=IN_PROGRESS, 轮询成功 → status=SUCCESS, data_id=<远程ID>
status=IN_PROGRESS, 轮询失败 → status=FAILED, error=<错误信息>
status=IN_PROGRESS, 超时 → status=FAILED, error="Timeout"

关键副作用(由 DataSource 在 sync_all 中执行):

  • CREATE 成功: data_id 从 "" 更新为远程分配的 ID,并回写 data 主键字段
  • CREATE 成功: 绑定记录从临时ID更新为真实ID
  • UPDATE 成功: origin_data 更新为当前 data
  • DELETE 成功: 移除绑定记录

skip_sync 处理:

  • 如果 strategy.skip_sync = True,跳过 create/update/commit 步骤
  • bind 步骤始终执行(用于状态判定)

详细规则: 参考 STATE_DEFINITIONS.md § 5


Stage 4: 同步结果报告

目标: 打印同步结果摘要,帮助用户了解同步情况

报告内容:

  1. 节点统计:按 node_type 统计各种 action/status 的节点数量
  2. 绑定关系:每个 node_type 的绑定记录数
  3. 异常检查:扫描并报告异常情况:
    • CREATE 成功但 data_id 为空(DataSource 回填失败)
    • CREATE 成功但绑定记录缺失
    • UPDATE/CREATE 失败的节点及错误原因

输出示例:

================================================================================
📊 Local Collection Summary
================================================================================
Node Type                 Bindings     Create          Update          Delete          None     Total          
--------------------------------------------------------------------------------
project                   5/5          0(0/0/0)        2(2/0/0)        0(0/0/0)        3        5(5/0/0)       
contract                  10/12        2(2/0/0)        5(5/0/0)        0(0/0/0)        5        12(12/0/0)     

注意: 此阶段不修改任何状态,仅作为信息展示。


Stage 5: 状态持久化

持久化内容:

  • binding_status, action, status 的最终值
  • data_id (可能在 CREATE 后更新)
  • error (如果失败)
  • 绑定关系的完整映射

错误处理策略

阶段 失败类型 处理策略
Stage 0 初始化失败 终止流程,抛出异常
Stage 1 数据加载失败 终止流程,抛出异常
Stage 2 & 3 代码异常 终止流程,抛出异常
Stage 2: create/update 内联检查 依赖ID未解析、data_id缺失 继续流程,节点标记为 DEPENDENCY_ERROR 或 PRECONDITION_FAILED
Stage 2 & 3 API 调用失败 继续流程,标记节点 FAILED
Stage 4 - 总是继续,仅作为报告
Stage 5 持久化失败 记录错误,不影响内存状态

节点状态完整时间线

┌──────────────┬─────────────┬────────┬────────┬─────────┐
│ 阶段          │ binding_    │ action │ status │ data_id │
│              │ status      │        │        │         │
├──────────────┼─────────────┼────────┼────────┼─────────┤
│ 数据加载      │ UNCHECKED   │ NONE   │PENDING │ 已加载   │
│ Bind         │ NORMAL/...  │ NONE   │PENDING │ 已加载   │
│ Create       │ NORMAL      │ CREATE │PENDING │ ""*   │
│ Commit Create│ NORMAL      │ CREATE │SUCCESS │ 远程ID** │
│ Update       │ NORMAL      │ UPDATE │PENDING │ 已加载   │
│ Commit Update│ NORMAL      │ UPDATE │SUCCESS │ 已加载   │
└──────────────┴─────────────┴────────┴────────┴─────────┘

* 新创建的节点 data_id 初始为 ""
** CREATE 成功后 data_id 立即更新为远程分配的ID,下游依赖可用

配置驱动的流程控制

跳过某些阶段

pipeline_config = {
    "skip_bind": False,          # 是否跳过 bind
    "skip_create": False,        # 是否跳过 create
    "skip_update": False,        # 是否跳过 update
    "skip_post_check": False,    # 是否跳过同步后检查
    "fail_on_warning": False,    # Pre-Check 时是否将 WARNING 视为失败
}

注意skip_pre_check 已移除,原 _pre_commit_check 逻辑已内联到 create/update 方法中。


### 策略预设应用

```python
# 首次同步:启用自动绑定,双向创建
for strategy in strategies:
    strategy.apply_preset("first_sync")

# 日常同步:仅推送更新
for strategy in strategies:
    strategy.apply_preset("push_only")

幂等性保证

要求: 同一个 Collection 的多次同步应该是幂等的。

设计保证:

  1. Bind 阶段: 基于绑定记录判定,已绑定节点不会重复绑定
  2. Create 阶段: 已有绑定的节点 (NORMAL) 不会重复创建
  3. Update 阶段: 基于 compute_diff() 判定,无差异则不执行
  4. Sync 阶段: action=NONE 的节点跳过执行

前提条件:

  • 绑定记录正确持久化
  • 节点的 binding_status 正确保存和加载
  • compute_diff() 逻辑准确

监控和日志

关键指标

指标 含义 阶段
nodes_loaded 加载的节点总数 Stage 1
nodes_normal NORMAL 状态节点数 Stage 2.1
nodes_missing MISSING 状态节点数 Stage 2.1
nodes_abnormal ABNORMAL+WARNING 节点数 Stage 2.1
nodes_dep_error DEPENDENCY_ERROR 节点数 Stage 2.1
actions_create CREATE 动作节点数 Stage 2.2
actions_update UPDATE 动作节点数 Stage 2.3
sync_success 同步成功节点数 Stage 3
sync_failed 同步失败节点数 Stage 3
success_rate 成功率 (success/total) Stage 4

日志级别

INFO:  流程阶段切换、统计信息
DEBUG: 节点级别的详细操作
WARN:  检查发现的警告、同步失败
ERROR: 检查发现的错误、致命异常

参考文档

1. 持久化 Collection

await local_collection.persist() await remote_collection.persist()

2. 持久化 Binding

await binding_manager.persist()


**持久化内容**:
- 节点的 `binding_status`, `action`, `status`, `error`
- 节点的 `data_id`(可能在 CREATE 后更新)
- 绑定关系的完整映射

---

## 错误处理策略

### 各阶段的失败处理

| 阶段 | 失败原因示例 | 处理策略 |
|------|------------|---------|
| Stage 1: 数据加载 | 网络错误、文件缺失 | **终止流程**,抛出异常 |
| Stage 2.1: Bind | 代码bug | **终止流程**,抛出异常 |
| Stage 2.2-2.3: Create/Update | 代码bug | **终止流程**,抛出异常 |
| Stage 2: create/update 内联检查 | 依赖ID未解析、data_id缺失 | **继续流程**,节点标记为 DEPENDENCY_ERROR 或 PRECONDITION_FAILED |
| Stage 3: Physical Sync | API错误、权限不足 | **继续流程**,标记节点为 FAILED |
| Stage 4: Post-Sync Check | 部分节点同步失败 | **继续流程**,打印警告 |
| Stage 5: Persistence | 磁盘满、权限错误 | **记录错误**,但不影响内存状态 |

### 部分成功的处理

在 Stage 3 中,允许部分节点成功、部分失败:
- 成功的节点: `status = SUCCESS`
- 失败的节点: `status = FAILED`, `error = "错误信息"`

Post-Sync Check 会统计成功率并给出警告。

---

## 配置驱动的流程控制

### 跳过某些阶段

通过配置控制哪些阶段执行:

```python
pipeline_config = {
    "skip_bind": False,          # 是否跳过 bind
    "skip_create": False,        # 是否跳过 create
    "skip_update": False,        # 是否跳过 update
    "skip_post_check": False,    # 是否跳过同步后检查
    "fail_on_warning": False,    # 是否将 WARNING 也视为失败
}

策略预设应用

在 Stage 2 之前,可以应用策略预设:

# 首次同步:启用自动绑定,双向创建
for strategy in strategies:
    strategy.apply_preset("first_sync")

# 日常同步:仅推送更新
for strategy in strategies:
    strategy.apply_preset("push_only")

监控和日志

关键指标

在各阶段收集以下指标:

指标 含义
nodes_loaded 加载的节点总数
nodes_bound 成功绑定的节点数
nodes_missing MISSING 状态的节点数
nodes_abnormal ABNORMAL/WARNING 状态的节点数
nodes_created CREATE 动作的节点数
nodes_updated UPDATE 动作的节点数
sync_success 同步成功的节点数
sync_failed 同步失败的节点数
errors_count 检查发现的 ERROR 数量
warnings_count 检查发现的 WARNING 数量

日志级别

INFO:  流程阶段切换、统计信息
DEBUG: 节点级别的详细操作
WARN:  检查发现的警告
ERROR: 检查发现的错误、异常

幂等性保证

要求: 同一个 Collection 的多次同步应该是幂等的。

设计保证:

  1. Bind 阶段: 基于绑定记录判定状态,已绑定的节点不会重复绑定
  2. Create 阶段: 已有绑定的节点(NORMAL)不会重复创建
  3. Update 阶段: 基于 compute_diff() 判定,无差异则不执行
  4. Sync 阶段: DataSource 根据 action 执行,action=NONE 的节点跳过

前提条件:

  • Binding 记录正确持久化
  • 节点的 binding_status 正确保存和加载
  • compute_diff() 逻辑准确

下一步

详细的检查规范和状态转换规则,请参考: