UME runtime_tasks: expose interval_s and interval_label for UI

Backend computes effective loop interval (same clamps as startup). Table column 间隔 with tooltip seconds.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-11 19:24:42 +08:00
parent fa1135a9c2
commit 10ff96f17c
3 changed files with 45 additions and 1 deletions

View file

@ -106,6 +106,41 @@ def _runtime_resume_task(task: str) -> None:
_UME_RUNTIME_PAUSED[tid] = False _UME_RUNTIME_PAUSED[tid] = False
def _format_runtime_interval_label(seconds: int) -> str:
s = max(1, int(seconds))
if s >= 3600 and s % 3600 == 0:
h = s // 3600
return f"{h} h"
if s >= 60 and s % 60 == 0:
m = s // 60
return f"{m} min"
return f"{s}s"
def _runtime_task_interval_fields(task_id: str) -> tuple[int | None, str]:
"""Effective loop interval as configured at process start (matches startup clamps)."""
if task_id == "token_keepalive":
if not bool(getattr(settings, "ume_keepalive_enabled", True)):
return None, "未启用"
interval_s = int(getattr(settings, "ume_keepalive_interval_s", 600) or 600)
eff = max(30, min(interval_s, 3600))
return eff, _format_runtime_interval_label(eff)
if task_id == "alarms_current_auto_sync":
if not bool(getattr(settings, "ume_sync_alarms_current_enabled", True)):
return None, "未启用"
interval_s = int(getattr(settings, "ume_sync_alarms_current_interval_s", 300) or 300)
eff = max(30, min(interval_s, 86400))
return eff, _format_runtime_interval_label(eff)
if task_id == "inventory_auto_sync":
if not bool(getattr(settings, "ume_sync_inventory_auto_enabled", True)):
return None, "未启用"
hours = int(getattr(settings, "ume_sync_inventory_every_hours", 48) or 48)
hours = max(1, min(hours, 168))
eff = int(hours * 3600)
return eff, _format_runtime_interval_label(eff)
return None, "—"
def _list_runtime_tasks() -> list[dict[str, Any]]: def _list_runtime_tasks() -> list[dict[str, Any]]:
with _UME_RUNTIME_LOCK: with _UME_RUNTIME_LOCK:
out: list[dict[str, Any]] = [] out: list[dict[str, Any]] = []
@ -114,6 +149,7 @@ def _list_runtime_tasks() -> list[dict[str, Any]]:
paused = bool(_UME_RUNTIME_PAUSED.get(task_id)) paused = bool(_UME_RUNTIME_PAUSED.get(task_id))
eff_status = "paused" if paused else str(v.get("status") or "unknown") eff_status = "paused" if paused else str(v.get("status") or "unknown")
ts = _ensure_utc(v.get("last_run_at")) if isinstance(v.get("last_run_at"), datetime) else None ts = _ensure_utc(v.get("last_run_at")) if isinstance(v.get("last_run_at"), datetime) else None
interval_s, interval_label = _runtime_task_interval_fields(task_id)
out.append( out.append(
{ {
"task": task_id, "task": task_id,
@ -121,6 +157,8 @@ def _list_runtime_tasks() -> list[dict[str, Any]]:
"paused": paused, "paused": paused,
"last_run_at": ts.isoformat() if ts else None, "last_run_at": ts.isoformat() if ts else None,
"last_error": str(v.get("last_error") or ""), "last_error": str(v.get("last_error") or ""),
"interval_s": interval_s,
"interval_label": interval_label,
} }
) )
return out return out

View file

@ -225,6 +225,7 @@ export function UmePage() {
<thead> <thead>
<tr> <tr>
<th>task</th> <th>task</th>
<th title="相邻两次循环 sleep 的配置间隔(与服务启动时 clamp 一致)">间隔</th>
<th>status</th> <th>status</th>
<th>last_run_at</th> <th>last_run_at</th>
<th>last_error</th> <th>last_error</th>
@ -235,6 +236,9 @@ export function UmePage() {
{runtimeTasks.map((x) => ( {runtimeTasks.map((x) => (
<tr key={`runtime-${x.task}`}> <tr key={`runtime-${x.task}`}>
<td>{x.task}</td> <td>{x.task}</td>
<td title={typeof x.interval_s === "number" ? `${x.interval_s}s` : undefined}>
{x.interval_label ?? "—"}
</td>
<td>{x.status}</td> <td>{x.status}</td>
<td>{x.last_run_at ? formatSystemTime(x.last_run_at) : "-"}</td> <td>{x.last_run_at ? formatSystemTime(x.last_run_at) : "-"}</td>
<td>{x.last_error || "-"}</td> <td>{x.last_error || "-"}</td>
@ -263,7 +267,7 @@ export function UmePage() {
))} ))}
{!syncStatusQuery.isLoading && runtimeTasks.length === 0 && ( {!syncStatusQuery.isLoading && runtimeTasks.length === 0 && (
<tr> <tr>
<td colSpan={5}>暂无后台任务状态</td> <td colSpan={6}>暂无后台任务状态</td>
</tr> </tr>
)} )}
</tbody> </tbody>

View file

@ -101,6 +101,8 @@ export type UmeSyncStatusResponse = {
paused?: boolean; paused?: boolean;
last_run_at?: string | null; last_run_at?: string | null;
last_error?: string; last_error?: string;
interval_s?: number | null;
interval_label?: string;
}>; }>;
}; };