-
Notifications
You must be signed in to change notification settings - Fork 930
Allow remote updates from watch to heal a cache with synthesized deletes in it #1015
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
448c522
6ce8ed4
44850e5
9bc9ba4
fd9de63
e694ead
8cbb935
168d86d
ac4aa80
0dc3eed
317467e
7bfb951
5b38dba
b825a94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -271,18 +271,54 @@ describeSpec('Listens:', [], () => { | |
// (the document falls out) and send us a snapshot that's ahead of | ||
// docAv3 (which is already in our cache). | ||
.userListens(visibleQuery, 'resume-token-1000') | ||
.watchAcksFull(visibleQuery, 5000, docAv2) | ||
.watchAcks(visibleQuery) | ||
.watchSends({ affects: [visibleQuery] }, docAv2) | ||
.watchSnapshots(5000) | ||
.watchSends({ affects: [visibleQuery] }, docAv3) | ||
.watchCurrents(visibleQuery, 'resume-token-5000') | ||
.watchSnapshots(6000) | ||
.expectEvents(visibleQuery, { fromCache: false }) | ||
.userUnlistens(visibleQuery) | ||
.watchRemoves(visibleQuery) | ||
// Listen to allQuery again and make sure we still get docAv3. | ||
.userListens(allQuery, 'resume-token-4000') | ||
.expectEvents(allQuery, { added: [docAv3], fromCache: true }) | ||
.watchAcksFull(allQuery, 6000) | ||
.watchAcksFull(allQuery, 7000) | ||
.expectEvents(allQuery, { fromCache: false }) | ||
); | ||
}); | ||
|
||
specTest('Deleted documents in cache are fixed', [], () => { | ||
const allQuery = Query.atPath(path('collection')); | ||
const docAv1 = doc('collection/a', 1000, { key: 'a' }); | ||
const docDeleted = deletedDoc('collection/a', 2000); | ||
|
||
return ( | ||
spec() | ||
// Presuppose an initial state where the remote document cache has a | ||
// broken synthesized delete at a timestamp later than the true version | ||
// of the document. This requires both adding and later removing the | ||
// document in order to force the watch change aggregator to propagate | ||
// the deletion. | ||
.withGCEnabled(false) | ||
.userListens(allQuery) | ||
.watchAcksFull(allQuery, 1000, docAv1) | ||
.expectEvents(allQuery, { added: [docAv1], fromCache: false }) | ||
.watchSends({ removed: [allQuery] }, docDeleted) | ||
.watchSnapshots(2000, [allQuery], 'resume-token-2000') | ||
.watchSnapshots(2000) | ||
.expectEvents(allQuery, { removed: [docAv1], fromCache: false }) | ||
.userUnlistens(allQuery) | ||
.watchRemoves(allQuery) | ||
|
||
// Now when the client listens expect the cached NoDocument to be | ||
// discarded because the global snapshot version exceeds what came before. | ||
.userListens(allQuery, 'resume-token-2000') | ||
.watchAcksFull(allQuery, 3000, docAv1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry - wouldn't this send an existence filter with count of 1 and not send this document (since the resume token is newer than the document)? It looks like a query with a single NoDocument associated has an document count of 1, and we will not reset the query (only verified by glancing through the code). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's probably true... It would either send us an existence filter, or it could send us a RESET and then the contents. You could fix it by using a different query than allQuery above to generate the initial state we want (and then we wouldn't include an existence filter here). BUT in general this test is an invalid set of watch events since we're intentionally getting the cache into a bad state. So I'm not sure we care. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've changed this to use a separate setup query to sidestep the existence filter issue. |
||
.expectEvents(allQuery, { added: [docAv1], fromCache: false }) | ||
); | ||
}); | ||
|
||
specTest('Listens are reestablished after network disconnect', [], () => { | ||
const expectRequestCount = requestCounts => | ||
requestCounts.addTarget + requestCounts.removeTarget; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not convinced watch will send us this. It would have to keep track of any document that it previously told us was in the query and somehow continue to send us changes for it even though it's no longer in the query, wouldn't it? Or maybe once it sends us a CURRENT it's allowed to stop? I don't really know what guarantee we're expecting and how watch would implement it.
In any case, I think this test as modified no longer reflects the comment a few lines above. We should probably get @jdimond's blessing and then update the comment as well if we're changing this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this scenario is possible as written then I can't make this change. I could adapt the change to only allow a bypass of the version check in the case of a delete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. 😦
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Take 4 ready for review. This passes all the tests we've thrown at it but does so by introducing a notion of authoritative updates--updates sent by watch in a configuration that we can blindly trust.