refactor(ao): background loops only orchestrate; cleanup/reconcile endpoints enqueue

- separate qB sync timer from the planning timer
- threshold cleanup, reserved-plan and pending-import sweeps, 6h reconcile enqueue
  engine tasks with time-slot idempotency keys instead of running inline
- pending-import sweep selects by completed_at (sync refreshes updated_at every round)
- POST /download-cache/cleanup and /library/reconcile return {taskId, runId} (202);
  web jumps to the engine run page
- test: a 50MB verifyAndImport in progress does not delay qB sync

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-27 22:12:16 +08:00
1 parent a9cee69bd2
commit fe9693d4ca
13 files changed
+334 -68

No files matched your search

@@ -1,5 +1,6 @@
import type { Dashboard } from "@umt/contracts";
import { Brush, HardDrive } from "lucide-react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import { useCacheCleanup, useCacheVolumes } from "~/api/downloads.ts";
import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx";
@@ -79,6 +80,7 @@ function VolumeBar({ v }: { v: Volume }) {
export function CacheVolumes() {
const vols = useCacheVolumes();
const cleanup = useCacheCleanup();
const navigate = useNavigate();
return (
<section className="pg-slab mb-6 rounded-xl p-4">
<div className="mb-3 flex flex-wrap items-center justify-between gap-2">
@@ -96,10 +98,8 @@ export function CacheVolumes() {
onConfirm={() =>
cleanup.mutateAsync(undefined).then(
(r) => {
const vols = (r.report as { volumes?: { removed?: unknown[]; skipped?: unknown[] }[] }).volumes ?? [];
const removed = vols.reduce((n, v) => n + (v.removed?.length ?? 0), 0);
const skipped = vols.reduce((n, v) => n + (v.skipped?.length ?? 0), 0);
toast.success(`清理完成:移除 ${removed} 个任务的缓存${skipped ? `,${skipped} 个因保留/H&R 跳过` : ""}`);
toast.success(`已排队清理任务 ${r.taskId.slice(0, 8)}`, { description: "后台执行,结果见任务详情" });
navigate(`/console/engine/${r.runId}`);
},
(e) => toast.error(errorMessage(e)),
)