Report renderer progress and detect stalled jobs
This commit is contained in:
@@ -5,8 +5,10 @@ import { createBrowserClient } from "@supabase/ssr";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { api } from "./StartGame";
|
||||
import type { MapListing } from "@/lib/catalog";
|
||||
import type { ProcessingJob } from "@/shared/processing-progress";
|
||||
import { ProcessingProgress } from "./ProcessingProgress";
|
||||
type Draft = MapListing & {
|
||||
upload_jobs: { state: string; progress: number; error: string | null } | null;
|
||||
upload_jobs: ProcessingJob | null;
|
||||
};
|
||||
export function Dashboard() {
|
||||
const [maps, setMaps] = useState<Draft[]>([]),
|
||||
@@ -101,12 +103,8 @@ export function Dashboard() {
|
||||
</span>
|
||||
<h3>{m.name}</h3>
|
||||
<span className="badge">{m.state}</span>{" "}
|
||||
<span className="muted">
|
||||
{m.panorama_count} locations{" "}
|
||||
{m.upload_jobs?.state === "running"
|
||||
? `· ${m.upload_jobs.progress}% processed`
|
||||
: ""}
|
||||
</span>
|
||||
<span className="muted">{m.panorama_count} locations</span>
|
||||
<ProcessingProgress job={m.upload_jobs} />
|
||||
{m.rejection_reason && (
|
||||
<p className="error-message">{m.rejection_reason}</p>
|
||||
)}
|
||||
|
||||
@@ -3,6 +3,8 @@ import { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { api } from "./StartGame";
|
||||
import type { DatasetManifest } from "@/shared/protocol";
|
||||
import type { ProcessingJob } from "@/shared/processing-progress";
|
||||
import { ProcessingProgress } from "./ProcessingProgress";
|
||||
type Draft = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -13,6 +15,7 @@ type Draft = {
|
||||
map: string | null;
|
||||
manifest: DatasetManifest;
|
||||
previews: { id: string; image: string | null }[];
|
||||
upload_jobs: ProcessingJob | null;
|
||||
};
|
||||
export function DraftEditor({ id }: { id: string }) {
|
||||
const [draft, setDraft] = useState<Draft | null>(null),
|
||||
@@ -29,6 +32,7 @@ export function DraftEditor({ id }: { id: string }) {
|
||||
api<Draft>("datasets/" + id)
|
||||
.then((d) => {
|
||||
if (disposed) return;
|
||||
setError("");
|
||||
setDraft(d);
|
||||
setName(d.name);
|
||||
setDescription(d.description);
|
||||
@@ -37,7 +41,10 @@ export function DraftEditor({ id }: { id: string }) {
|
||||
timer = setTimeout(load, 5000);
|
||||
})
|
||||
.catch((e) => {
|
||||
if (!disposed) setError(e.message);
|
||||
if (!disposed) {
|
||||
setError(e.message);
|
||||
timer = setTimeout(load, 5000);
|
||||
}
|
||||
});
|
||||
load();
|
||||
return () => {
|
||||
@@ -89,6 +96,7 @@ export function DraftEditor({ id }: { id: string }) {
|
||||
return (
|
||||
<>
|
||||
<span className="badge">{draft.state}</span>
|
||||
<ProcessingProgress job={draft.upload_jobs} />
|
||||
{["uploading", "processing"].includes(draft.state) && (
|
||||
<p role="status" className="success-message">
|
||||
{draft.state === "uploading"
|
||||
|
||||
42
components/ProcessingProgress.tsx
Normal file
42
components/ProcessingProgress.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
"use client";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
processingStage,
|
||||
type ProcessingJob,
|
||||
} from "@/shared/processing-progress";
|
||||
|
||||
export function ProcessingProgress({ job }: { job: ProcessingJob | null }) {
|
||||
const [now, setNow] = useState<number | null>(null);
|
||||
useEffect(() => {
|
||||
setNow(Date.now());
|
||||
const timer = setInterval(() => setNow(Date.now()), 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
if (!job || !["queued", "running"].includes(job.state)) return null;
|
||||
const progress = Math.max(0, Math.min(100, job.progress));
|
||||
const stopped =
|
||||
now !== null &&
|
||||
job.state === "running" &&
|
||||
(!job.lease_until || Date.parse(job.lease_until) < now);
|
||||
return (
|
||||
<div className="processing-progress" role="status" aria-live="polite">
|
||||
<p>
|
||||
{job.state === "queued"
|
||||
? "Waiting for a processing worker"
|
||||
: `${progress}% · ${processingStage(progress)}`}
|
||||
</p>
|
||||
<progress
|
||||
max={100}
|
||||
value={progress}
|
||||
aria-label="Map processing progress"
|
||||
/>
|
||||
<p className="muted">
|
||||
{stopped
|
||||
? "The worker has stopped reporting. Check its terminal and restart it if necessary. Your uploaded export is saved."
|
||||
: job.state === "running"
|
||||
? "Worker connected. Large exports can take a while; progress measures completed work."
|
||||
: "Processing will start when a worker is available."}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user