Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
daa47068bc |
@@ -645,6 +645,10 @@ export class Library {
|
||||
collectionKey: collection.key,
|
||||
sinceTime: known ? known.updationTime : 0,
|
||||
});
|
||||
// A refresh that ran during the fetch may have stored a copy as new as
|
||||
// `collection` or newer. Committing this result would replace it.
|
||||
const stored = this.store.getCollection(collection.id);
|
||||
if (stored && collection.updationTime <= stored.updationTime) return;
|
||||
// The stored cursor stays where it is, so the next refresh still
|
||||
// fetches the files of every other collection that changed.
|
||||
await this.commit(
|
||||
@@ -836,9 +840,8 @@ export class Library {
|
||||
|
||||
// Commit a collections page and the file pages fetched for its collections
|
||||
// to the store, then save. A collection or file that does not decrypt is
|
||||
// left out, as if deleted, with the reason kept in the store: the cursor
|
||||
// moves past it, so no later refresh sees it again until the server's copy
|
||||
// changes.
|
||||
// left out, as if deleted, with the reason kept in the store, and no later
|
||||
// refresh sees it again until the server's copy changes.
|
||||
private async commit(
|
||||
page: CollectionsPage,
|
||||
filePages: { collectionID: number; page: FilesPage }[],
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
* fetches the files of every collection (issue #210).
|
||||
* 5. `refreshCollection()` brings one collection up to date in the store and
|
||||
* leaves the stored cursor where it was, so the next refresh still fetches
|
||||
* the files of every other collection that changed (issue #217).
|
||||
* the files of every other collection that changed (issue #217). A newer
|
||||
* copy that a refresh stores while it fetches the files is kept.
|
||||
*
|
||||
* The client is the same metadata-only mock the background-refresh tests use:
|
||||
* no crypto, no network, scripted pages, and a record of each call. A long
|
||||
@@ -424,4 +425,51 @@ describe("Library.refreshCollection", () => {
|
||||
await lib.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Collection 1 is stored at 100. `refreshCollection()` asks for it at 110,
|
||||
// which adds file 1002. While that files request waits, a refresh stores
|
||||
// it at 120, where 1002 is deleted again and 1003 added.
|
||||
it("keeps a newer copy that a refresh stores while the files are fetched", async () => {
|
||||
const { client, lib } = await openSeeded(cacheDirectory);
|
||||
let release!: () => void;
|
||||
const held = new Promise<void>((r) => (release = r));
|
||||
try {
|
||||
client.filesFor(
|
||||
1,
|
||||
{ files: [file(1002, 1, 110)], deleted: [], cursor: 110 },
|
||||
{ files: [file(1003, 1, 120)], deleted: [1002], cursor: 120 },
|
||||
);
|
||||
client.collectionsQueue.push({
|
||||
collections: [collection(1, 120)],
|
||||
deleted: [],
|
||||
cursor: 120,
|
||||
});
|
||||
|
||||
// Hold the next files request, refreshCollection's, until the
|
||||
// test releases it. The refresh's request after it is answered
|
||||
// at once.
|
||||
let fetchStarted!: () => void;
|
||||
const started = new Promise<void>((r) => (fetchStarted = r));
|
||||
const realFilesSince = client.filesSince.bind(client);
|
||||
client.filesSince = async (args) => {
|
||||
client.filesSince = realFilesSince;
|
||||
const page = await realFilesSince(args);
|
||||
fetchStarted();
|
||||
await held;
|
||||
return page;
|
||||
};
|
||||
|
||||
const refreshing = lib.refreshCollection(collection(1, 110));
|
||||
await started;
|
||||
await lib.fresh();
|
||||
release();
|
||||
await refreshing;
|
||||
|
||||
expect(lib.getCollection(1)?.updationTime).toBe(120);
|
||||
expect(lib.listFiles(1).map((f) => f.id)).toEqual([1001, 1003]);
|
||||
} finally {
|
||||
release();
|
||||
await lib.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user