修改多个问题,优化代码结构

This commit is contained in:
strepsiades
2026-04-01 16:23:43 +08:00
parent 8f4727a772
commit 7c49df94fc
29 changed files with 968 additions and 504 deletions
+129 -12
View File
@@ -1,35 +1,45 @@
from abc import ABC, abstractmethod
from typing import TypeVar, Generic, Type, Dict, List, Optional, Any
from pydantic import BaseModel
import logging
from pathlib import Path
from ..common.collection import DataCollection
from ..common.binding import BindingManager
from ..common.sync_node import SyncNode
from ..logging import get_logger
from .config import StrategyConfig, OrphanAction, UpdateDirection
from ..config.strategy_config import resolve_domain_option_config
from .strategy_ops import (
run_bind,
run_create,
run_delete,
)
from .strategy_ops.bind_ops import (
apply_auto_bind_updates,
collect_auto_bind_ready_nodes,
collect_bind_entry_nodes,
plan_auto_bind_updates,
phase_core_state,
phase_dependency_check,
refresh_bind_data_id,
)
from .strategy_ops.create_ops import add_create_action
from .strategy_ops.update_ops import (
BoundNodePair,
_build_schema_diff_validator,
collect_bound_node_pairs,
default_get_node_update_payload,
default_needs_update,
default_update_pair,
emit_schema_diff_report,
prepare_directional_update,
run_update,
)
from ..engine import (
StateMachineConfig,
StateMachineRuntime,
)
from .strategy_ops.compare_ops import normalized_data_for_compare
from .strategy_ops.compare_ops import build_data_id_normalization_map, normalized_data_for_compare
T = TypeVar("T", bound=BaseModel)
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
class BaseSyncStrategy(ABC, Generic[T]):
"""
@@ -69,7 +79,7 @@ class BaseSyncStrategy(ABC, Generic[T]):
pass
@abstractmethod
async def bind(self, **kwargs):
async def bind(self):
"""进行绑定逻辑判定,设置 node.binding_status 和 node.action"""
pass
@@ -191,17 +201,124 @@ class DefaultSyncStrategy(BaseSyncStrategy[T]):
)
return normalized
async def bind(self, **kwargs):
self.ensure_runtime()
await run_bind(self, **kwargs)
async def bind(self):
runtime = self.ensure_runtime()
bind_local_nodes, bind_remote_nodes = collect_bind_entry_nodes(
node_type=self.node_type,
local_collection=self.local_collection,
remote_collection=self.remote_collection,
)
await phase_core_state(
node_type=self.node_type,
runtime=runtime,
binding_manager=self.binding_manager,
local_nodes=bind_local_nodes,
remote_nodes=bind_remote_nodes,
)
await phase_dependency_check(
node_type=self.node_type,
runtime=runtime,
depend_fields=dict(self.config.depend_fields),
local_nodes=bind_local_nodes,
remote_nodes=bind_remote_nodes,
local_collection=self.local_collection,
remote_collection=self.remote_collection,
)
auto_bind_local_nodes, auto_bind_remote_nodes = collect_auto_bind_ready_nodes(
node_type=self.node_type,
local_collection=self.local_collection,
remote_collection=self.remote_collection,
)
local_create_enabled = self.config.local_orphan_action == OrphanAction.CREATE_REMOTE
remote_create_enabled = self.config.remote_orphan_action == OrphanAction.CREATE_LOCAL
local_orphan_create_enabled_by_node = {
node.node_id: local_create_enabled for node in auto_bind_local_nodes
}
remote_orphan_create_enabled_by_node = {
node.node_id: remote_create_enabled for node in auto_bind_remote_nodes
}
pending_updates = await plan_auto_bind_updates(
node_type=self.node_type,
config=self.config,
local_collection=self.local_collection,
remote_collection=self.remote_collection,
binding_manager=self.binding_manager,
local_nodes=auto_bind_local_nodes,
remote_nodes=auto_bind_remote_nodes,
id_field_hints=dict(self.config.depend_fields),
local_orphan_create_enabled_by_node=local_orphan_create_enabled_by_node,
remote_orphan_create_enabled_by_node=remote_orphan_create_enabled_by_node,
)
await apply_auto_bind_updates(
node_type=self.node_type,
runtime=runtime,
binding_manager=self.binding_manager,
pending_auto_bind_updates=pending_updates,
)
await refresh_bind_data_id(
node_type=self.node_type,
local_collection=self.local_collection,
remote_collection=self.remote_collection,
binding_manager=self.binding_manager,
local_node_ids={
*(node.node_id for node in bind_local_nodes),
*(node.node_id for node in auto_bind_local_nodes),
},
remote_node_ids={
*(node.node_id for node in bind_remote_nodes),
*(node.node_id for node in auto_bind_remote_nodes),
},
)
async def create(self) -> List[SyncNode]:
self.ensure_runtime()
return await run_create(self)
created_nodes: List[SyncNode] = []
created_nodes.extend(await self.create_for_direction(source_is_local=True))
created_nodes.extend(await self.create_for_direction(source_is_local=False))
return created_nodes
async def create_for_direction(self, *, source_is_local: bool) -> List[SyncNode]:
from_collection = self.local_collection if source_is_local else self.remote_collection
to_collection = self.remote_collection if source_is_local else self.local_collection
return await add_create_action(
self,
from_collection=from_collection,
to_collection=to_collection,
source_is_local=source_is_local,
)
async def update(self) -> List[SyncNode]:
self.ensure_runtime()
return await run_update(self)
validator = _build_schema_diff_validator(self)
self._active_schema_diff_validator = validator
data_id_map = await self.build_update_data_id_map()
try:
pairs = await self.collect_update_pairs()
updated_by_id = await self.process_update_pairs(pairs, data_id_map)
finally:
self._active_schema_diff_validator = None
emit_schema_diff_report(self, validator)
return list(updated_by_id.values())
async def build_update_data_id_map(self) -> Dict[str, str]:
return await build_data_id_normalization_map(
node_type=self.node_type,
local_collection=self.local_collection,
remote_collection=self.remote_collection,
binding_manager=self.binding_manager,
)
async def process_update_pairs(
self,
pairs: List[BoundNodePair],
data_id_map: Optional[Dict[str, str]] = None,
) -> Dict[str, SyncNode]:
updated_by_id: Dict[str, SyncNode] = {}
for pair in pairs:
for updated_node in await self.update_pair(pair.local_node, pair.remote_node, data_id_map):
updated_by_id[updated_node.node_id] = updated_node
return updated_by_id
def get_node_update_payload(self, node: SyncNode) -> Dict[str, Any]:
return default_get_node_update_payload(node)