mirror of
https://github.com/hansjone/netx.git
synced 2026-10-11 01:43:21 +08:00
Show UME sync delete counts in API and UME UI
Parse UmeSyncJob.details_json in GET /v1/ume/sync/status for deleted_inventory_ne, deleted_inventory_holders, deleted_stale_current_alarms. Add table columns on UmePage and types. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
340fc8ee7d
commit
a025245c8f
3 changed files with 43 additions and 1 deletions
|
|
@ -496,6 +496,33 @@ 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]:
|
||||||
|
"""Parse ``details_json`` from sync jobs (inventory / alarms) for delete-reconcile stats."""
|
||||||
|
out = {"deleted_inventory_ne": 0, "deleted_inventory_holders": 0, "deleted_current_alarms": 0}
|
||||||
|
raw = str(getattr(row, "details_json", "") or "").strip()
|
||||||
|
if not raw:
|
||||||
|
return out
|
||||||
|
try:
|
||||||
|
obj = json.loads(raw)
|
||||||
|
except Exception:
|
||||||
|
return out
|
||||||
|
if not isinstance(obj, dict):
|
||||||
|
return out
|
||||||
|
try:
|
||||||
|
out["deleted_inventory_ne"] = max(0, int(obj.get("deleted_inventory_ne") or 0))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
out["deleted_inventory_holders"] = max(0, int(obj.get("deleted_inventory_holders") or 0))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
out["deleted_current_alarms"] = max(0, int(obj.get("deleted_stale_current_alarms") or 0))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
@app.get("/v1/ume/sync/status")
|
@app.get("/v1/ume/sync/status")
|
||||||
def ume_sync_status(
|
def ume_sync_status(
|
||||||
page: int = Query(default=1, ge=1),
|
page: int = Query(default=1, ge=1),
|
||||||
|
|
@ -513,6 +540,7 @@ 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 ""),
|
||||||
|
|
@ -521,6 +549,9 @@ 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_inventory_holders": int(del_counts["deleted_inventory_holders"]),
|
||||||
|
"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),
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,9 @@ 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="对账删除的机框行">删机框</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>
|
||||||
|
|
@ -255,6 +258,9 @@ 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_inventory_holders ?? 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>
|
||||||
|
|
@ -262,7 +268,7 @@ export function UmePage() {
|
||||||
))}
|
))}
|
||||||
{!syncStatusQuery.isLoading && (syncStatusQuery.data?.items || []).length === 0 && (
|
{!syncStatusQuery.isLoading && (syncStatusQuery.data?.items || []).length === 0 && (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={9}>暂无同步记录</td>
|
<td colSpan={12}>暂无同步记录</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,11 @@ 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). */
|
||||||
|
deleted_inventory_ne?: number;
|
||||||
|
deleted_inventory_holders?: 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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue