quak files COLLECTION fetches that collection's files alone (closes #217)
check / check (push) Canceled after 0s
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()`, which brings that one collection up to date in the store as a refresh would, and saves it. It sends no request for the files when the stored copy is current. It leaves the refresh cursor alone, so the next refresh still fetches every other collection that changed. `refreshOnce` and `refreshCollection` share the commit step. `quak files` with no argument still waits for a refresh. Model: opus-5-5
This commit is contained in:
+34
-19
@@ -3,13 +3,16 @@
|
||||
* issue #36, issue #52).
|
||||
*
|
||||
* The `collections`, `files`, `get`, and `get-thumb` commands must answer for
|
||||
* current server state, not the local cache. `files`, `get` and `get-thumb`
|
||||
* force a `Library.fresh()` round-trip before they read; the stand-in library
|
||||
* below serves nothing until `fresh()` has been awaited, so a helper that read
|
||||
* without refreshing would come back empty and fail here. `collections` asks
|
||||
* the library for the collection list alone (`freshCollections()`, issue
|
||||
* #210), and must not wait for a refresh, which would fetch the files of every
|
||||
* collection.
|
||||
* current server state, not the local cache. `files` without a collection ID,
|
||||
* `get` and `get-thumb` force a `Library.fresh()` round-trip before they read;
|
||||
* the stand-in library below serves nothing until `fresh()` has been awaited,
|
||||
* so a helper that read without refreshing would come back empty and fail
|
||||
* here. `collections` asks the library for the collection list alone
|
||||
* (`freshCollections()`, issue #210), and must not wait for a refresh, which
|
||||
* would fetch the files of every collection. `files COLLECTION` reads that list
|
||||
* too and then brings that one collection up to date
|
||||
* (`refreshCollection()`, issue #217); the stand-in serves a collection's files
|
||||
* once either has run.
|
||||
*
|
||||
* `collections` and `files` also list in the library's enumeration order
|
||||
* (`listCollections`/`listFiles`) — the order the pre-library CLI printed — not
|
||||
@@ -64,12 +67,14 @@ const file = (
|
||||
|
||||
// A library that reveals its records only after `fresh()` has been awaited, and
|
||||
// serves them in the enumeration order it was given. `freshCollections()`
|
||||
// answers the collection list in that order without a refresh. `photos.byID`
|
||||
// returns a stand-in `Photo` carrying just the fileID the helper passes
|
||||
// through.
|
||||
// answers the collection list in that order without a refresh.
|
||||
// `refreshCollection()` reveals the files of that one collection.
|
||||
// `photos.byID` returns a stand-in `Photo` carrying just the fileID the helper
|
||||
// passes through.
|
||||
class FakeLibrary implements FreshReadLibrary {
|
||||
freshCalls = 0;
|
||||
freshCollectionsCalls = 0;
|
||||
refreshCollectionIDs: number[] = [];
|
||||
private refreshed = false;
|
||||
|
||||
constructor(
|
||||
@@ -88,9 +93,8 @@ class FakeLibrary implements FreshReadLibrary {
|
||||
return this.collections;
|
||||
}
|
||||
|
||||
getCollection(id: number): Collection | undefined {
|
||||
if (!this.refreshed) return undefined;
|
||||
return this.collections.find((c) => c.id === id);
|
||||
async refreshCollection(collection: Collection): Promise<void> {
|
||||
this.refreshCollectionIDs.push(collection.id);
|
||||
}
|
||||
|
||||
listCollections(): Collection[] {
|
||||
@@ -98,7 +102,9 @@ class FakeLibrary implements FreshReadLibrary {
|
||||
}
|
||||
|
||||
listFiles(collectionID: number): EnteFile[] {
|
||||
return this.refreshed
|
||||
const current =
|
||||
this.refreshed || this.refreshCollectionIDs.includes(collectionID);
|
||||
return current
|
||||
? this.files.filter((f) => f.collectionID === collectionID)
|
||||
: [];
|
||||
}
|
||||
@@ -138,18 +144,25 @@ describe("CLI read helpers (issue #36 amendment, issue #52)", () => {
|
||||
expect(rows.map((c) => c.id)).not.toEqual(newestFirst);
|
||||
});
|
||||
|
||||
it("freshFiles refreshes first, lists in enumeration order, keeps raw fields", async () => {
|
||||
it("freshFiles brings the collection alone up to date, lists in enumeration order, keeps raw fields", async () => {
|
||||
// Enumeration order by id 10, 11, 12; creationTimes ascending, so a
|
||||
// newest-first sort would reverse them.
|
||||
// newest-first sort would reverse them. Collection 2's file is not
|
||||
// listed.
|
||||
const files = [
|
||||
file(10, 1, 1_700_000_000_000_000),
|
||||
file(11, 1, 1_700_000_000_000_001),
|
||||
file(12, 1, 1_700_000_000_000_002),
|
||||
file(20, 2, 1_700_000_000_000_003),
|
||||
];
|
||||
const lib = new FakeLibrary([collection(1, 100)], files);
|
||||
const lib = new FakeLibrary(
|
||||
[collection(1, 100), collection(2, 100)],
|
||||
files,
|
||||
);
|
||||
|
||||
const rows = await freshFiles(lib, 1);
|
||||
expect(lib.freshCalls).toBe(1);
|
||||
expect(lib.freshCollectionsCalls).toBe(1);
|
||||
expect(lib.refreshCollectionIDs).toEqual([1]);
|
||||
expect(lib.freshCalls).toBe(0);
|
||||
expect(rows?.map((f) => f.id)).toEqual([10, 11, 12]);
|
||||
|
||||
// Field values come from raw metadata: microsecond creationTime and the
|
||||
@@ -206,7 +219,9 @@ describe("CLI read helpers (issue #36 amendment, issue #52)", () => {
|
||||
it("freshFiles returns undefined for an unknown collection", async () => {
|
||||
const lib = new FakeLibrary([collection(1, 100)], []);
|
||||
const rows = await freshFiles(lib, 999);
|
||||
expect(lib.freshCalls).toBe(1);
|
||||
expect(lib.freshCollectionsCalls).toBe(1);
|
||||
expect(lib.refreshCollectionIDs).toEqual([]);
|
||||
expect(lib.freshCalls).toBe(0);
|
||||
expect(rows).toBeUndefined();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user