Skip to content
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

Equality check for timestamp fields fails when caching is active in a web worker. #8031

Closed
sethrevelle opened this issue Feb 20, 2024 · 7 comments · Fixed by #8090
Closed

Comments

@sethrevelle
Copy link

Operating System

Ubuntu 22.04.4 LTS

Browser Version

Chrome Version 121.0.6167.160 (Official Build) (64-bit)

Firebase SDK Version

10.7.2

Firebase SDK Product:

Auth, Firestore

Describe your project's tooling

Angular 16.2.9. Firestore is running within a web worker.

Describe the problem

When firestore caching is active, equality query's for Time Stamp fields do not return expected results. I have a set of documents sharing a common TimeStamp of exactly 2024-02-20 . When I query with caching disabled, I correctly get back results. When caching is enabled, no results are returned.

Steps and code to reproduce issue

const app = initializeApp(data.config);
db = initializeFirestore(app, { ignoreUndefinedProperties: true, localCache: persistentLocalCache(/settings/{tabManager: persistentSingleTabManager({forceOwnership:true})},), });

Below Fails (returns 0 documents w/ metaData from cache: true, never returns again):
const coll = collection(db, "/service-providers/aKgDbsxAm0iCTnZR53cp/resourceDayAddressRouting");
const que = query(coll,...[where("resourceDay","==",startOfDay(new Date(2024,1,20)))]);
onSnapshot(que, (querySnapshot) => {
const metaData = querySnapshot.metadata;
const docs = [];
querySnapshot.forEach((doc) => {
const docData = doc.data();
docs.push(docData);
});
console.log(docs);
);

But if you change query to look for :
const que = query(coll,...[where("resourceDay",">=",startOfDay(new Date(2024,1,20))),
where("resourceDay","<",addSeconds(startOfDay(new Date(2024,1,20)),1))]);

All 60 rows come back, with the identical timestamp value for resource day specified when querying for equality. (seconds and nanoseconds).
Timestamp(seconds=1708405200, nanoseconds=0)

If you initialize firestore without caching i.e. : db = initializeFirestore(app, { ignoreUndefinedProperties: true });

Then you also get the full 60 rows when checking for exact equality
const que = query(coll,...[where("resourceDay","==",startOfDay(new Date(2024,1,20)))]);

@sethrevelle sethrevelle added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Feb 20, 2024
@sethrevelle sethrevelle changed the title Title for the bug Equality check for timestamp fields fails when caching is active in a web worker. Feb 20, 2024
@MarkDuckworth MarkDuckworth self-assigned this Feb 20, 2024
@jbalidiong jbalidiong added api: firestore needs-attention and removed new A new issue that hasn't be categoirzed as question, bug or feature request labels Feb 20, 2024
@MarkDuckworth
Copy link
Contributor

@sethrevelle, I'm having trouble reproducing the issue. I cannot run the code exactly as your provided, but I wrote the following code and ran it in a web worker. The code consistently

const firebaseApp = initializeApp(config);
setLogLevel('debug');
const db = initializeFirestore(firebaseApp, {
  ignoreUndefinedProperties: true,
  localCache: persistentLocalCache({
    tabManager: persistentSingleTabManager({forceOwnership:true})
  })
});

const col = collection(db, "0000-10k-docs");

const ms = 1708405200 * 1000

await addDoc(col, {
  tsField: Timestamp.fromMillis(ms)
});

const q = query(col, where('tsField', '==', Timestamp.fromMillis(ms)));
onSnapshot(q, snap => {
  console.log(`Received count of docs: ${snap.size}. From cache: ${snap.metadata.fromCache}`);
});

Can you do some testing on your end by directly using Timestamp.fromMillis(ms)? This will rule out any conversion issues with startOfDay, addSeconds, etc. Also, if you enable debug logging in the SDK and provide us with the logs, that may help us diagnose the issue. Enable debug logging with setLogLevel('debug');

@sethrevelle
Copy link
Author

@MarkDuckworth I ran some testing on my end. Your code indeed seems to work happily. I changed my code to using Timestamp.fromMillis(ms) as suggested, but it still fails to return results. Interestingly (at least w/o being familiar with the internals of things) query below also returned 0 results until at least 1 second of time was added to the < query constraint.

// fails until at least 1000 ms of time added to < portion
const que = query(coll,...[where("resourceDay",">=",Timestamp.fromMillis(ms)),
where("resourceDay","<",Timestamp.fromMillis(ms + 999))]);

Another possible contributor is that I previously was calling
enablePersistentCacheIndexAutoCreation(getPersistentCacheIndexManager(db)) immediately after instantiating cloud firestore (though I commented out while working to understand this bit).

I have attached log file below.
localhost-1708491831032.log

@MarkDuckworth
Copy link
Contributor

@sethrevelle,

From the logs it looks like you have a client side index on this collection, which was probably auto-created. This could be related. However, I'm still having trouble reproducing, even after adding my own client side index.

There's also a stack trace in your logs around time '00:03:42.136'. This is unexpected, but it doesn't contain an error message, so it's not immediately helpful.

I'd like to see what indexes were created in your browser. Can you open Chrome Developer Tools > Application tab > IndexedDb > firestore/[DEFAULT]/<your_db>/main > indexConfiguration > collectionGroupIndex and reply with the config. Here's mine for example:

image

Also, are you able to reproduce this issue in another browser/device/incognito-mode? You can re-enable auto index creation if testing in another browser.

@sethrevelle
Copy link
Author

@MarkDuckworth,

The issue does not reproduce for me in incognito mode, or in firefox. It does reproduce in chrome if I launch it in debug mode w/ VSCode.

I haven't done anything to create indexes on IndexedDb manually, so I would concur that the indexes were auto-created. Looking at the stack trace @ 00:03:42:136 , I am seeing my code reporting an empty array, and then the snapshot metadata at line 1054. The line immediately before this though ( line 1012 at 00:03:42.134 ) is interesting :

00:03:42.134 [2024-02-21T05:03:42.134Z] @firebase/firestore: Firestore (10.7.2): WebChannelConnection RPC 'Listen' stream 0x5068812e sending: {"database":"projects/service-vanguard/databases/(default)","addTarget":{"query":{"structuredQuery":{"from":[{"collectionId":"resourceDayAddressRouting"}],"where":{"fieldFilter":{"field":{"fieldPath":"resourceDay"},"op":"EQUAL","value":{"timestampValue":"2024-02-20T05:00:00.000000000Z"}}},"orderBy":[{"field":{"fieldPath":"name"},"direction":"ASCENDING"}]},"parent":"projects/service-vanguard/databases/(default)/documents/service-providers/aKgDbsxAm0iCTnZR53cp"},"targetId":12376,"resumeToken":"CgkI4L2gntO7hAM=","expectedCount":60}}

The "expectedCount" at the end of the line matches the correct count of rows, if the rows were returned.

Below is the screenshot of the collectionGroupIndex config:

image

@MarkDuckworth
Copy link
Contributor

Good news, bad news. I'm able to reproduce. We will investigate further and update you here.

@MarkDuckworth
Copy link
Contributor

@sethrevelle, We've identified the root cause and we are working on a solution.

In the meantime, the workaround for you and other affected customers is the following:

  1. Disable client side index auto creation until the fix is released. It's disabled by default, so do not enable it with enablePersistentCacheIndexAutoCreation(...).
  2. Clear existing client side indexes deleteAllPersistentCacheIndexes(indexManager).
  3. Optionally, if you need client side indexes on fields that do not contain timestamp values, then the indexes can be manually created using setIndexConfiguration(firestore, configuration).

Note: the issue only affects the Web SDK when persistence is enabled, and only for queries filtering on Timestamp values, and only if there is a client side index on that collection+field.

@sethrevelle
Copy link
Author

@MarkDuckworth I am currently transforming equality queries -> timestamp >= x and timestamp < x + 1s , which seems to work as well (at least in my testing). Is there any reason to believe this will not also consistently produce correct matching documents? For various reasons it is more convienient at moment for my use case.

@milaGGL milaGGL mentioned this issue Mar 25, 2024
2 tasks
@firebase firebase locked and limited conversation to collaborators Apr 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.