Files
ecm_sync_system/sync_state_machine/config/node_state_machine.yaml
T
strepsiades 4a9c444b10 first commit
2026-03-09 16:31:42 +08:00

601 lines
18 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
meta:
name: node_state_machine
version: 0.1
language: zh-CN
desc: "节点状态机配置(用于驱动/校验未来的状态机组件)"
# 命名约定(配置内唯一真名;图上不再有 display/别名):
# - Sxx: State / PseudoState(节点)
# - Exx: Event(事件)
# - 事件分支由渲染器在边上追加 a/b/c...(对应 outcomes 顺序)
id_convention:
state_prefix: "S"
event_prefix: "E"
# Variables are computed by the caller and passed into the state machine.
# Rule: the YAML never directly mutates "peer" nodes. Cross-node changes must be
# represented as separate invocations with different inputs.
context:
is_create_zombie: { type: bool, desc: "初始化时判定为 CREATE 僵尸:action=CREATE 且 (status=FAILED 或 data_id 为空)" }
has_binding_record: { type: bool, desc: "binding_manager 里存在绑定记录 (remote_id/local_id 非空)" }
core_binding_result: { type: enum, values: [NORMAL, WARNING, ABNORMAL], desc: "SyncDecisionEngine.determine_core_status() 给本节点的结果(仅在 has_binding_record=true 时有效)" }
peer_core_binding_result: { type: enum, values: [NORMAL, WARNING, ABNORMAL], desc: "SyncDecisionEngine.determine_core_status() 给对方节点的结果(用于静态约束 core matrix 对称性)" }
data_present: { type: bool, desc: "node.get_data() 非空" }
has_depend_fields: { type: bool, desc: "config.depend_fields 非空" }
dep_satisfied: { type: bool, desc: "依赖满足:空依赖值跳过;非空依赖值必须能在 collection 中按 data_id 找到且节点状态可用" }
auto_bind_enabled: { type: bool, desc: "config.auto_bind && auto_bind_fields 非空" }
auto_bind_outcome:
type: enum
values: [ONE_TO_ONE, AMBIGUOUS, ZERO, KEY_MISSING, KEY_ID_RESOLVE_FAIL, DATA_MISSING]
desc: "自动绑定结果(由业务代码完成全集搜索+去噪后 1:1 判定)"
create_enabled: { type: bool, desc: "create() 是否对当前方向启用 (local_orphan_action/remote_orphan_action)" }
create_id_resolve_ok: { type: bool, desc: "IDResolver.resolve_and_validate() 是否成功" }
spawn_success: { type: bool, desc: "创建副作用(spawn + bind)是否成功" }
update_enabled: { type: bool, desc: "update() 是否启用 (update_direction != NONE)" }
target_has_data_id: { type: bool, desc: "UPDATE 目标节点 data_id 非空" }
update_id_resolve_ok: { type: bool, desc: "UPDATE 前 IDResolver.resolve_and_validate() 是否成功" }
has_diff: { type: bool, desc: "needs_update_check 判定有差异" }
handler_result:
type: enum
values: [SUCCESS, FAILED, SKIPPED, IN_PROGRESS]
desc: "TaskResult.status"
poll_timeout: { type: bool, desc: "异步轮询超过 max_retries" }
execute_action:
type: enum
values: [CREATE, UPDATE, DELETE, NONE]
desc: "E40 执行时的动作类型(用于区分 SKIPPED 的落点)"
# State IDs are for visualization and static validation.
# NOTE: 本状态机按“加载时清空执行状态,再开始本轮”建模:
# - 加载/初始化后,稳态节点的 status 统一回到 PENDING
# - 上一轮遗留的 FAILED/SUCCESS 等不作为本轮的入口状态
states:
# --- Stable entry to bind (after init reset + zombie cleanup) ---
S00:
binding_status: UNCHECKED
action: NONE
status: PENDING
data_id_exist: true
desc: |
进入 bind 前的唯一起点
binding_status: UNCHECKED
action: NONE
status: PENDING
data_id_exist: true
# --- Bind results ---
S01:
binding_status: NORMAL
action: NONE
status: PENDING
data_id_exist: true
desc: |
绑定正常(待后续 update 检查)
binding_status: NORMAL
action: NONE
status: PENDING
data_id_exist: true
S02:
binding_status: MISSING
action: NONE
status: PENDING
data_id_exist: true
desc: |
孤儿节点(可能进入 create / auto_bind / delete
binding_status: MISSING
action: NONE
status: PENDING
data_id_exist: true
S03:
binding_status: ABNORMAL
action: NONE
status: PENDING
data_id_exist: true
desc: |
数据损坏/缺失(阻断态,需人工)
binding_status: ABNORMAL
action: NONE
status: PENDING
data_id_exist: true
S04:
binding_status: WARNING
action: NONE
status: PENDING
data_id_exist: true
desc: |
不可自动处理(阻断态,需人工)
binding_status: WARNING
action: NONE
status: PENDING
data_id_exist: true
S05:
binding_status: DEPENDENCY_ERROR
action: NONE
status: PENDING
data_id_exist: true
desc: |
依赖项不满足/ID解析失败(阻断态)
binding_status: DEPENDENCY_ERROR
action: NONE
status: PENDING
data_id_exist: true
# --- Create & Update prepared actions (target-side nodes) ---
S06:
binding_status: NORMAL
action: CREATE
status: PENDING
data_id_exist: false
shape: pseudo
desc: |
待执行 CREATE(执行入口)
binding_status: NORMAL
action: CREATE
status: PENDING
data_id_exist: false
S07:
binding_status: NORMAL
action: UPDATE
status: PENDING
data_id_exist: true
desc: |
准备更新
binding_status: NORMAL
action: UPDATE
status: PENDING
data_id_exist: true
S08:
binding_status: NORMAL
action: UPDATE
status: PRECONDITION_FAILED
data_id_exist: [false, true]
desc: |
更新前置失败(缺 data_id / 依赖ID未解析等)
binding_status: NORMAL
action: UPDATE
status: PRECONDITION_FAILED
data_id_exist: false | true
S09:
binding_status: NORMAL
action: DELETE
status: PENDING
data_id_exist: true
desc: |
待执行 DELETE(执行入口)
binding_status: NORMAL
action: DELETE
status: PENDING
data_id_exist: true
# --- Sync results ---
S10C:
binding_status: NORMAL
action: CREATE
status: IN_PROGRESS
data_id_exist: false
desc: |
CREATE 异步执行中
binding_status: NORMAL
action: CREATE
status: IN_PROGRESS
data_id_exist: false
S10U:
binding_status: NORMAL
action: UPDATE
status: IN_PROGRESS
data_id_exist: true
desc: |
UPDATE 异步执行中
binding_status: NORMAL
action: UPDATE
status: IN_PROGRESS
data_id_exist: true
S10D:
binding_status: NORMAL
action: DELETE
status: IN_PROGRESS
data_id_exist: true
desc: |
DELETE 异步执行中
binding_status: NORMAL
action: DELETE
status: IN_PROGRESS
data_id_exist: true
S11C:
binding_status: NORMAL
action: CREATE
status: SUCCESS
data_id_exist: true
desc: |
CREATE 执行成功
binding_status: NORMAL
action: CREATE
status: SUCCESS
data_id_exist: true
S11U:
binding_status: NORMAL
action: UPDATE
status: SUCCESS
data_id_exist: true
desc: |
UPDATE 执行成功
binding_status: NORMAL
action: UPDATE
status: SUCCESS
data_id_exist: true
S11D:
binding_status: NORMAL
action: DELETE
status: SUCCESS
data_id_exist: true
desc: |
DELETE 执行成功(随后删除节点)
binding_status: NORMAL
action: DELETE
status: SUCCESS
data_id_exist: true
S12C:
binding_status: NORMAL
action: CREATE
status: FAILED
data_id_exist: [false, true]
desc: |
CREATE 执行失败
binding_status: NORMAL
action: CREATE
status: FAILED
data_id_exist: false | true
S12U:
binding_status: NORMAL
action: UPDATE
status: FAILED
data_id_exist: [false, true]
desc: |
UPDATE 执行失败
binding_status: NORMAL
action: UPDATE
status: FAILED
data_id_exist: false | true
S12D:
binding_status: NORMAL
action: DELETE
status: FAILED
data_id_exist: [false, true]
desc: |
DELETE 执行失败
binding_status: NORMAL
action: DELETE
status: FAILED
data_id_exist: false | true
S13:
binding_status: PEER_CREATING
action: NONE
status: PENDING
data_id_exist: true
desc: |
对侧创建进行中(本侧等待提交)
binding_status: PEER_CREATING
action: NONE
status: PENDING
data_id_exist: true
# Handler 在 update 路径中可能把 action 降级为 NONE 并返回 SKIPPED。
# NOTE: 这会产生 (NORMAL, NONE, SKIPPED),并且该节点会被统计到 none 列。
S14:
binding_status: NORMAL
action: NONE
status: SKIPPED
data_id_exist: true
desc: |
更新被跳过(执行时降级为 NONE)
binding_status: NORMAL
action: NONE
status: SKIPPED
data_id_exist: true
pseudo_states:
S15:
desc: "节点被清理删除(zombie cleanup"
S16:
desc: "持久化加载输入态:本轮 E01 的输入节点集合(可包含上轮遗留与已稳定节点)"
S17:
desc: "加载异常隔离态:持久化枚举非法,保留错误供人工处理,不进入自动流程"
stages:
bootstrap:
desc: "启动/初始化(仅针对持久化加载出的节点):僵尸清理与归并到 S00"
entry_states: [S16]
exit_states: [S00, S15]
bind:
desc: "绑定判定:core matrix +(可选)依赖检查 +(可选)自动绑定;stage 仅约束边界,不要求内部顺序"
entry_states: [S00]
exit_states: [S01, S02, S03, S04, S05, S13]
create_prepare:
desc: "Create: 从 MISSING 源节点发起创建请求并在副作用提交后归并"
entry_states: [S02, S13]
exit_states: [S01, S02, S04, S05, S09, S13]
update_prepare:
desc: "Update: 检测差异并在目标节点上设置 UPDATE/PRECONDITION_FAILED"
entry_states: [S01]
exit_states: [S01, S07, S08]
post_create_ready:
desc: "创建成功后归并:CREATE 成功节点回到 NORMAL/NONE/PENDING,作为 update 起点"
entry_states: [S11C]
exit_states: [S01]
sync_execute:
desc: "Sync: DataSource 调用 handler,根据 TaskResult 更新 status;部分 handler 可能降级 action"
entry_states: [S06, S07, S09, S10C, S10U, S10D]
exit_states: [S10C, S10U, S10D, S11C, S11U, S11D, S12C, S12U, S12D, S14]
transitions:
E01:
stage: bootstrap
desc: "初始化:删CREATE僵尸;其余重置后进入起点"
from: [S16]
outcomes:
- when: { is_create_zombie: true }
to: S15
- when: { is_create_zombie: false }
to: S00
# --- Bind phase1 core ---
E10:
stage: bind
desc: "核心绑定判定:有绑定按core结果分流;无绑定→MISSING"
from: [S00]
outcomes:
- when: { has_binding_record: true, core_binding_result: NORMAL, peer_core_binding_result: NORMAL }
to: S01
emit:
note: "绑定关系一致,进入正常态"
- when: { has_binding_record: true, core_binding_result: WARNING, peer_core_binding_result: ABNORMAL }
to: S04
emit:
note: "对端异常,本端标记WARNING"
- when: { has_binding_record: true, core_binding_result: ABNORMAL, peer_core_binding_result: WARNING }
to: S03
emit:
note: "本端异常,进入ABNORMAL"
- when: { has_binding_record: true, core_binding_result: ABNORMAL, peer_core_binding_result: ABNORMAL }
to: S03
emit:
note: "双方异常,进入ABNORMAL"
- when: { has_binding_record: false }
to: S02
emit:
note: "无绑定记录,标记为MISSING"
# --- Bind phase2 dependency ---
E15:
stage: bind
desc: "依赖检查:失败→阻断;缺少依赖配置→WARNING;通过→不变(不在图上画自环)"
from: [S02]
outcomes:
- when: { has_depend_fields: false, data_present: true }
to: S04
emit:
note: "缺少依赖字段配置,无法自动处理"
- when: { data_present: false }
to: S03
emit:
note: "节点数据为空或不存在"
- when: { data_present: true, has_depend_fields: true, dep_satisfied: false }
to: S05
emit:
note: "依赖项不满足"
# --- Bind phase3 auto bind ---
E16:
stage: bind
desc: "自动绑定:1:1→NORMAL;歧义/缺字段/数据为空→阻断;N:0 且允许创建→S13 等待创建提交"
from: [S02]
outcomes:
- when: { auto_bind_enabled: false }
to: S04
emit:
note: "自动绑定未启用"
- when: { auto_bind_enabled: true, auto_bind_outcome: DATA_MISSING }
to: S04
emit:
note: "节点数据为空,无法自动绑定"
- when: { auto_bind_enabled: true, auto_bind_outcome: ONE_TO_ONE }
to: S01
emit:
note: "自动绑定成功(1:1"
- when: { auto_bind_enabled: true, auto_bind_outcome: AMBIGUOUS }
to: S04
emit:
note: "存在多个候选节点,无法自动绑定"
- when: { auto_bind_enabled: true, auto_bind_outcome: KEY_MISSING }
to: S04
emit:
note: "缺少业务键字段,无法自动绑定"
- when: { auto_bind_enabled: true, auto_bind_outcome: KEY_ID_RESOLVE_FAIL }
to: S05
emit:
note: "业务键中的ID字段解析失败"
- when: { auto_bind_enabled: true, auto_bind_outcome: ZERO, create_enabled: true }
to: S13
emit:
spawn_request: true
spawn_target_node_state: S06
note: "自动绑定识别为需创建,进入创建提交中间态"
- when: { auto_bind_enabled: true, auto_bind_outcome: ZERO, create_enabled: false }
to: S04
emit:
note: "未匹配到候选节点且不允许创建"
# --- Create prepare ---
E20:
stage: create_prepare
desc: "创建准备阶段2spawn 成功则提交到 NORMAL;失败保持等待态(不迁移)"
from: [S13]
outcomes:
- when: { spawn_success: true }
to: S01
emit:
note: "创建副作用提交成功"
E21:
stage: create_prepare
desc: "创建依赖解析失败→DEPENDENCY_ERROR"
from: [S02]
outcomes:
- when: { create_enabled: true, data_present: true, create_id_resolve_ok: false }
to: S05
emit:
note: "创建前依赖ID解析失败"
E22:
stage: create_prepare
desc: "孤儿自删准备:从 MISSING 进入 DELETE 执行入口"
from: [S02]
outcomes:
- when: {}
to: S09
emit:
note: "孤儿节点按策略进入自删"
# --- Update prepare (target-side) ---
E30:
stage: update_prepare
desc: "更新准备:缺data_id/依赖未解析→PRECONDITION_FAILED;有差异→UPDATE"
from: [S01]
outcomes:
- when: { update_enabled: true, target_has_data_id: false }
to: S08
emit:
note: "目标节点缺少data_id"
- when: { update_enabled: true, target_has_data_id: true, update_id_resolve_ok: false }
to: S08
emit:
note: "更新前依赖ID未解析"
- when: { update_enabled: true, target_has_data_id: true, update_id_resolve_ok: true, has_diff: true }
to: S07
emit:
note: "检测到数据差异,准备更新"
# --- Post-create normalization ---
E41:
stage: post_create_ready
desc: "创建成功后归并到 update 起点"
from: [S11C]
outcomes:
- when: { execute_action: CREATE }
to: S01
emit:
note: "创建成功后转入更新起点"
# --- Sync execute (split by action) ---
E40C_START:
stage: sync_execute
desc: "CREATE 执行入口:进入异步执行中"
from: [S06]
outcomes:
- when: { handler_result: IN_PROGRESS }
to: S10C
emit:
note: "CREATE 进入异步执行中"
E40C:
stage: sync_execute
desc: "CREATE 执行结果回写:进行中/成功/失败"
from: [S10C]
outcomes:
- when: { handler_result: SUCCESS }
to: S11C
emit:
note: "CREATE 执行成功"
- when: { handler_result: FAILED }
to: S12C
emit:
note: "CREATE 执行失败"
E40U_START:
stage: sync_execute
desc: "UPDATE 执行入口:进入异步执行中"
from: [S07]
outcomes:
- when: { handler_result: IN_PROGRESS }
to: S10U
emit:
note: "UPDATE 进入异步执行中"
E40U:
stage: sync_execute
desc: "UPDATE 执行结果回写:进行中/成功/失败/跳过"
from: [S10U]
outcomes:
- when: { handler_result: SUCCESS }
to: S11U
emit:
note: "UPDATE 执行成功"
- when: { handler_result: FAILED }
to: S12U
emit:
note: "UPDATE 执行失败"
- when: { handler_result: SKIPPED }
to: S14
emit:
note: "更新降级并跳过"
E40D_START:
stage: sync_execute
desc: "DELETE 执行入口:进入异步执行中"
from: [S09]
outcomes:
- when: { handler_result: IN_PROGRESS }
to: S10D
emit:
note: "DELETE 进入异步执行中"
E40D:
stage: sync_execute
desc: "DELETE 执行结果回写:进行中/成功/失败"
from: [S10D]
outcomes:
- when: { handler_result: SUCCESS }
to: S11D
emit:
note: "DELETE 执行成功"
delete_node: true
- when: { handler_result: FAILED }
to: S12D
emit:
note: "DELETE 执行失败"
invariants:
INV-1_UNCHECKED_ACTION_NONE:
desc: "UNCHECKED 不允许有动作"
when: { binding_status: UNCHECKED }
require: { action: NONE }
INV-2_BLOCKING_NO_ACTION:
desc: "阻断态不允许执行动作"
when_any:
- { binding_status: ABNORMAL }
- { binding_status: WARNING }
- { binding_status: DEPENDENCY_ERROR }
require: { action: NONE }
INV-3_PRECOND_IMPLIES_UPDATE:
desc: "PRECONDITION_FAILED 必须伴随 action=UPDATE"
when: { status: PRECONDITION_FAILED }
require: { action: UPDATE }