Commit Graph
9 Commits
Author SHA1 Message Date
dckc f5d57f73d3 diigo-cache: a short page before the stated end peeks at the next page
The real fill failed at "diigo returned 44 items for page 167 of 168":
diigo's `total` overstates what load_user_items returns, so the true
last page looked short and the guard took it for a capped page size.

A short page that isn't the last by `total` now fetches the next page
(paced like any diigo call): empty means the data really ends there —
accepted, with a "total-overstated" notice logging total vs actual;
anything else means items would be skipped — refused, the message now
giving both counts. The fake gains an account whose total claims 60
more than it has; a fill on it runs to done.

Generated-by: Claude Opus 5.5
2026-10-07 05:04:04 -05:00
dckc 563cb83995 diigo-cache: page size 100, diigo's cap; fill jobs record their page size
Asked for 128, diigo returned 100 (the short-page guard caught it on the
first real fill), so PAGE_SIZE = 100: ~168 pages for 16.7k bookmarks.

The same run showed a fill job outliving a page-size change: progress
counted in 24s ("page 25 of 698") resumed as if counted in 128s. Stored
state reinterpreted, so: FillStatus records pageSize (additive; jobs
saved without it counted in 24), and a job whose size differs from
PAGE_SIZE fails with "page size changed …; start the fill again"
instead of resuming; starting again replaces it. Tested with the old
shape in storage.

Generated-by: Claude Opus 5.5
2026-10-07 04:59:39 -05:00
dckc 826153e35f diigo-cache: fetch 128 items per diigo page; refuse short pages
PAGE_SIZE = 128 (was 24), one constant for the fill job, public pages,
dumps, and DiigoBridge, so a cache never mixes sizes: ~131 pages instead
of ~698 for 16.7k bookmarks.

Cache invalidation, agreed beforehand: pages are cached by (page number,
size), so pages cached at 24 become misses and refetch at 128. Items are
keyed by link_id and just re-upsert; nothing is lost.

Unknown whether diigo honors count=128, so a short page that isn't the
last is refused loudly (logged, thrown; a fill fails with the reason)
rather than silently skipping items. The fake gains a capped account to
test it; the plain account grows to 300 (3 pages), the deep one to 6000.

Generated-by: Claude Opus 5.5
2026-10-07 04:56:56 -05:00
dckc efaf74023d diigo-cache: webkey page logs in with the password manager
/cache/ without a fragment is now a login form: petname
(autocomplete=username) and cache id (type=password,
autocomplete=current-password), the shape password managers fill from
the entries the save button makes. Its inputs have no name, so a native
submit (script failed) sends nothing; the key stays in memory, out of
the address bar and history. Home links to it.

Generated-by: Claude Opus 5.5
2026-10-07 04:48:15 -05:00
dckc 961515d8db fixup! diigo-cache: the caches take their clock as a constructor argument
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
2026-10-07 04:39:29 -05:00
dckc b6823867ff diigo-cache: the caches take their clock as a constructor argument
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
2026-10-07 04:34:48 -05:00
dckc 8c221abe6f diigo-cache: fill from a webkey page over Cap'n Web
Starting a fill no longer POSTs the cache id to /_fill. Instead:

- the created page links the cache's webkey, /cache/#<cache id>: a
  skeleton page, the same for every key, that reads the key from the
  fragment (never sent to the server or in a Referer)
- its script trades the key in-band for a capability over Cap'n Web at
  /api: CacheApi.cache(key) returns a CacheCap facet (fill, status,
  fingerprint, the public companion's fill) and never the DO's wiring
  methods; malformed and unknown keys get one refusal that never echoes
  the key, and each refusal is logged without it
- then calls startFill(): trade and call pipeline into one round trip
- the worker serves capnweb's browser build itself at /_capnweb.js (a
  wrangler Text rule), so no third-party script sits beside the key

The /_fill route and its forms are gone. Tests run the real capnweb
client against the worker (fetch routed to worker.fetch).

Generated-by: Claude Opus 5.5
2026-10-07 04:32:44 -05:00
dckc 31ded9735b diigo-cache: fill job — a button that grabs every page (goal 1e)
POST /_fill (cache id in the body; target private|public; action
start|stop) starts or stops a background walk of every diigo page into
the cache. DO alarms advance it pagesPerStep pages per step (default
20), a second apart; progress (FillStatus) is stored in the DO after
each page, so it survives eviction. Cached pages are skipped; starting
while running rejoins the job; a stop mid-step wins; a failure is
recorded with its reason and logged once. The created page gets fill
buttons; the public page shows "filling: n of m pages".

Fill state is new, additive DO storage (fill, fillStep): no existing
state changes meaning.

The 13 fill specs are unskipped and green, plus one: a fill makes one
diigo call per page fetched.

Generated-by: Claude Opus 5.5
2026-10-07 04:25:38 -05:00
dckc cf5ccce4e2 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
2026-10-07 04:19:54 -05:00