Extract import sync preview service
This commit is contained in:
@@ -96,6 +96,8 @@ from api_server.html5_setup_controller import (
|
||||
)
|
||||
from api_server.import_quality_models import ImportQualityResponse
|
||||
from api_server.import_quality_service import import_quality_response as _build_import_quality_response
|
||||
from api_server.import_sync_models import ImportSyncPreview
|
||||
from api_server.import_sync_service import build_import_sync_preview as _build_import_sync_preview
|
||||
from api_server.metadata_tree_controller import (
|
||||
metadata_tree as _metadata_tree,
|
||||
metadata_tree_children as _metadata_tree_children,
|
||||
@@ -923,28 +925,6 @@ class ImportRequest(BaseModel):
|
||||
mode: ImportMode = ImportMode.FULL_REPLACE
|
||||
|
||||
|
||||
class ImportSyncDiffItem(BaseModel):
|
||||
qualified_name: str
|
||||
name: str
|
||||
object_kind: str
|
||||
group_name: str | None = None
|
||||
change_kind: str
|
||||
before_hash: str | None = None
|
||||
after_hash: str | None = None
|
||||
|
||||
|
||||
class ImportSyncPreview(BaseModel):
|
||||
mode: ImportMode = ImportMode.SYNC_PREVIEW
|
||||
applied: bool = False
|
||||
status: str = "preview_only"
|
||||
message: str
|
||||
added_count: int = 0
|
||||
removed_count: int = 0
|
||||
changed_count: int = 0
|
||||
unchanged_count: int = 0
|
||||
items: list[ImportSyncDiffItem] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ImportSummary(BaseModel):
|
||||
source: ImportSourceKind
|
||||
mode: ImportMode = ImportMode.FULL_REPLACE
|
||||
@@ -7249,72 +7229,6 @@ def _import_project_sync_preview(project_id: str, request: ImportRequest) -> Imp
|
||||
return summary
|
||||
|
||||
|
||||
def _build_import_sync_preview(
|
||||
current: NormalizedProject | None,
|
||||
incoming: NormalizedProject | None,
|
||||
) -> ImportSyncPreview:
|
||||
current_index = _normalized_object_hash_index(current)
|
||||
incoming_index = _normalized_object_hash_index(incoming)
|
||||
items: list[ImportSyncDiffItem] = []
|
||||
|
||||
for qualified_name in sorted(set(current_index) | set(incoming_index)):
|
||||
before = current_index.get(qualified_name)
|
||||
after = incoming_index.get(qualified_name)
|
||||
if before is None and after is not None:
|
||||
change_kind = "ADD"
|
||||
elif before is not None and after is None:
|
||||
change_kind = "REMOVE"
|
||||
elif before is not None and after is not None and before["hash"] != after["hash"]:
|
||||
change_kind = "UPDATE"
|
||||
else:
|
||||
change_kind = "UNCHANGED"
|
||||
|
||||
source = after or before or {}
|
||||
items.append(
|
||||
ImportSyncDiffItem(
|
||||
qualified_name=qualified_name,
|
||||
name=str(source.get("name", qualified_name)),
|
||||
object_kind=str(source.get("object_kind", "UNKNOWN")),
|
||||
group_name=source.get("group_name"),
|
||||
change_kind=change_kind,
|
||||
before_hash=before["hash"] if before is not None else None,
|
||||
after_hash=after["hash"] if after is not None else None,
|
||||
)
|
||||
)
|
||||
|
||||
added_count = sum(1 for item in items if item.change_kind == "ADD")
|
||||
removed_count = sum(1 for item in items if item.change_kind == "REMOVE")
|
||||
changed_count = sum(1 for item in items if item.change_kind == "UPDATE")
|
||||
unchanged_count = sum(1 for item in items if item.change_kind == "UNCHANGED")
|
||||
return ImportSyncPreview(
|
||||
message=(
|
||||
"Synchronization is not applied yet. This preview shows what would change; "
|
||||
"use FULL_REPLACE to replace current project data."
|
||||
),
|
||||
added_count=added_count,
|
||||
removed_count=removed_count,
|
||||
changed_count=changed_count,
|
||||
unchanged_count=unchanged_count,
|
||||
items=[item for item in items if item.change_kind != "UNCHANGED"],
|
||||
)
|
||||
|
||||
|
||||
def _normalized_object_hash_index(normalized: NormalizedProject | None) -> dict[str, dict]:
|
||||
if normalized is None:
|
||||
return {}
|
||||
result: dict[str, dict] = {}
|
||||
for group in normalized.configuration.groups:
|
||||
for item in group.objects:
|
||||
payload = item.model_dump(mode="json")
|
||||
result[item.qualified_name] = {
|
||||
"name": item.name,
|
||||
"object_kind": item.object_kind,
|
||||
"group_name": group.name,
|
||||
"hash": stable_hash(json.dumps(payload, ensure_ascii=False, sort_keys=True)),
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
def _append_import_history(project_id: str, summary: ImportSummary) -> None:
|
||||
state = _project_setup.setdefault(project_id, {})
|
||||
history = list(state.get("import_history", []))
|
||||
|
||||
Reference in New Issue
Block a user