Reputation: 390
I created a bundle of 3 documents. Then I deleted 2 of them and created the bundle again. So the bundle now contains one document! And the application cache contains 3
Then I download the bundle again:
const resp = await fetch(downloadUrl);
await loadBundle(db, resp.body); //{totalDocuments: 1} - as expected
const query = await namedQuery(db, `my-bundle-query`);
if (query) {
const snap = await getDocsFromCache(query); //Nope! there should be one document, but there are three
}
Looks like a bug. I think loadBundle should somehow keep track of deleted documents. What should I do?
UPDATE:
namedQuery - query the entire cache. But the expected behavior is to get only the documents associated with the bundle. So this doesn't work at all - in my namedQuery I have a limit of 4 documents but got more from the cache!!
So the official example is wrong because it faces the same problem I described above
Upvotes: 0
Views: 219
Reputation: 26246
Unfortunately this is a limitation of the way that bundles are currently coded. It would also be out of scope for bundles as they are designed to be used against collections with large amounts of reused data for the initial load of a page.
If you think that loadBundle
should purge items from the local cache that aren't returned in the bundle, you should file a feature request to add this feature to the loadBundle
call (e.g. loadBundle(rawBundle, /* forceRefresh = */ true)
) or file a bug report.
For example's sake, lets assume your query is "Get the first 10 posts in collection /Posts".
Upon requesting the bundle for this query, the first bundle returns the following results:
{
"/Posts/D9p7MbcYCbTNzcXLrzfQ": { /* post data */ },
"/Posts/xz3eY1Gwsjl4tTxTjXyR": { /* post data */ },
"/Posts/fIvk5LF2zj2xgpgWIv9h": { /* post data */ }
}
which you then load using loadBundle
.
Next, you delete two of these documents from the server using another client (using the same client would delete them from the local cache).
Now you re-request the bundle, which returns:
{
"/Posts/fIvk5LF2zj2xgpgWIv9h": { /* post data */ }
}
Upon calling loadBundle
, the library iterates through the collection of documents in the bundle, updating the local cache for each document:
// this is psuedo-code, not the true implementation
function loadBundle(rawBundle) {
decodedBundle = parseBundle(rawBundle);
decodedBundle.docs.forEach((doc) => {
cachedDocuments.set(doc.id, doc);
})
return { // return bundle load progress
totalDocuments: decodedBundle.docs.length,
/* ... other stats ... */
};
}
In the above psuedo-code, you can see that only the documents that are included in the bundle are updated in the local cache. Documents not included in the bundle are not updated and the stats returned are related to the documents included in the bundle that was just decoded - not the results of the relevant query.
When you run the named query, the query is decoded, compared and executed against the local cache. As the former documents currently match the query according to the cache, they are included in the results.
The documents in the local cache will only be omitted when:
So for the local cache to be purged, the bundle would have to contain:
{
"/Posts/D9p7MbcYCbTNzcXLrzfQ": _DELETED,
"/Posts/xz3eY1Gwsjl4tTxTjXyR": _DELETED,
// ... for every deleted document that ever existed ...
"/Posts/fIvk5LF2zj2xgpgWIv9h": { /* post data */ }
}
Returning such a bundle would be technically complex and incredibly inefficient.
When requesting the bundle, you could include a list of document IDs, where if a given document ID doesn't exist, a document deletion is included in the bundle's data. However, in doing so, you may as well just make a normal database request to the server using getDocs
or onSnapshot
for the same result which would be faster and cheaper.
Bundles are designed to be used against collections with large amounts of reused data and generally only on the initial load of a page. If a post is deleted in the top 50 results, you would invalidate the cached results and rebuild the bundle. All new users would see the changed results immediately and only those users with the local copy would see them.
If you think that loadBundle
should purge items from the local cache that aren't returned in the bundle, you should file a feature request to add this feature to the loadBundle
call (e.g. loadBundle(rawBundle, /* forceRefresh = */ true)
).
Upvotes: 1