diigo-cache: fill job, designed as skipped specs (goal 1e)

A button that grabs every page into a cache: owner-only POST /_fill
(cache id in the body; target private|public; action start|stop),
advanced by DO alarms a few pages per step, progress stored in the DO
(new, additive state) so it survives eviction, cached pages skipped,
a rerun rejoins the running job, failures recorded and logged once.
The created page gets the button; the public page shows progress.

startFill/fillStatus/stopFill on PagedCache are JSDoc'd stubs; 13
specs are describe.skip until it lands (alarms driven by
runDurableObjectAlarm, eviction by evictDurableObject).

Generated-by: Claude Opus 5.5
This commit is contained in:
dckc committed 2026-10-07 04:19:54 -05:00
1 parent 3e5e139dea
commit cf5ccce4e2
2 files changed
+209

No files matched your search

+39
View File
@@ -53,6 +53,25 @@ export type CachePage = {
const MS_PER_CALL = 500;
/**
* a fill job's progress (goal 1e, **not yet implemented**: the design is
* pinned by the skipped suite in tests/fill.test.ts). Stored in the DO
* (new state, additive), so it survives eviction; advanced by alarms.
*/
export type FillStatus = {
state: "running" | "done" | "stopped" | "failed";
/** the next diigo page to fetch (pages already cached are skipped) */
nextPage: number;
/** diigo's page count, known after page 1 */
pages: number | null;
/** pages fetched from diigo by this job (cache hits not counted) */
fetched: number;
startedAt: string;
updatedAt: string;
/** why it failed: safe to show and log (no ids, no header values) */
error?: string;
};
function sleep(ms: number): Promise<void> {
return new Promise((r) => setTimeout(r, ms));
}
@@ -104,6 +123,26 @@ abstract class PagedCache extends DurableObject<CacheEnv> {
/** which cache this is, for logs (never the id: that's the bearer key) */
protected abstract readonly kind: "private" | "public";
/**
* start (or rejoin) the fill job: walk every diigo page into this
* cache, `pagesPerStep` per alarm (default 20, 1–50). Starting while a
* job runs returns that job unchanged. Goal 1e; not yet implemented.
*/
async startFill(opts: { pagesPerStep?: number } = {}): Promise<FillStatus> {
void opts;
throw new Error("startFill: not implemented (goal 1e)");
}
/** the fill job's progress, or undefined if none was ever started */
async fillStatus(): Promise<FillStatus | undefined> {
throw new Error("fillStatus: not implemented (goal 1e)");
}
/** stop the fill job after its current step; cached pages stay */
async stopFill(): Promise<FillStatus> {
throw new Error("stopFill: not implemented (goal 1e)");
}
/**
* read page `pageNum` (`count` per page, diigo's updated-desc order):
* storage first; on miss, fetch through the webapp instance (etching