Cache/API implementation (#36), phase 2.
Depends on the metadata-store unit and the enumeration unit.
Goal
Library.open() and the transparent refresh loop. No sync() anywhere in the
surface (owner ruling): open() loads metadata.json, does a first refresh,
then a background timer refreshes on an interval; every read is answered from
RAM with no network in front of it (owner's TTL/staleness ruling).
cacheDirectory default from env-paths cache dir + /<userID>
(bin/quak.ts already calls envPaths("quak", { suffix: "" })).
loads the store, runs one refresh, then starts the interval.
Refresh: one /collections/v2?sinceTime=cursor (empty when nothing changed),
then a per-album diff only for albums whose updationTime advanced, applying
tombstones (drop membership; mark collection deleted). Persist cursors + data
in one rename only when something changed. Uses the enumeration variants.
refreshIntervalSeconds default 3 (owner: 3–5s recent images, ~10s album
list/membership all met by one small poll per 3s). First run with no local
copy resolves only when the first fetch completes; later runs resolve as soon
as the local copy is loaded and the first refresh has started.
A failed refresh is not visible to reads: reads keep answering from RAM; the
failure is reported once via onProgress (operation: "refresh", status: "failed") and shown in status().
status() and close() (stops the loop; in-flight work finishes). No serverReachable flag, no refresh: "beforeEachRead" mode, no lib.refresh()
(all removed by owner rulings in the final design comment).
All metadata requests go through the metadata pool once that unit lands; until
then, direct Client calls are acceptable and swapped in later.
Definition of done
open() loads + first-refreshes; interval refresh applies diffs and
tombstones; metadata.json rewritten only on change.
Reads (added in later units) never trigger a network call.
Non-advancing / failing refresh handled per above; status() reflects it.
Tested against a mock Client; make check green.
Grounding
src/library/ (the Library class). Depends on metadata-store + enumeration.
Dispatch notes: TDD; no scripted edits; no interactive questions; plain language.
Squash subject ends (closes #<this issue>). End every message with Model: opus-4-8.
Model: opus-4-8
Cache/API implementation (https://git.eeqj.de/sneak/quak/issues/36), phase 2.
Depends on the metadata-store unit and the enumeration unit.
## Goal
`Library.open()` and the transparent refresh loop. No `sync()` anywhere in the
surface (owner ruling): `open()` loads `metadata.json`, does a first refresh,
then a background timer refreshes on an interval; every read is answered from
RAM with no network in front of it (owner's TTL/staleness ruling).
## Scope
- `Library.open(args: { client; cacheDirectory?; downloadDirectory?; refreshIntervalSeconds?; onProgress? })`:
- `cacheDirectory` default from `env-paths` cache dir + `/<userID>`
(`bin/quak.ts` already calls `envPaths("quak", { suffix: "" })`).
- loads the store, runs one refresh, then starts the interval.
- Refresh: one `/collections/v2?sinceTime=cursor` (empty when nothing changed),
then a per-album diff only for albums whose `updationTime` advanced, applying
tombstones (drop membership; mark collection deleted). Persist cursors + data
in one rename only when something changed. Uses the enumeration variants.
- `refreshIntervalSeconds` default 3 (owner: 3–5s recent images, ~10s album
list/membership all met by one small poll per 3s). First run with no local
copy resolves only when the first fetch completes; later runs resolve as soon
as the local copy is loaded and the first refresh has started.
- A failed refresh is not visible to reads: reads keep answering from RAM; the
failure is reported once via `onProgress` (`operation: "refresh"`,
`status: "failed"`) and shown in `status()`.
- `status()` and `close()` (stops the loop; in-flight work finishes). No
`serverReachable` flag, no `refresh: "beforeEachRead"` mode, no `lib.refresh()`
(all removed by owner rulings in the final design comment).
- All metadata requests go through the metadata pool once that unit lands; until
then, direct `Client` calls are acceptable and swapped in later.
## Definition of done
- `open()` loads + first-refreshes; interval refresh applies diffs and
tombstones; `metadata.json` rewritten only on change.
- Reads (added in later units) never trigger a network call.
- Non-advancing / failing refresh handled per above; `status()` reflects it.
- Tested against a mock `Client`; `make check` green.
## Grounding
`src/library/` (the `Library` class). Depends on metadata-store + enumeration.
Dispatch notes: TDD; no scripted edits; no interactive questions; plain language.
Squash subject ends ` (closes #<this issue>)`. End every message with
`Model: opus-4-8`.
Model: opus-4-8
Library.open() loads the metadata store, does one refresh, then refreshes on a background timer every refreshIntervalSeconds (default 3). Reads are answered from RAM with no network in front of them. A refresh commits to the store only after all its fetches succeed, so a failed refresh is invisible to reads and surfaces only via onProgress ("failed") and status(). No sync(), no refresh(), no serverReachable. status() and close() are provided; close() stops the timer and is idempotent.
A collection's files are re-enumerated only when its updationTime advances, reusing the metadata store and the collectionsSince/filesSince enumerators unchanged.
make check passes.
Model: opus-4-8
Implemented in https://git.eeqj.de/sneak/quak/pulls/60.
`Library.open()` loads the metadata store, does one refresh, then refreshes on a background timer every `refreshIntervalSeconds` (default 3). Reads are answered from RAM with no network in front of them. A refresh commits to the store only after all its fetches succeed, so a failed refresh is invisible to reads and surfaces only via `onProgress` ("failed") and `status()`. No `sync()`, no `refresh()`, no `serverReachable`. `status()` and `close()` are provided; `close()` stops the timer and is idempotent.
A collection's files are re-enumerated only when its `updationTime` advances, reusing the metadata store and the `collectionsSince`/`filesSince` enumerators unchanged.
`make check` passes.
Model: opus-4-8
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Cache/API implementation (#36), phase 2.
Depends on the metadata-store unit and the enumeration unit.
Goal
Library.open()and the transparent refresh loop. Nosync()anywhere in thesurface (owner ruling):
open()loadsmetadata.json, does a first refresh,then a background timer refreshes on an interval; every read is answered from
RAM with no network in front of it (owner's TTL/staleness ruling).
Scope
Library.open(args: { client; cacheDirectory?; downloadDirectory?; refreshIntervalSeconds?; onProgress? }):cacheDirectorydefault fromenv-pathscache dir +/<userID>(
bin/quak.tsalready callsenvPaths("quak", { suffix: "" }))./collections/v2?sinceTime=cursor(empty when nothing changed),then a per-album diff only for albums whose
updationTimeadvanced, applyingtombstones (drop membership; mark collection deleted). Persist cursors + data
in one rename only when something changed. Uses the enumeration variants.
refreshIntervalSecondsdefault 3 (owner: 3–5s recent images, ~10s albumlist/membership all met by one small poll per 3s). First run with no local
copy resolves only when the first fetch completes; later runs resolve as soon
as the local copy is loaded and the first refresh has started.
failure is reported once via
onProgress(operation: "refresh",status: "failed") and shown instatus().status()andclose()(stops the loop; in-flight work finishes). NoserverReachableflag, norefresh: "beforeEachRead"mode, nolib.refresh()(all removed by owner rulings in the final design comment).
then, direct
Clientcalls are acceptable and swapped in later.Definition of done
open()loads + first-refreshes; interval refresh applies diffs andtombstones;
metadata.jsonrewritten only on change.status()reflects it.Client;make checkgreen.Grounding
src/library/(theLibraryclass). Depends on metadata-store + enumeration.Dispatch notes: TDD; no scripted edits; no interactive questions; plain language.
Squash subject ends
(closes #<this issue>). End every message withModel: opus-4-8.Model: opus-4-8
Implemented in #60.
Library.open()loads the metadata store, does one refresh, then refreshes on a background timer everyrefreshIntervalSeconds(default 3). Reads are answered from RAM with no network in front of them. A refresh commits to the store only after all its fetches succeed, so a failed refresh is invisible to reads and surfaces only viaonProgress("failed") andstatus(). Nosync(), norefresh(), noserverReachable.status()andclose()are provided;close()stops the timer and is idempotent.A collection's files are re-enumerated only when its
updationTimeadvances, reusing the metadata store and thecollectionsSince/filesSinceenumerators unchanged.make checkpasses.Model: opus-4-8
Landed on next via #60 (squash). Closing manually — the merge-commit keyword did not auto-close.
Model: opus-4-8