整体同步代码
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import inspect
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict, Mapping, Optional
|
||||
|
||||
|
||||
async def build_data_id_normalization_map(
|
||||
@@ -39,18 +39,42 @@ def is_id_like_field(field_name: Optional[str]) -> bool:
|
||||
return lowered.endswith("_id") or lowered.endswith("_ids")
|
||||
|
||||
|
||||
def _strip_ignored_list_item_fields(
|
||||
field_name: Optional[str],
|
||||
value: Any,
|
||||
ignore_list_item_fields: Mapping[str, list[str]],
|
||||
) -> Any:
|
||||
if not isinstance(value, list):
|
||||
return value
|
||||
|
||||
ignored_keys = set(ignore_list_item_fields.get(field_name or "", []))
|
||||
if not ignored_keys:
|
||||
return value
|
||||
|
||||
normalized_items = []
|
||||
for item in value:
|
||||
if isinstance(item, dict):
|
||||
normalized_items.append({key: nested for key, nested in item.items() if key not in ignored_keys})
|
||||
else:
|
||||
normalized_items.append(item)
|
||||
return normalized_items
|
||||
|
||||
|
||||
def normalize_compare_value(
|
||||
field_name: Optional[str],
|
||||
value: Any,
|
||||
data_id_map: Dict[str, str],
|
||||
ignore_list_item_fields: Optional[Mapping[str, list[str]]] = None,
|
||||
) -> Any:
|
||||
ignored_list_fields = ignore_list_item_fields or {}
|
||||
if isinstance(value, dict):
|
||||
return {
|
||||
key: normalize_compare_value(key, nested, data_id_map)
|
||||
key: normalize_compare_value(key, nested, data_id_map, ignored_list_fields)
|
||||
for key, nested in value.items()
|
||||
}
|
||||
if isinstance(value, list):
|
||||
return [normalize_compare_value(field_name, item, data_id_map) for item in value]
|
||||
value = _strip_ignored_list_item_fields(field_name, value, ignored_list_fields)
|
||||
return [normalize_compare_value(field_name, item, data_id_map, ignored_list_fields) for item in value]
|
||||
|
||||
if value == "":
|
||||
value = None
|
||||
@@ -64,6 +88,7 @@ def normalized_data_for_compare(
|
||||
data: Optional[Dict[str, Any]],
|
||||
data_id_map: Optional[Dict[str, str]] = None,
|
||||
ignore_fields: Optional[set[str]] = None,
|
||||
ignore_list_item_fields: Optional[Mapping[str, list[str]]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
payload = copy.deepcopy(data or {})
|
||||
payload.pop("id", None)
|
||||
@@ -71,7 +96,7 @@ def normalized_data_for_compare(
|
||||
ignored = ignore_fields or set()
|
||||
mapping = data_id_map or {}
|
||||
return {
|
||||
key: normalize_compare_value(key, value, mapping)
|
||||
key: normalize_compare_value(key, value, mapping, ignore_list_item_fields)
|
||||
for key, value in payload.items()
|
||||
if key not in ignored
|
||||
}
|
||||
|
||||
@@ -55,15 +55,17 @@ def default_needs_update(
|
||||
return False
|
||||
|
||||
ignore_fields = set(strategy.config.compare_ignore_fields)
|
||||
normalized_source = strategy.normalize_compare_payload(
|
||||
normalized_source = normalized_data_for_compare(
|
||||
source_data,
|
||||
data_id_map,
|
||||
ignore_fields=ignore_fields,
|
||||
ignore_list_item_fields=strategy.config.post_check_ignore_list_item_fields,
|
||||
)
|
||||
normalized_target = strategy.normalize_compare_payload(
|
||||
normalized_target = normalized_data_for_compare(
|
||||
target_data,
|
||||
data_id_map,
|
||||
ignore_fields=ignore_fields,
|
||||
ignore_list_item_fields=strategy.config.post_check_ignore_list_item_fields,
|
||||
)
|
||||
diff_map = strategy.get_schema_diff_validator().compare_payloads(
|
||||
normalized_source,
|
||||
@@ -85,26 +87,28 @@ def resolve_needs_update_check(strategy) -> Callable:
|
||||
|
||||
|
||||
def _collect_diff_descriptions(
|
||||
strategy,
|
||||
source_data,
|
||||
target_data,
|
||||
*,
|
||||
data_id_map,
|
||||
ignore_fields: set[str],
|
||||
ignore_list_item_fields: dict[str, list[str]],
|
||||
max_items: int = 8,
|
||||
) -> List[str]:
|
||||
if source_data is None or target_data is None:
|
||||
return []
|
||||
|
||||
normalized_source = strategy.normalize_compare_payload(
|
||||
normalized_source = normalized_data_for_compare(
|
||||
source_data,
|
||||
data_id_map,
|
||||
ignore_fields=ignore_fields,
|
||||
ignore_list_item_fields=ignore_list_item_fields,
|
||||
)
|
||||
normalized_target = strategy.normalize_compare_payload(
|
||||
normalized_target = normalized_data_for_compare(
|
||||
target_data,
|
||||
data_id_map,
|
||||
ignore_fields=ignore_fields,
|
||||
ignore_list_item_fields=ignore_list_item_fields,
|
||||
)
|
||||
diff_map = collect_payload_diffs(
|
||||
normalized_source,
|
||||
@@ -202,11 +206,11 @@ async def add_update_action(
|
||||
has_diff = bool(should_update)
|
||||
if has_diff:
|
||||
diff_descriptions = _collect_diff_descriptions(
|
||||
strategy,
|
||||
data,
|
||||
target_node.get_data(),
|
||||
data_id_map=data_id_map or {},
|
||||
ignore_fields=set(strategy.config.compare_ignore_fields),
|
||||
ignore_list_item_fields=dict(strategy.config.post_check_ignore_list_item_fields),
|
||||
)
|
||||
|
||||
if steps_changed:
|
||||
@@ -318,6 +322,7 @@ async def run_update(strategy) -> List["SyncNode"]:
|
||||
f" (Pull, field_direction_key={field_key})"
|
||||
)
|
||||
|
||||
strategy.emit_schema_diff_report()
|
||||
return updated_nodes
|
||||
|
||||
# ── 无字段级覆盖:原有逻辑不变 ──
|
||||
@@ -350,4 +355,5 @@ async def run_update(strategy) -> List["SyncNode"]:
|
||||
f"[{strategy.node_type}] update_direction=BIDIRECTIONAL requires custom implementation"
|
||||
)
|
||||
|
||||
strategy.emit_schema_diff_report()
|
||||
return updated_nodes
|
||||
|
||||
Reference in New Issue
Block a user