-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Fix RTDB query getData
caching behavior
#9707
Conversation
Generated by 🚫 Danger |
@@ -533,7 +533,7 @@ - (void)getData:(FIRDatabaseQuery *)query | |||
}]; | |||
return; | |||
} | |||
[self.persistenceManager setQueryActive:querySpec]; | |||
NSNumber *tag = [self.serverSyncTree registerQuery:[query querySpec]]; |
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 don't think get queries are tagged on the backend, but it looks like the tag is only used retrieve the query spec in applyTaggedQueryOverwriteAtPath
.
forNonExistingViewForQuery:(FQuerySpec *)query | ||
writesCache:(FWriteTreeRef *)writesCache | ||
serverCache:(FCacheNode *)serverCache { | ||
- (void)registerQuery:(FQuerySpec *)query |
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.
This method does everything that addEventRegistration
did before actually adding an event registration to the view.
Size Report 1Affected ProductsTest Logs |
@@ -199,6 +205,15 @@ - (NSArray *)addEventRegistration:(id<FEventRegistration>)eventRegistration | |||
return [view initialEvents:eventRegistration]; | |||
} | |||
|
|||
- (BOOL)unregisterQuery:(FQuerySpec *)query { |
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.
This method just removes the query from the view map if no other query added an event registration to it.
There is quite a bit of logic that isn't brought over from removeEventRegistration
. In particular, we are not:
- Removing all empty views from a syncpoint if the getData query is default.
- Generating any
FCancelEvent
s for the query since there is no event registration associated with it.
I'm least sure about this function.
Coverage Report 1Affected Products
Test Logs |
@jsdt I am hoping you could give me some early feedback on this change. I added a test that checks for the reported issue. More in progress. |
} | ||
if (removed) { | ||
[self removeTags:@[ query ]]; | ||
[self.persistenceManager setQueryInactive:query]; |
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.
Note: only call setQueryInactive when we just removed the last query in the view. This is consistent with how removeEventRegistration
works.
|
||
@implementation FIRDatabaseGetTests | ||
|
||
- (void)testGetDoesntTriggerExtraListens { |
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.
Can we also add a test to ensure that a subsequent listen for the same query returns the cached data immediately?
@@ -70,5 +70,9 @@ | |||
- (BOOL)viewExistsForQuery:(FQuerySpec *)query; | |||
- (BOOL)hasCompleteView; | |||
- (FView *)completeView; | |||
- (void)registerQuery:(FQuerySpec *)query |
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.
Can you add comments for any new functions?
#import "FirebaseDatabase/Tests/Helpers/FTestExpectations.h" | ||
#import "FirebaseDatabase/Tests/Helpers/FTupleEventTypeString.h" | ||
|
||
@implementation FIRDatabaseGetTests |
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.
Do we have a test where we perform a get, then perform a listen before the get is finished?
@@ -448,6 +457,42 @@ - (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path | |||
} | |||
} | |||
|
|||
- (NSNumber *)registerQuery:(FQuerySpec *)query { |
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.
Query is used a lot, including for listeners. Should we call this something like "registerGet"?
atPath:path]; | ||
} | ||
NSNumber *tag = nil; | ||
BOOL viewAlreadyExists = [syncPoint viewExistsForQuery:query]; |
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.
Seems like the code up until here is reused from addEventRegistration
, can we extract this out?
whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { | ||
foundAncestorDefaultView = | ||
foundAncestorDefaultView || [syncPoint hasCompleteView]; | ||
return !foundAncestorDefaultView; |
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 don't actually think we're using this block, since we aren't checking foundAncestorDefaultView
later in the function
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.
Yes, will remove this.
writesCache:writesCache | ||
serverCache:serverCache]; | ||
} else if (![query loadsAllData]) { | ||
tag = [self tagQuery:query]; |
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.
This needs to be moved into the
if (!viewAlreadyExists) {
...
}
bock above.
This is an attempt at fixing #8286. The root cause is that get doesn't update cache correctly, always calling FSyncTree applyServerOverwriteAtPath, even when
getData
was called on a query.There is an alternative method for updating cache called applyTaggedQueryOverwriteAtPath. This method is called in onDataUpdate when the server sends a listener overwrite for a query.
In order to use this method, we need to create an
FView
for thegetData
query. I added 4 methods:To maintain the view without adding an event registration.