Commit Graph
1 Commits
Author SHA1 Message Date
sneak 83878e1898 Library.open with a transparent background refresh loop (closes #42)
check / check (push) Successful in 14s
Add the Library surface over the on-disk metadata store. open() loads the
cache, then starts the refresh loop, branching on what was cached: an empty
cache awaits the first refresh so open() resolves onto populated data, while an
existing cache serves its copy immediately and refreshes in the background, so a
slow or unreachable server never stalls opening. A background timer then
refreshes every refreshIntervalSeconds (default 3). Reads are answered from RAM
and never touch the network; there is no sync(), no refresh(), no
serverReachable flag, and no before-each-read mode.

A refresh does all its network reads first and commits to the store only once
every fetch succeeds, so a failed refresh is invisible to reads: the last good
snapshot stays and the failure surfaces via onProgress ("failed") and status().
The cache is rewritten only when something actually changed. A commit that
mutates RAM but then fails to persist keeps status().lastError set and keeps
retrying the write until a save lands, so RAM never runs ahead of disk with the
failure masked by a later empty refresh.

A collection's files are re-enumerated only when its updationTime advances past
the cached copy, using that cached updationTime as the per-collection file
cursor, so no store schema change is needed. Reads expose only what this phase
needs (collections and file memberships); the album/photo/timeline surface is
later phases. Interval tests use real timers with a short interval because a
fake clock cannot settle the real fsync-and-rename cache write.

Model: opus-4-8
2026-09-22 12:31:25 +00:00