Files
ecm_sync_system/docs/archive/from_root_docs/状态定义规范.md
T
strepsiades 4a9c444b10 first commit
2026-03-09 16:31:42 +08:00

18 KiB
Raw Blame History

同步系统状态定义 (Final Spec)

本文档定义了同步系统的状态机逻辑。逻辑流转遵循以下顺序:

  1. 核心状态判定 (Core State)
  2. 依赖检查与ID解析 (Dependency)
  3. 自动绑定/发现 (Discovery)
  4. 策略执行 (Action)

0. 绑定状态枚举 (BindingStatus)

状态值 含义 来源 允许创建
UNCHECKED 未执行绑定检查 加载后的初始状态
NORMAL 绑定正常 核心状态判定
MISSING 无绑定记录(孤儿) 核心状态判定
WARNING 业务键不完整 自动绑定阶段
ABNORMAL 数据损坏 核心状态判定
DEPENDENCY_ERROR 依赖未就绪 依赖检查或自动绑定

关键原则

  • UNCHECKED 阻止创建:加载后节点状态为 UNCHECKED,只有执行了 bind() 后才会转为其他状态
  • 只有 MISSING 状态才能触发 CREATEcreate() 方法只查找 binding_status == MISSING 的节点
  • 如果 bind() 被跳过(如 skip_sync=True),节点保持 UNCHECKED,不会被创建

1. 核心状态判定表 (Core Binding Matrix)

说明:

  • Binding Record Pair: 数据库中的绑定记录 (必须成对出现,已排除单边绑定)。
  • Data Valid: 指数据是否可读、Schema校验是否通过。
  • Warning vs Abnormal:
    • ABNORMAL: 自身数据损坏。
    • WARNING: 自身健康,但因为对方损坏导致连接不可用
Bind Pair (Record) Local Data (Valid?) Remote Data (Valid?) -> Local Status Remote Status 说明
YES YES YES -> NORMAL NORMAL 稳态。链路完整,数据健康,可进行 Diff/Update。
YES YES NO -> WARNING ABNORMAL 远程损坏。本地虽好,但链路已断 (Link Degraded)。禁止同步。
YES NO YES -> ABNORMAL WARNING 本地损坏。远程虽好,但链路已断。禁止同步。
YES NO NO -> ABNORMAL ABNORMAL 双向损坏
NO YES N/A -> MISSING N/A 本地孤儿。进入“依赖与发现”流程。
NO N/A YES -> N/A MISSING 远程孤儿。进入“依赖与发现”流程。

2. 依赖与业务键解析 (Dependency & ID Resolution)

适用范围: 所有涉及外键依赖 (Foreign Key) 的节点。 前置条件: 核心状态 = MISSING (准备进行自动绑定或新建)。

在进行 Auto-BindCreate 之前,必须先尝试构建远程业务键。 例如:本地 Contract(proj_id="P1", code="C01") 想找远程对象,必须先查询 P1 对应的远程 ID RP_99,转换成 (RP_99, "C01") 才能去远程搜索。

