现在depend_fields可以处理列表类id

This commit is contained in:
strepsiades
2026-03-24 10:18:13 +08:00
parent 03a22b0c1c
commit 65bf2346a3
2 changed files with 211 additions and 28 deletions
+117 -28
View File
@@ -219,7 +219,7 @@ class IDResolver:
# 遍历所有字段
for field_name, value in list(data_dict.items()):
# 判断是否是ID字段
is_id_field = field_name.endswith("_id") or field_name == "id"
is_id_field = field_name.endswith("_id") or field_name.endswith("_ids") or field_name == "id"
is_primary_id_field = field_name in ("id", "_id")
if not is_id_field:
@@ -241,32 +241,18 @@ class IDResolver:
hint = node_type
# 解析ID
target_id = await self.resolve_id(str(value), hint, to_remote=to_remote)
if target_id is None:
# to_remote=True表示从local到remote,所以node是local节点
# to_remote=False表示从remote到local,所以node是remote节点
collection_name = "local" if to_remote else "remote"
node_data_id = node.data_id or "N/A"
direction = "remote" if to_remote else "local"
if is_depend_field:
logger.warning(
f"[{node_type}] {collection_name.capitalize()} node {node.node_id} "
f"(data_id={node_data_id}): Dependency field '{field_name}' "
f"with value '{value}' failed to resolve to {direction} ID"
)
else:
if not is_primary_id_field:
logger.warning(
f"[{node_type}] {collection_name.capitalize()} node {node.node_id} "
f"(data_id={node_data_id}): Non-dependency ID field '{field_name}' "
f"with value '{value}' failed to resolve to {direction} ID, setting to empty"
)
data_dict[field_name] = ""
else:
# 成功解析,更新字段值
data_dict[field_name] = target_id
target_value = await self._resolve_id_field_value(
value=value,
hint=hint,
node=node,
node_type=node_type,
field_name=field_name,
is_depend_field=is_depend_field,
is_primary_id_field=is_primary_id_field,
to_remote=to_remote,
logger=logger,
)
data_dict[field_name] = target_value
# 将修改后的数据写回节点
node.set_data(data_dict)
@@ -347,7 +333,7 @@ class IDResolver:
# 原本有值(源端 ID),但解析后为空(找不到目标端 ID)
# 说明依赖节点虽然在源端存在,但在目标端还没就绪
if original_value and not resolved_value:
if self._has_unresolved_dependency_value(original_value, resolved_value):
failed_fields.append(f"{field_name}({dep_type})={original_value}")
if failed_fields:
@@ -356,3 +342,106 @@ class IDResolver:
return None, error_msg
return resolved_data, None
@staticmethod
def _has_unresolved_dependency_value(original_value: Any, resolved_value: Any) -> bool:
if isinstance(original_value, list) and isinstance(resolved_value, list):
if len(original_value) != len(resolved_value):
return True
for original_item, resolved_item in zip(original_value, resolved_value):
if original_item in (None, ""):
continue
if not resolved_item:
return True
return False
if isinstance(original_value, list):
return any(item not in (None, "") for item in original_value) and not resolved_value
return bool(original_value) and not resolved_value
async def _resolve_id_field_value(
self,
*,
value: Any,
hint: Optional[str],
node: "SyncNode",
node_type: str,
field_name: str,
is_depend_field: bool,
is_primary_id_field: bool,
to_remote: bool,
logger,
) -> Any:
if isinstance(value, list):
resolved_items = []
has_failure = False
for item in value:
if item is None or item == "":
resolved_items.append("")
continue
target_id = await self.resolve_id(str(item), hint, to_remote=to_remote)
if target_id is None:
has_failure = True
resolved_items.append("")
else:
resolved_items.append(target_id)
if has_failure:
self._log_id_resolution_failure(
logger=logger,
node=node,
node_type=node_type,
field_name=field_name,
value=value,
is_depend_field=is_depend_field,
is_primary_id_field=is_primary_id_field,
to_remote=to_remote,
)
return resolved_items
target_id = await self.resolve_id(str(value), hint, to_remote=to_remote)
if target_id is None:
self._log_id_resolution_failure(
logger=logger,
node=node,
node_type=node_type,
field_name=field_name,
value=value,
is_depend_field=is_depend_field,
is_primary_id_field=is_primary_id_field,
to_remote=to_remote,
)
return ""
return target_id
@staticmethod
def _log_id_resolution_failure(
*,
logger,
node: "SyncNode",
node_type: str,
field_name: str,
value: Any,
is_depend_field: bool,
is_primary_id_field: bool,
to_remote: bool,
) -> None:
collection_name = "local" if to_remote else "remote"
node_data_id = node.data_id or "N/A"
direction = "remote" if to_remote else "local"
if is_depend_field:
logger.warning(
f"[{node_type}] {collection_name.capitalize()} node {node.node_id} "
f"(data_id={node_data_id}): Dependency field '{field_name}' "
f"with value '{value}' failed to resolve to {direction} ID"
)
elif not is_primary_id_field:
logger.warning(
f"[{node_type}] {collection_name.capitalize()} node {node.node_id} "
f"(data_id={node_data_id}): Non-dependency ID field '{field_name}' "
f"with value '{value}' failed to resolve to {direction} ID, setting to empty"
)