1 Commits
Author SHA1 Message Date
sneak b4b279cc05 quak files COLLECTION fetches that collection's files alone (closes #217)
check / check (push) Canceled after 0s
`quak files COLLECTION` used to wait for a full refresh, which on an
empty cache fetched the files of every collection before it listed one.
It now reads the collection list, then calls the new
`Library.refreshCollection()`. That brings one collection up to date in
the store as a refresh would, and saves it. It runs in the same slot as
a refresh, so the two never run at the same time, and `close()` waits
for it. It never stores a collection that a refresh has already dropped.
It leaves the refresh cursor alone. `open()` therefore awaits the first
refresh on a cache whose cursor is still 0. `quak files` with no
argument still waits for a refresh.

Model: opus-5-5
2026-10-26 01:46:20 +00:00
2 changed files with 12 additions and 14 deletions
+5 -6
View File
@@ -1099,12 +1099,11 @@ against a fake of the Ente HTTP API, and `yarn test` verifies them.
loop, and resolves to a `Library`. On an empty cache it awaits the first
refresh, so it opens onto the account's data whenever the server is reachable.
It also awaits it on a cache that holds only what `lib.refreshCollection()`
stored, so it never serves one collection as the whole account. If that refresh
fails, it opens onto what the cache holds and records the error in
`lib.status()`. On any other cache it returns immediately and refreshes in the
background, so an unreachable server does not block opening. With
`refreshOnOpen: false` it starts no refresh and returns at once onto what the
cache holds, empty or not; a refresh then starts only when `fresh()` or
stored. If that refresh fails, it opens onto what the cache holds and records
the error in `lib.status()`. On any other cache it returns immediately and
refreshes in the background, so an unreachable server does not block opening.
With `refreshOnOpen: false` it starts no refresh and returns at once onto what
the cache holds, empty or not; a refresh then starts only when `fresh()` or
`lib.backup()` asks, or the background timer fires. The CLI's read commands open
it so (see "CLI surface").
+7 -8
View File
@@ -944,10 +944,10 @@ export class Library {
if (changed) this.unsaved = true;
// Reproject and notify subscribers of the delta. This tracks RAM (what
// reads see), so it fires whether or not the save below succeeds; a
// save failure surfaces separately through `status().lastError`.
// `lastRecords` advances every changed refresh so the next diff is
// against current state.
// reads see), so it fires whether or not the save below succeeds. A
// failed save rejects the caller, and a refresh also records it in
// `status().lastError`. `lastRecords` advances every changed refresh so
// the next diff is against current state.
if (changed) {
const next = this.deriveNow();
if (this.subscribers.size > 0) {
@@ -964,10 +964,9 @@ export class Library {
// Persist whenever RAM holds changes disk has not accepted — including
// changes an earlier cycle staged whose save failed. `unsaved` clears
// only once a save lands, so a save failure both stays visible through
// `status().lastError` (the throw below records it) and keeps being
// retried, instead of a later empty refresh silently clearing it while
// the on-disk cache is still behind RAM.
// only once a save lands, so a later commit retries a failed save even
// when it changes nothing. A failed save rejects the caller, and a
// refresh also records it in `status().lastError`.
if (this.unsaved) {
await this.store.save();
this.unsaved = false;