-
Notifications
You must be signed in to change notification settings - Fork 889
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
Queries to the same database path get mixed up and return incorrect results depending on order of execution #6038
Comments
@stevenpal Thank you for this report. It looks like the get() query removes data from the cache, when it really should not since it does not actually fetch the full data set. I will pass this on to our RTDB engineers. |
I heard back from the Firebase support team with a useful workaround that I thought I would share here in case anyone else is facing this issue. The workaround is to use So instead of doing something like the following with const snap1 = await get(dbRef1); You can instead just use const snap1 = await new Promise((resolve, reject) => {
onValue(dbRef1, (snap) => resolve(snap), { onlyOnce: true });
}); I tested this with the above code example and confirmed that it works. |
This error still exists in SDK v9.8.3 |
@stevenpal - we have made several improvements on the existing |
@maneesht Thanks so much for the update! I just tested this with Firebase 9.9.3 and using |
[REQUIRED] Describe your environment
[REQUIRED] Describe the problem
Queries to the same realtime database path get mixed up and return incorrect results depending on the order in which you define queries, execute
get
requests, and triggeronChild
listener callbacks. In developing an app that makes bothget
requests and that haveonChild
callbacks triggered on the same realtime database path, I found that depending on the order in which database references and queries are defined and executed, you get unexpected behavior and incorrect results.It appears that if a database query is defined while another query or reference is being executed (either via a
get
or via anonChild
listener returning results), the newly defined query somehow overwrites other references or queries that were defined, causing both the currently executing query oronChild
listener to return incorrect results and subsequent queries to the same path to return incorrect (or no) results.This means as a developer you have to ensure that only one query can ever be executing at any given time against a database path. This is extremely problematic or near impossible to ensure in an app that involves collaboration between multiple users across different instances/apps.
This issue was observed on v9. I haven't tried reverting to v8 to see if the issue exists there as well.
Steps to reproduce:
Step 1. Create realtime database with sample data and rules
Create a database (or use an existing one). At the database path
/todos
, import the following sample data.Create rules that allow reads of the path
/todos
and an index on the propertyisCompleted
:Step 2. Create test that performs both a get and onChild subscription
The following code creates one database reference and two queries. The database reference is used for the
onChild
subscriptions and the queries are used to performget
s with two different filter criteria (i.e. one that gets open todos and another that gets closed todos).Create a test that calls the
createErrorAsync
function.Expected Results:
After running, I would expect the following output when the
createErrorAsync
function is called. TheonChild
callbacks should return all six entities, the firstget
should return four entities, and the secondget
should return two entities.Actual Results:
What is actually returned is that the
onChild
listeners trigger sixonChildAdded
callbacks followed by twoonChildRemoved
callbacks (when nothing was removed). Then the four entities are returned by the firstget
request. And then, the finalget
returns no results at all.Partial Workaround:
Through a lot of trial-and-error, I discovered a partial workaround for the issue. You basically need to try (as best you can) to ensure the queries are never executed at the same time. As I mentioned in the earlier description, it seems pretty much impossible to ensure this in a multi-user app where there can be database mutations made by anyone that can trigger
onChild
callbacks at any time.If you modify the above code sample to define the queries / database references in a different order and implement a timeout/delay to ensure the
onChild
callbacks have finished executing, you seem to get the results you expect. I have no idea how robust this workaround is though and would much rather have someone from the Firebase team comment.Here's the modified code for reference:
If you remove the delay, you can see how the queries get mixed up and change the behavior of the
get
andonChild
listeners. After removing the delay, theonChild
listeners return sixonChildAdded
callbacks and then fouronChildRemoved
callbacks (when nothing was removed).The text was updated successfully, but these errors were encountered: