Unify sync status deleted into single deleted field

API GET /v1/ume/sync/status exposes deleted only (sum of inventory NE + current-alarm reconcile counts from details_json). UI one column.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-11 18:51:30 +08:00
parent ac1f573508
commit c06beecfe6
3 changed files with 15 additions and 21 deletions

View file

@ -498,27 +498,27 @@ def ume_sync(payload: dict[str, Any] | None = None, db: Session = Depends(get_db
return out return out
def _ume_sync_job_details_counts(row: UmeSyncJob) -> dict[str, int]: def _ume_sync_job_deleted_count(row: UmeSyncJob) -> int:
"""Parse ``details_json`` from sync jobs (inventory / alarms) for delete-reconcile stats.""" """Single reconcile delete count: inventory uses deleted_inventory_ne; current alarms uses deleted_stale_current_alarms."""
out = {"deleted_inventory_ne": 0, "deleted_current_alarms": 0}
raw = str(getattr(row, "details_json", "") or "").strip() raw = str(getattr(row, "details_json", "") or "").strip()
if not raw: if not raw:
return out return 0
try: try:
obj = json.loads(raw) obj = json.loads(raw)
except Exception: except Exception:
return out return 0
if not isinstance(obj, dict): if not isinstance(obj, dict):
return out return 0
inv = cur = 0
try: try:
out["deleted_inventory_ne"] = max(0, int(obj.get("deleted_inventory_ne") or 0)) inv = max(0, int(obj.get("deleted_inventory_ne") or 0))
except Exception: except Exception:
pass pass
try: try:
out["deleted_current_alarms"] = max(0, int(obj.get("deleted_stale_current_alarms") or 0)) cur = max(0, int(obj.get("deleted_stale_current_alarms") or 0))
except Exception: except Exception:
pass pass
return out return int(inv + cur)
@app.get("/v1/ume/sync/status") @app.get("/v1/ume/sync/status")
@ -538,7 +538,6 @@ def ume_sync_status(
items = [] items = []
latest_by_domain: dict[str, dict[str, Any]] = {} latest_by_domain: dict[str, dict[str, Any]] = {}
for r in rows: for r in rows:
del_counts = _ume_sync_job_details_counts(r)
item = { item = {
"id": int(r.id), "id": int(r.id),
"domain": str(r.domain or ""), "domain": str(r.domain or ""),
@ -547,8 +546,7 @@ def ume_sync_status(
"pulled_count": int(r.pulled_count or 0), "pulled_count": int(r.pulled_count or 0),
"inserted_count": int(r.inserted_count or 0), "inserted_count": int(r.inserted_count or 0),
"updated_count": int(r.updated_count or 0), "updated_count": int(r.updated_count or 0),
"deleted_inventory_ne": int(del_counts["deleted_inventory_ne"]), "deleted": int(_ume_sync_job_deleted_count(r)),
"deleted_current_alarms": int(del_counts["deleted_current_alarms"]),
"error_message": str(r.error_message or ""), "error_message": str(r.error_message or ""),
"started_at": (_ensure_utc(r.started_at) or datetime.now(timezone.utc)).isoformat(), "started_at": (_ensure_utc(r.started_at) or datetime.now(timezone.utc)).isoformat(),
"ended_at": (_ensure_utc(r.ended_at).isoformat() if r.ended_at else None), "ended_at": (_ensure_utc(r.ended_at).isoformat() if r.ended_at else None),

View file

@ -241,8 +241,7 @@ export function UmePage() {
<th>pulled</th> <th>pulled</th>
<th>inserted</th> <th>inserted</th>
<th>updated</th> <th>updated</th>
<th title="对账删除的网元行(仅 inventory 全量成功时)">删网元</th> <th title="全量对账删除条数:inventory 为网元行,alarms_current 为当前告警行,其余域多为 0">deleted</th>
<th title="对账删除的当前告警行(仅 alarms_current 全量成功时)">删当前告警</th>
<th>started_at</th> <th>started_at</th>
<th>ended_at</th> <th>ended_at</th>
<th>error</th> <th>error</th>
@ -257,8 +256,7 @@ export function UmePage() {
<td>{x.pulled_count}</td> <td>{x.pulled_count}</td>
<td>{x.inserted_count}</td> <td>{x.inserted_count}</td>
<td>{x.updated_count}</td> <td>{x.updated_count}</td>
<td>{Number(x.deleted_inventory_ne ?? 0)}</td> <td>{Number(x.deleted ?? 0)}</td>
<td>{Number(x.deleted_current_alarms ?? 0)}</td>
<td>{formatSystemTime(x.started_at)}</td> <td>{formatSystemTime(x.started_at)}</td>
<td>{x.ended_at ? formatSystemTime(x.ended_at) : "-"}</td> <td>{x.ended_at ? formatSystemTime(x.ended_at) : "-"}</td>
<td>{x.error_message || "-"}</td> <td>{x.error_message || "-"}</td>
@ -266,7 +264,7 @@ export function UmePage() {
))} ))}
{!syncStatusQuery.isLoading && (syncStatusQuery.data?.items || []).length === 0 && ( {!syncStatusQuery.isLoading && (syncStatusQuery.data?.items || []).length === 0 && (
<tr> <tr>
<td colSpan={11}>暂无同步记录</td> <td colSpan={10}>暂无同步记录</td>
</tr> </tr>
)} )}
</tbody> </tbody>

View file

@ -82,10 +82,8 @@ export type UmeSyncJobItem = {
pulled_count: number; pulled_count: number;
inserted_count: number; inserted_count: number;
updated_count: number; updated_count: number;
/** Reconcile deletes after full inventory snapshot (netx ume_sync_service). */ /** Full-snapshot reconcile deletes (inventory: NE rows; alarms_current: current alarm rows). */
deleted_inventory_ne?: number; deleted?: number;
/** Reconcile deletes for current alarms after full snapshot. */
deleted_current_alarms?: number;
error_message?: string; error_message?: string;
started_at: string; started_at: string;
ended_at?: string | null; ended_at?: string | null;