page() ran the 500 ms pacing gate before the cache check, so every hit
waited too: a fill rerun skipping 166 cached pages took ~80 s and
looked like a start from scratch. The gate now sits after the hit
check (re-checking storage once through it, in case a request ahead
had just etched the page).
Regression test: the fixed-clock test cache records its sleeps; a miss
sleeps once, three hits add none (failed before: 4 sleeps).
Generated-by: Claude Opus 5.5
Past the transitional idiom: the cache logic (DiigoCacheLogic,
PublicCacheLogic in cache.ts) requires its Clock, with no default, so
cache.ts reaches no ambient time. The worker's entry module is the
edge: it makes the live clock and exports the runtime-constructed
DiigoCache/PublicCache as (ctx, env) subclasses that supply it (the
Cloudflare constraint: the runtime constructs DOs with ctx and env
only). Binding class names are unchanged, so stored state is too. The
tests' FixedClockCache extends the logic class.
Generated-by: Claude Opus 5.5
Ocap discipline: no ambient time in logic. PagedCache reads time and
waits only through a Clock { now, sleep }, a default constructor
argument (the live clock; the runtime constructs DOs with ctx and env
only). The fill job's timestamps and alarms, the etch time, and the
diigo-call pacing all go through it.
Tests interpose through the constructor: tests/test-worker.ts (now the
tests' main module) adds FixedClockCache, bound as CLOCKED_DO, and a
test pins startedAt, updatedAt, and the alarm time to the fixed clock
(an ambient new Date() fails it).
Generated-by: Claude Opus 5.5