依赖项 (Dependency) 依赖项绑定状态 -> 能否构建业务键 节点状态 说明
无依赖 N/A -> Yes MISSING 根节点 (如 Project),直接进入下一阶段。
有依赖 NORMALdata_id 非空(status 任意) -> Yes MISSING 依赖项已获得远程ID,可进入下一阶段。
有依赖 NORMALdata_id 为空("",含 status = FAILED -> No DEPENDENCY_ERROR 依赖项未回填ID,阻断绑定与同步。
有依赖 MISSING / ABNORMAL -> No DEPENDENCY_ERROR 依赖阻断。父节点未同步或损坏,无法计算远程键,无法绑定,无法创建。
有依赖 WARNING -> No DEPENDENCY_ERROR 父节点状态不确定(如连接降级),禁止基于此建立新关系。

处理策略: 处于 DEPENDENCY_ERROR 状态的节点,其动作强制为 SKIP (或 PENDING)。必须先修复父节点。

错误信息格式: DEPENDENCY_ERROR 节点的 error 字段会包含详细的依赖失败信息:

  • dep_err: not_found: field_name(node_type)=value - 依赖节点未找到
  • dep_err: field_name: status=FAILED - 依赖节点状态为 FAILED
  • 多个依赖失败时用分号分隔:dep_err: not_found: project_id(project)=P1; contract_id: status=FAILED

3. 自动绑定状态处理 (Auto-Binding State Handling)

此逻辑遵循“去噪后 1:1”原则:只有在排除掉所有健康同步对后,若剩余节点形成绝对的 1:1 关系,才允许自动绑定。

配置说明与触发机制:

  • 初始化场景: 通常在系统第一次初始化或首次接入新实体时,配置 auto_bind = True 来对齐历史数据。
  • 后续同步: 系统在日常同步中不建议开启全局自动绑定。自动绑定仅作为“发现”手段,一旦建立过关系的节点,其后续绑定操作通常仅在“自动创建”逻辑中伴随产生(详见第 4 节孤儿处理)。
  • 执行前提: 只有当节点状态为 MISSING 且依赖解析成功(DEPENDENCY_ERROR = False)时,才会尝试以下探测逻辑。
  • 业务键完整性: 若业务键字段缺失(如 serial_number = null),直接标记 binding_status = WARNING,并在 node.error 记录原因(Auto-bind skipped: missing fields ...),不参与自动绑定与孤儿创建判定。- ID字段解析失败: 若业务键包含ID字段(如 supplier_id)且依赖节点未绑定,ID解析失败,标记 binding_status = DEPENDENCY_ERROR,阻止孤儿创建。 核心算法:
  1. 全集搜索: 寻找本地/远端所有共享同一个业务键(Business Key)的记录。
  2. 排除稳态对: 识别并移除成对且互绑NORMAL 记录。
    • 只有当本地 A 与远端 B 互为绑定对象,且状态皆为 NORMAL 时,才将这一对记录从待判定集合中剔除。
    • 若出现单边 NORMAL 记录(即其配对项不在本次搜索范围内或状态不属于另一端的 NORMAL),则不予剔除,视为环境污染项。
  3. 判定剩余: 检查排除上述稳态对后的剩余集合(包含 MISSING, ABNORMAL, WARNING 及单边已占用的 NORMAL 记录)。

术语

  • L_remain = 本地记录中,排除“成对稳态”后剩余的数量。
  • R_remain = 远端记录中,排除“成对稳态”后剩余的数量。
L_remain R_remain -> 动作 说明
1 1 -> BIND (Link) 1对1 自动对齐:仅当两端剩余记录皆为 MISSING 且绝对 1:1 时,执行自动绑定。
1 1 -> SKIP 带障不处理:若剩余记录中包含 ABNORMAL 等异常状态,说明存在历史冲突,不执行自动动作。
N 0 -> CREATE 可判定缺失:业务键完整且唯一,本地存在而远端不存在(N:0)时,才允许进入孤儿创建策略。
其他 其他 -> SKIP 非 1:1 不处理:存在多对多、多对一或无候选情况,系统保持原状。

设计优势:

  1. 对故障极端敏感:环境中存在任何 ABNORMAL 记录都会阻断自动绑定,强制人工介入处理异常。
  2. 状态纯净:失败时不产生任何中间态(如已废弃的 AMBIGUOUS),保持语义清晰。
  3. 静默自愈: 当外界清理了环境且满足 1:1 条件后,系统下次同步会自动完成绑定。

3.1 空数据处理策略

原则空数据不推送

空数据定义

  • 初始化时创建但未编辑的业务记录(如空合同、空施工任务)
  • 业务键字段为空或关键字段缺失的记录

处理方式

  • 在自动绑定阶段,若业务键字段缺失,标记 binding_status = WARNING,记录原因
  • 不参与自动绑定与孤儿创建判定
  • 不推送到远程系统

设计理由

  1. 远程系统简化:远程只需处理完整数据,无需兼容空数据校验逻辑
  2. 避免垃圾数据:空数据通常会被本地删除,若已推送则清理复杂
  3. 数据质量保障:远程系统只能看到本地已正确编辑保存的业务

配置方式Strategy 层):

# 在 Strategy 配置中指定必填字段
default_config = StrategyConfig(
    auto_bind_fields=["contract_id", "task_type"],  # 业务键字段
    # 如果这些字段为空,节点将被标记为 WARNING 而非 MISSING
)

4. 动作策略表 (Action Policy Matrix)

此表定义了在特定状态下,execute 阶段允许产生的 意图行动 (SyncAction)

A. 稳态更新 (NORMAL)

适用于已有绑定关系且链路健康的节点。

状态 动作条件 执行动作 (SyncAction)
NORMAL compute_diff 判定存在差异 UPDATE
NORMAL compute_diff 判定无差异 NONE

