mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-26 21:41:57 -06:00
Made Activity History Updates Report Live Status While Being Watched
This commit is contained in:
@@ -231,10 +231,14 @@ export default function DeviceDetails({ device, onBack }) {
|
|||||||
load();
|
load();
|
||||||
}, [device]);
|
}, [device]);
|
||||||
|
|
||||||
|
const activityHostname = useMemo(() => {
|
||||||
|
return (meta?.hostname || agent?.hostname || device?.hostname || "").trim();
|
||||||
|
}, [meta?.hostname, agent?.hostname, device?.hostname]);
|
||||||
|
|
||||||
const loadHistory = useCallback(async () => {
|
const loadHistory = useCallback(async () => {
|
||||||
if (!device?.hostname) return;
|
if (!activityHostname) return;
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`/api/device/activity/${encodeURIComponent(device.hostname)}`);
|
const resp = await fetch(`/api/device/activity/${encodeURIComponent(activityHostname)}`);
|
||||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
setHistoryRows(data.history || []);
|
setHistoryRows(data.history || []);
|
||||||
@@ -242,18 +246,47 @@ export default function DeviceDetails({ device, onBack }) {
|
|||||||
console.warn("Failed to load activity history", e);
|
console.warn("Failed to load activity history", e);
|
||||||
setHistoryRows([]);
|
setHistoryRows([]);
|
||||||
}
|
}
|
||||||
}, [device]);
|
}, [activityHostname]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => { loadHistory(); }, [loadHistory]);
|
useEffect(() => { loadHistory(); }, [loadHistory]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const socket = typeof window !== "undefined" ? window.BorealisSocket : null;
|
||||||
|
if (!socket || !activityHostname) return undefined;
|
||||||
|
|
||||||
|
let refreshTimer = null;
|
||||||
|
const normalizedHost = activityHostname.toLowerCase();
|
||||||
|
const scheduleRefresh = (delay = 200) => {
|
||||||
|
if (refreshTimer) clearTimeout(refreshTimer);
|
||||||
|
refreshTimer = setTimeout(() => {
|
||||||
|
refreshTimer = null;
|
||||||
|
loadHistory();
|
||||||
|
}, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleActivityChanged = (payload = {}) => {
|
||||||
|
const payloadHost = String(payload?.hostname || "").trim().toLowerCase();
|
||||||
|
if (!payloadHost) return;
|
||||||
|
if (payloadHost === normalizedHost) {
|
||||||
|
const delay = payload?.change === "updated" ? 150 : 0;
|
||||||
|
scheduleRefresh(delay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on("device_activity_changed", handleActivityChanged);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (refreshTimer) clearTimeout(refreshTimer);
|
||||||
|
socket.off("device_activity_changed", handleActivityChanged);
|
||||||
|
};
|
||||||
|
}, [activityHostname, loadHistory]);
|
||||||
|
|
||||||
// No explicit live recap tab; recaps are recorded into Activity History
|
// No explicit live recap tab; recaps are recorded into Activity History
|
||||||
|
|
||||||
const clearHistory = async () => {
|
const clearHistory = async () => {
|
||||||
if (!device?.hostname) return;
|
if (!activityHostname) return;
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`/api/device/activity/${encodeURIComponent(device.hostname)}`, { method: "DELETE" });
|
const resp = await fetch(`/api/device/activity/${encodeURIComponent(activityHostname)}`, { method: "DELETE" });
|
||||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
||||||
setHistoryRows([]);
|
setHistoryRows([]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -4743,6 +4743,15 @@ def scripts_quick_run():
|
|||||||
}
|
}
|
||||||
# Broadcast to all connected clients; no broadcast kw in python-socketio v5
|
# Broadcast to all connected clients; no broadcast kw in python-socketio v5
|
||||||
socketio.emit("quick_job_run", payload)
|
socketio.emit("quick_job_run", payload)
|
||||||
|
try:
|
||||||
|
socketio.emit("device_activity_changed", {
|
||||||
|
"hostname": str(host),
|
||||||
|
"activity_id": job_id,
|
||||||
|
"change": "created",
|
||||||
|
"source": "quick_job",
|
||||||
|
})
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
results.append({"hostname": host, "job_id": job_id, "status": "Running"})
|
results.append({"hostname": host, "job_id": job_id, "status": "Running"})
|
||||||
|
|
||||||
return jsonify({"results": results})
|
return jsonify({"results": results})
|
||||||
@@ -4821,6 +4830,13 @@ def ansible_quick_run():
|
|||||||
try:
|
try:
|
||||||
_ansible_log_server(f"[quick_run] emit ansible_playbook_run host='{host}' run_id={run_id} job_id={job_id} path={rel_path}")
|
_ansible_log_server(f"[quick_run] emit ansible_playbook_run host='{host}' run_id={run_id} job_id={job_id} path={rel_path}")
|
||||||
socketio.emit("ansible_playbook_run", payload)
|
socketio.emit("ansible_playbook_run", payload)
|
||||||
|
if job_id:
|
||||||
|
socketio.emit("device_activity_changed", {
|
||||||
|
"hostname": str(host),
|
||||||
|
"activity_id": job_id,
|
||||||
|
"change": "created",
|
||||||
|
"source": "ansible",
|
||||||
|
})
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_ansible_log_server(f"[quick_run] emit failed host='{host}' run_id={run_id} err={ex}")
|
_ansible_log_server(f"[quick_run] emit failed host='{host}' run_id={run_id} err={ex}")
|
||||||
results.append({"hostname": host, "run_id": run_id, "status": "Queued", "activity_job_id": job_id})
|
results.append({"hostname": host, "run_id": run_id, "status": "Queued", "activity_job_id": job_id})
|
||||||
@@ -4904,6 +4920,7 @@ def handle_quick_job_result(data):
|
|||||||
status = (data.get("status") or "").strip() or "Failed"
|
status = (data.get("status") or "").strip() or "Failed"
|
||||||
stdout = data.get("stdout") or ""
|
stdout = data.get("stdout") or ""
|
||||||
stderr = data.get("stderr") or ""
|
stderr = data.get("stderr") or ""
|
||||||
|
broadcast_payload = None
|
||||||
try:
|
try:
|
||||||
conn = _db_conn()
|
conn = _db_conn()
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
@@ -4912,9 +4929,30 @@ def handle_quick_job_result(data):
|
|||||||
(status, stdout, stderr, job_id),
|
(status, stdout, stderr, job_id),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
try:
|
||||||
|
cur.execute(
|
||||||
|
"SELECT id, hostname, status FROM activity_history WHERE id=?",
|
||||||
|
(job_id,),
|
||||||
|
)
|
||||||
|
row = cur.fetchone()
|
||||||
|
if row and (row[1] or "").strip():
|
||||||
|
broadcast_payload = {
|
||||||
|
"activity_id": row[0],
|
||||||
|
"hostname": row[1],
|
||||||
|
"status": row[2] or status,
|
||||||
|
"change": "updated",
|
||||||
|
"source": "quick_job",
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
conn.close()
|
conn.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] quick_job_result DB update failed for job {job_id}: {e}")
|
print(f"[ERROR] quick_job_result DB update failed for job {job_id}: {e}")
|
||||||
|
if broadcast_payload:
|
||||||
|
try:
|
||||||
|
socketio.emit("device_activity_changed", broadcast_payload)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
@@ -5287,6 +5325,14 @@ def api_ansible_recap_report():
|
|||||||
"updated_at": row[15],
|
"updated_at": row[15],
|
||||||
}
|
}
|
||||||
socketio.emit("ansible_recap_update", payload)
|
socketio.emit("ansible_recap_update", payload)
|
||||||
|
if payload.get("activity_job_id"):
|
||||||
|
socketio.emit("device_activity_changed", {
|
||||||
|
"hostname": payload.get("hostname") or "",
|
||||||
|
"activity_id": payload.get("activity_job_id"),
|
||||||
|
"status": payload.get("status") or "",
|
||||||
|
"change": "updated",
|
||||||
|
"source": "ansible",
|
||||||
|
})
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user