规范了update data的构建方式,统一使用build_update_request_data方法来处理更新数据的构建和过滤逻辑。这个方法会根据提供的原始数据、更新数据和对应的schema来生成最终的更新请求数据,同时会自动排除掉未变化的字段和空值字段,从而确保只发送必要的更新信息到后端接口。这种方式不仅简化了代码逻辑,还提高了代码的可维护性和一致性。
This commit is contained in:
@@ -45,6 +45,7 @@ class BaseSyncStrategy(Generic[T]):
|
||||
skip_sync: bool - 如果为 True,则跳过该类型的 bind/create/update/sync 阶段
|
||||
数据仍会被加载,但不会执行任何同步操作
|
||||
适用于只需要加载数据供其他类型引用的场景(如 supplier)
|
||||
skip_post_check: bool - 如果为 True,则跳过该类型最终 post-check 的 reload 与一致性校验
|
||||
"""
|
||||
# 类变量:默认配置(子类可覆盖)
|
||||
default_config: StrategyConfig = StrategyConfig()
|
||||
@@ -52,6 +53,8 @@ class BaseSyncStrategy(Generic[T]):
|
||||
schema: Type[T] = None # type: ignore
|
||||
# 类变量:是否默认跳过同步(子类可覆盖)
|
||||
default_skip_sync: bool = False
|
||||
# 类变量:是否默认跳过 post-check(子类可覆盖)
|
||||
default_skip_post_check: bool = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -71,6 +74,8 @@ class BaseSyncStrategy(Generic[T]):
|
||||
self.config = self.default_config.model_copy(deep=True)
|
||||
# 是否跳过同步(可运行时修改)
|
||||
self.skip_sync = self.default_skip_sync
|
||||
# 是否跳过 post-check(可运行时修改)
|
||||
self.skip_post_check = self.default_skip_post_check
|
||||
# 统一由 Pipeline 注入 runtime;未注入时在执行阶段显式报错
|
||||
self.sm_runtime: Optional[StateMachineRuntime] = None
|
||||
self._schema_diff_validator: Optional[SchemaDiffValidator] = None
|
||||
|
||||
@@ -16,6 +16,12 @@ if TYPE_CHECKING:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _stable_pick_bind_pair(local_candidates: List["SyncNode"], remote_candidates: List["SyncNode"]):
|
||||
local_node = sorted(local_candidates, key=lambda item: ((item.data_id or ""), item.node_id))[0]
|
||||
remote_node = sorted(remote_candidates, key=lambda item: ((item.data_id or ""), item.node_id))[0]
|
||||
return local_node, remote_node
|
||||
|
||||
|
||||
async def run_bind(strategy, **kwargs):
|
||||
logger.info(f"[{strategy.node_type}] Starting Binding Pipeline...")
|
||||
|
||||
@@ -519,29 +525,78 @@ async def phase_auto_binding(strategy, local_nodes: List["SyncNode"], remote_nod
|
||||
}
|
||||
)
|
||||
|
||||
if (len(l_remain) > 1 and len(r_remain) >= 1) or (len(l_remain) == 1 and len(r_remain) > 1):
|
||||
for n in l_remain:
|
||||
if n.binding_status == BindingStatus.MISSING:
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": n,
|
||||
"outcome": "AMBIGUOUS",
|
||||
"create_enabled": None,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
many_local_one_remote = len(l_remain) > 1 and len(r_remain) == 1
|
||||
one_local_many_remote = len(l_remain) == 1 and len(r_remain) > 1
|
||||
|
||||
if strategy.config.allow_many_to_one_auto_bind and (many_local_one_remote or one_local_many_remote):
|
||||
chosen_local, chosen_remote = _stable_pick_bind_pair(l_remain, r_remain)
|
||||
|
||||
if chosen_local.binding_status == BindingStatus.MISSING:
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": chosen_local,
|
||||
"outcome": "ONE_TO_ONE",
|
||||
"create_enabled": None,
|
||||
"bind_remote_node_id": chosen_remote.node_id,
|
||||
}
|
||||
)
|
||||
if chosen_remote.binding_status == BindingStatus.MISSING:
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": chosen_remote,
|
||||
"outcome": "ONE_TO_ONE",
|
||||
"create_enabled": None,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
|
||||
for n in l_remain:
|
||||
if n.node_id == chosen_local.node_id or n.binding_status != BindingStatus.MISSING:
|
||||
continue
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": n,
|
||||
"outcome": "ZERO",
|
||||
"create_enabled": local_create_enabled,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
|
||||
if (len(r_remain) > 1 and len(l_remain) >= 1) or (len(r_remain) == 1 and len(l_remain) > 1):
|
||||
for n in r_remain:
|
||||
if n.binding_status == BindingStatus.MISSING:
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": n,
|
||||
"outcome": "AMBIGUOUS",
|
||||
"create_enabled": None,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
if n.node_id == chosen_remote.node_id or n.binding_status != BindingStatus.MISSING:
|
||||
continue
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": n,
|
||||
"outcome": "ZERO",
|
||||
"create_enabled": remote_create_enabled,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
else:
|
||||
if (len(l_remain) > 1 and len(r_remain) >= 1) or (len(l_remain) == 1 and len(r_remain) > 1):
|
||||
for n in l_remain:
|
||||
if n.binding_status == BindingStatus.MISSING:
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": n,
|
||||
"outcome": "AMBIGUOUS",
|
||||
"create_enabled": None,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
|
||||
if (len(r_remain) > 1 and len(l_remain) >= 1) or (len(r_remain) == 1 and len(l_remain) > 1):
|
||||
for n in r_remain:
|
||||
if n.binding_status == BindingStatus.MISSING:
|
||||
pending_auto_bind_updates.append(
|
||||
{
|
||||
"node": n,
|
||||
"outcome": "AMBIGUOUS",
|
||||
"create_enabled": None,
|
||||
"bind_remote_node_id": None,
|
||||
}
|
||||
)
|
||||
|
||||
for item in pending_auto_bind_updates:
|
||||
node = item["node"]
|
||||
@@ -572,3 +627,25 @@ async def phase_auto_binding(strategy, local_nodes: List["SyncNode"], remote_nod
|
||||
reason = f"{reason} | detail={detail}"
|
||||
node.error = reason
|
||||
logger.debug(f"[{strategy.node_type}] 自动绑定阻断: node={node.node_id}, reason={reason}")
|
||||
|
||||
outcome_counts: Dict[str, int] = {}
|
||||
create_enabled_count = 0
|
||||
bound_pairs = 0
|
||||
for item in pending_auto_bind_updates:
|
||||
outcome = str(item.get("outcome") or "NONE")
|
||||
outcome_counts[outcome] = outcome_counts.get(outcome, 0) + 1
|
||||
if item.get("create_enabled"):
|
||||
create_enabled_count += 1
|
||||
if item.get("bind_remote_node_id"):
|
||||
bound_pairs += 1
|
||||
|
||||
if pending_auto_bind_updates:
|
||||
ordered = ", ".join(f"{key}={outcome_counts[key]}" for key in sorted(outcome_counts))
|
||||
logger.info(
|
||||
"[%s] Auto-bind summary: candidates=%d, bind_pairs=%d, create_enabled=%d, outcomes={%s}",
|
||||
strategy.node_type,
|
||||
len(pending_auto_bind_updates),
|
||||
bound_pairs,
|
||||
create_enabled_count,
|
||||
ordered,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user