B. 异常处理 (阻断态)

处于这些状态的节点,引擎会自动中止后续的读写操作。

状态 说明 动作 (SyncAction)
DEPENDENCY_ERROR 父节点缺失/异常同步导致阻断 NONE
ABNORMAL / WARNING 数据损坏或链路降级,需人工修复 NONE

C. 孤儿处理 (Create Only)

适用于最终探测状态为 MISSING 且无法/不满足自动绑定的节点。

本地孤儿 (Local Orphan): 本地有,远程无。

策略配置 (local_orphan_action) 对应的同步模式 动作 (SyncAction)
"create_remote" Push (本地推远端) CREATE
"delete_local" Pull (远端拉本地) 报错 (未实现)
"none" Any NONE

远程孤儿 (Remote Orphan): 远程有,本地无。

策略配置 (remote_orphan_action) 对应的同步模式 动作 (SyncAction)
"create_local" Pull (远端拉本地) CREATE
"delete_remote" Push (本地推远端) 报错 (未实现)
"none" Any NONE

5. 执行同步状态转换 (Physical Sync State Transitions)

在策略执行完成、设置好 action 后,DataSource 层负责执行实际的同步操作并更新 status 字段。

A. 执行状态枚举 (SyncStatus)

状态值 含义 适用场景
PENDING 待执行 初始状态、无动作的节点
IN_PROGRESS 执行中 异步接口已提交,等待结果回调
SUCCESS 执行成功 同步操作完成且成功
FAILED 执行失败 同步操作失败,error 字段记录原因
SKIPPED 已跳过 节点被主动跳过(如依赖未满足)
PRECONDITION_FAILED 前置条件失败 create/update 内部验证发现问题

B. 执行转换矩阵

同步接口(一步式)

适用于同步 API(调用后立即返回成功/失败)。

输入: action API 调用结果 输出: status 副作用
CREATE 成功返回 (200/201) SUCCESS data_id 设置为远程返回的ID
CREATE 失败返回 (4xx/5xx) FAILED error 记录错误信息
UPDATE 成功返回 (200) SUCCESS -
UPDATE 失败返回 (4xx/5xx) FAILED error 记录错误信息
DELETE 成功返回 (200/204) SUCCESS 节点可能被移除
DELETE 失败返回 (4xx/5xx) FAILED error 记录错误信息
NONE - PENDING 不执行,保持原状

异步接口(两步式)

适用于异步 API(提交后需要轮询或回调获取结果)。

输入: action API 提交结果 输出: status 后续操作
CREATE 提交成功 (202 Accepted) IN_PROGRESS 记录 task_id,等待轮询
CREATE 提交失败 (4xx/5xx) FAILED error 记录错误
IN_PROGRESS 轮询返回成功 SUCCESS data_id 设置为远程ID
IN_PROGRESS 轮询返回失败 FAILED error 记录错误
IN_PROGRESS 超时未完成 FAILED error 记录 "Timeout"

B+. Handler 降级(action 取消)

