6.4 KiB
6.4 KiB
节点状态持久化与人工介入规范
代码实现:
sync_system_new/common/state_reset.py
1. 持久化规则
1.1 持久化目标
| 目标 | 说明 |
|---|---|
| 可恢复性 | 系统重启后能从上次状态继续 |
| 可观测性 | 失败和异常状态要保留,供人工查看 |
| 可追溯性 | 失败信息持久化,不自动重试,需人工确认 |
| 绑定稳定性 | 手工绑定一旦建立,永不自动改变 |
1.2 分阶段重置设计
状态重置分为两个阶段执行:
阶段1:加载时重置(Collection.load_from_persistence)
| 字段 | 性质 | 持久化 | 阶段1重置 |
|---|---|---|---|
node_id |
恒定标识 | ✅ 必须 | ❌ 不重置 |
data_id |
业务主键 | ✅ 必须 | ❌ 不重置 |
data |
业务数据 | ✅ 必须 | ✅ 重置(每次重新取数) |
origin_data |
原始快照 | ✅ 必须 | ✅ 重置(每次重新取数) |
depend_ids |
依赖列表 | ❌ 不持久化 | ✅ 初始化为[](bind 阶段从 data 实时计算) |
binding_status |
绑定状态 | ✅ 必须 | ✅ 重置为 UNCHECKED |
action |
同步意图 | ✅ 保存 | ❌ 保留(用于阶段2判断) |
status |
执行状态 | ✅ 保存 | ❌ 保留(全部保留,不重置) |
error |
错误信息 | ✅ 保存 | ✅ 重置为None(清空上次错误) |
context |
扩展上下文 | ✅ 保存 | ❌ 不重置 |
阶段2:数据加载后清理(Pipeline._cleanup_create_failed_zombies)
在数据加载完成后、策略执行前,执行CREATE失败节点清理:
-
检查条件:
- 本地节点
action == CREATE(上次尝试创建) - 本地节点
status == FAILED(创建失败)
- 本地节点
-
清理动作:
- 删除本地失败节点(从 collection 中移除)
- 如果有绑定记录:
- 解除绑定关系
- 删除远程 collection 中的僵尸节点
-
最后重置 action:
- 所有剩余节点的
action重置为 NONE - 准备进入策略阶段
- 所有剩余节点的
-
下次同步的自动恢复:
- 被删除的节点会从数据源重新加载
- 如果远程实际已创建成功(网络波动导致未获取到结果)→ 绑定阶段会自动绑定上
- 如果远程实际也失败了 → 重新尝试创建
-
UPDATE 阶段保护:
- UPDATE 操作会跳过所有
status == FAILED的节点 - 防止 UPDATE 阶段覆盖 CREATE/UPDATE 失败的状态和错误信息
- 确保失败节点的 action 和 error 信息保持不变,直到下次同步清理
- UPDATE 操作会跳过所有
说明:
data/origin_data:每次运行从数据源重新获取,保证数据最新depend_ids:不持久化,每次 bind 阶段从 data 的业务字段(如 contract_id, project_id)实时提取binding_status:持久化用于审计,加载时重置为UNCHECKED,由 bind() 重新判定error:阶段1清空,避免上次错误影响本次运行,新错误会在各阶段重新生成action:阶段1保留用于识别 CREATE 失败的节点,阶段2清理后重置status:阶段1全部保留(包括 FAILED、PRECONDITION_FAILED 等),不自动重置- CREATE 失败节点会被自动删除并重新加载,UPDATE/DELETE 失败保留需人工处理
- UPDATE 操作会跳过 FAILED 节点,避免覆盖失败状态和错误信息
1.3 绑定记录 vs binding_status
| 概念 | 存储位置 | 持久性 | 如何改变 |
|---|---|---|---|
| 绑定记录 | bindings 表 |
永久保留 | 只能手工 bind/unbind,或 CREATE 失败自动清理 |
| binding_status | nodes 表 |
保存但可重判 | 每次 bind() 重新判定 |
1.4 CREATE 失败的自动恢复
当 CREATE 操作失败时,会产生"僵尸绑定":
- 绑定记录已建立(local_id → remote_node_id)
- 但远程节点的
data_id为空(API 未返回真实 ID)
下次同步时的自动恢复流程:
- 阶段1加载:保留
action=CREATE - 阶段2清理:检测到僵尸绑定,自动清理
- 本地节点恢复为 MISSING 状态
- 策略阶段重新判定,再次尝试 CREATE
2. 人工介入规范
2.1 介入时机
| 时机 | 场景 | 操作 |
|---|---|---|
| 运行前 | 查看上次失败记录 | 查看持久化的 error,决定是否修复后重试 |
| bind() 后 | 出现 ABNORMAL/WARNING | 检查数据一致性,手工修复或确认 |
| bind() 后 | 1:N / N:N 映射 | 手工绑定指定远程记录 |
| sync() 后 | 批量失败 | 分析失败原因,决定重试策略 |
2.2 binding_status 与介入需求
| binding_status | 含义 | 需要介入 | 说明 |
|---|---|---|---|
UNCHECKED |
未检查 | ❌ | 等待 bind() 判定 |
NORMAL |
绑定正常 | ❌ | 自动处理 |
MISSING |
无绑定记录 | ❌ | 自动创建 |
WARNING |
本地有绑定但远程无数据 | ⚠️ 可选 | 可能是远程删除,需确认 |
ABNORMAL |
状态不一致 | ✅ 必须 | 需人工排查 |
DEPENDENCY_ERROR |
依赖未就绪 | ❌ | 等依赖解决后自动重试 |
2.3 人工绑定操作
# 手工绑定(1:N 场景)
binding_manager.bind(node_id="local_xxx", data_id="remote_xxx")
# 手工解绑
binding_manager.unbind(node_id="local_xxx")
绑定记录一旦建立,永不自动改变,只能手工操作。
2.4 职责分工
| 职责 | 系统自动 | 人工介入 |
|---|---|---|
| 1:1 自动绑定 | ✅ | - |
| 1:N / N:N 绑定 | ❌ | ✅ |
| NORMAL 节点同步 | ✅ | - |
| MISSING 节点创建 | ✅ | - |
| CREATE 失败重试 | ✅(自动清理僵尸) | ⚠️(需确认后手动重置) |
| UPDATE 失败重试 | ❌(保留FAILED状态) | ✅(需确认后手动重置) |
| ABNORMAL 处理 | ❌ | ✅ |
| WARNING 确认 | ❌ | ✅(可选) |
3. 总结
- 分阶段重置:
- 阶段1(加载时):只重置 binding_status,保留 action/status/error
- 阶段2(数据加载后):清理 CREATE 失败僵尸,然后重置 action
- 失败状态持久化:FAILED 状态和 error 信息保留,不自动重试
- 绑定记录:永久保留,除非 CREATE 失败自动清理或手工操作
- 人工介入:失败需确认后手动重置,ABNORMAL/WARNING 需人工处理,1:N 绑定需手工指定