23 KiB
同步编排流程规范 (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才可能为 ""(空字符串) - 从持久化恢复时应重置所有
action为NONE 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 = NORMAL但data_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的节点不会进入 CREATE(create()只查找 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 = NORMALstatus != 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
关键特性:
- 按类型顺序: 每个 node_type 完全同步后才处理下一个(保证依赖顺序)
- 立即提交: create/update 后立即同步,不等待所有策略执行完
- 内置轮询:
sync_all(poll_async=True)内部自动轮询异步任务 - 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: 同步结果报告
目标: 打印同步结果摘要,帮助用户了解同步情况
报告内容:
- 节点统计:按 node_type 统计各种 action/status 的节点数量
- 绑定关系:每个 node_type 的绑定记录数
- 异常检查:扫描并报告异常情况:
- 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 的多次同步应该是幂等的。
设计保证:
- Bind 阶段: 基于绑定记录判定,已绑定节点不会重复绑定
- Create 阶段: 已有绑定的节点 (NORMAL) 不会重复创建
- Update 阶段: 基于
compute_diff()判定,无差异则不执行 - 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: 检查发现的错误、致命异常
参考文档
- STATE_DEFINITIONS.md - 详细的状态定义和转换规则
- CHECK_SPEC.md - 检查点的实现细节和代码示例(可选)
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 的多次同步应该是幂等的。
设计保证:
- Bind 阶段: 基于绑定记录判定状态,已绑定的节点不会重复绑定
- Create 阶段: 已有绑定的节点(NORMAL)不会重复创建
- Update 阶段: 基于
compute_diff()判定,无差异则不执行 - Sync 阶段: DataSource 根据
action执行,action=NONE的节点跳过
前提条件:
- Binding 记录正确持久化
- 节点的
binding_status正确保存和加载 compute_diff()逻辑准确
下一步
详细的检查规范和状态转换规则,请参考:
- CHECK_SPEC.md - 检查点详细规范
- STATE_TRANSITIONS.md - 状态转换表