feat(web): surface Discover freshness ("last discovered N ago") + true in-progress
/discover felt "stale until I hit Discover now": it showed the result string but
never WHEN the sweep last ran, and "Discovering…" ended the moment the worker
claimed the request (requested→false) rather than when the sweep finished.
- /api/discover/run GET now also returns `inProgress` (discover.inProgress) and
`lastRunAt` (the discover.result Config row's updatedAt = last completion).
- The client treats requested||inProgress as "running", so "Discovering…"
persists for the whole sweep, and polls until both clear before refreshing.
- The tool row shows "Last discovered {N ago} · {result}", a sweeping message
while running, and a clear "Not yet run" empty state.
web 151 tests (inProgress + lastRunAt asserted), tsc + build clean. No worker
change (signals already written); NOT a page cache (would worsen staleness).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,10 +12,20 @@ describe("discover run API", () => {
|
||||
const body = await (await GET()).json();
|
||||
expect(body.requested).toBe(true);
|
||||
expect(body.result).toBeNull();
|
||||
expect(body.inProgress).toBe(false);
|
||||
expect(body.lastRunAt).toBeNull();
|
||||
});
|
||||
|
||||
it("GET returns discover.result when the worker has written it", async () => {
|
||||
it("GET returns discover.result + lastRunAt when the worker has written it", async () => {
|
||||
await prisma.config.create({ data: { key: "discover.result", value: "artists 3, albums 1" } });
|
||||
expect((await (await GET()).json()).result).toBe("artists 3, albums 1");
|
||||
const body = await (await GET()).json();
|
||||
expect(body.result).toBe("artists 3, albums 1");
|
||||
expect(body.lastRunAt).not.toBeNull();
|
||||
expect(Number.isNaN(Date.parse(body.lastRunAt))).toBe(false); // a real ISO timestamp
|
||||
});
|
||||
|
||||
it("GET reports inProgress from discover.inProgress", async () => {
|
||||
await prisma.config.create({ data: { key: "discover.inProgress", value: "true" } });
|
||||
expect((await (await GET()).json()).inProgress).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,12 +10,19 @@ export async function POST(_request: Request) {
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
const [requested, result] = await Promise.all([
|
||||
const [requested, inProgress, result] = await Promise.all([
|
||||
prisma.config.findUnique({ where: { key: "discover.requested" } }),
|
||||
prisma.config.findUnique({ where: { key: "discover.inProgress" } }),
|
||||
prisma.config.findUnique({ where: { key: "discover.result" } }),
|
||||
]);
|
||||
return Response.json({
|
||||
// a sweep is either queued (requested) or actively running (inProgress) — the UI treats
|
||||
// both as "running" so "Discovering…" persists for the whole sweep, not just until the
|
||||
// worker claims the request.
|
||||
requested: requested?.value === "true",
|
||||
inProgress: inProgress?.value === "true",
|
||||
result: result?.value ?? null,
|
||||
// when the last completed sweep wrote its result — the "last discovered N ago" signal.
|
||||
lastRunAt: result?.updatedAt?.toISOString() ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user