代码实现:各 domain/*/api_handler.py 中的 update() 方法。

当 Handler 在构建 API 请求数据时,发现实际无需更新的字段(如 schema 校验后所有字段与远程一致), Handler 会主动将节点的 actionUPDATE 降级为 NONE

action=UPDATE → Handler 校验 → 无实际变更字段 → action=NONE(不提交 API

此机制确保 DataSource 不会向远程发送无意义的空更新请求。

C. 关键副作用

动作 成功时的副作用 说明
CREATE 临时绑定已建立 绑定关系可在提交前创建,用于推送与追踪;是否成功不影响该绑定存在
CREATE 设置 data_id 成功后从API响应中提取远程分配的ID,更新到节点
CREATE 回写 data 主键 DataSource 将远程返回的ID写回 SyncNode.data(如 id/*_id 字段)
CREATE 更新绑定记录 若使用临时ID,成功后替换为真实的远程ID
UPDATE 更新 origin_data 将当前 data 保存为新的 origin_data
DELETE 移除绑定记录 删除成功后,清除对应的绑定关系

D. 错误处理

错误类型 记录方式 重试策略
网络错误 error = "Network timeout" 可重试
权限错误 error = "403 Forbidden" 不可重试,需人工介入
数据校验错误 error = "Validation failed: ..." 不可重试,需修复数据
依赖缺失 status = PRECONDITION_FAILED 不执行,等待依赖修复

6. 同步检查规范 (Sync Check Specification)

在执行同步前后,需要进行状态检查以确保操作的合法性和完整性。

A. 内联前置检查(create/update 阶段)

实现说明:原 _pre_commit_check 方法已移除(保留空壳兼容接口)。 所有有效检查已内联到 strategy_ops/create_ops.py::add_create_action()strategy_ops/update_ops.py::add_update_action() 中。

create() 阶段内联检查

检查类别 检查条件 不通过时 说明
数据完整性 src_node.get_data() 不为空 跳过该节点,记录日志 MISSING 但数据为空
依赖 ID 解析 id_resolver.resolve_and_validate() 成功 binding_status → DEPENDENCY_ERROR 依赖字段无法解析到目标系统 ID

update() 阶段内联检查

检查类别 检查条件 不通过时 说明
FAILED 保护 src_node.status != FAILED 跳过该节点 不覆盖上次失败的状态和错误
数据完整性 src_node.get_data() 不为空 跳过该节点 NORMAL 但数据为空
目标节点存在 通过绑定找到目标节点 跳过该节点 绑定记录指向的节点不在集合中
data_id 完整性 target_node.data_id 非空 status → PRECONDITION_FAILED UPDATE 必须有业务主键
依赖 ID 解析 id_resolver.resolve_and_validate() 成功 status → PRECONDITION_FAILED 依赖字段无法解析到目标系统 ID
差异检测 _needs_update() 返回 True 跳过该节点 无差异则不更新

注意:以下检查项在当前实现中 未覆盖【未实现】:

  • 状态合法性:binding_status 必须是已知状态
  • 动作合法性:CREATE/UPDATE 只能用于 NORMAL 节点
  • 绑定一致性:NORMAL 节点必须有绑定记录

B. 同步后检查 (Post-Sync Check)

目标: 验证同步结果的完整性,发现残留问题。

实现说明:当前 _stage4_post_sync_check 只打印摘要表格,不做异常检测。以下检查项均为【未实现】。

检查项清单【未实现】

检查类别 检查条件 异常情况 严重程度
CREATE 完成性 CREATE 节点应该有 data_id action = CREATE, status = SUCCESSdata_id = "" 🔴 ERROR
CREATE 绑定 CREATE 节点应该有绑定记录 CREATE 成功但无绑定 🔴 ERROR
UPDATE 完成性 UPDATE 节点应该成功 action = UPDATEstatus = FAILED ⚠️ WARNING
绑定保持 UPDATE 节点的绑定应该保持 UPDATE 后绑定记录丢失 🔴 ERROR
残留异常 不应有 ABNORMAL 节点 同步后仍有 binding_status = ABNORMAL ⚠️ WARNING
残留依赖错误 不应有 DEPENDENCY_ERROR 同步后仍有依赖阻断 ⚠️ WARNING

统计指标

指标 计算方式 用途
成功率 SUCCESS / (CREATE + UPDATE) 评估同步质量
异常率 (ABNORMAL + WARNING) / total 发现数据质量问题
阻断率 DEPENDENCY_ERROR / total 发现依赖关系问题

决策规则

检查结果 ERROR 数量 决策
通过 0 继续持久化,正常结束
⚠️ 有警告 0, WARNING ≥1 继续持久化,打印警告报告
有错误 ≥1 继续持久化(已同步无法回滚),打印错误报告

注意: Post-Sync Check 即使有 ERROR 也不会终止流程,因为同步已经执行,无法回滚。检查目的是发现问题并记录,供后续修复。


附录: 状态字段说明

SyncNode 核心字段

字段 类型 设置阶段 含义
binding_status BindingStatus Bind 阶段 绑定健康状态
action SyncAction Create/Update 阶段 待执行动作
status SyncStatus Physical Sync 阶段 执行结果状态
data_id str 数据加载 / CREATE 后 业务主键IDCREATE 前为 ""
depend_ids List[str] 数据加载 依赖节点的 node_id 列表
error str | None Physical Sync 阶段 错误信息(失败时)

状态流转时序

[数据加载]          [Bind]              [Create/Update]     [Physical Sync]
binding_status:   UNCHECKED  →  NORMAL/MISSING/...  →  (保持)          →  (保持)
action:           NONE       →  NONE                →  CREATE/UPDATE   →  (保持)
status:           PENDING    →  PENDING             →  PENDING         →  SUCCESS/FAILED
data_id:          从源加载    →  (保持)              →  可能为 ""      →  CREATE 后设置