Description
Operating System
Windows 11 Pro 22H2
Browser Version
Firefox v120.0.1 (64-bit)
Firebase SDK Version
^8.3.2
Firebase SDK Product:
Firestore
Describe your project's tooling
It is web app written using React v17.0.1
. For state management we use redux (with sagas).
Describe the problem
We've enabled persistence in our app. In some places we rely on the cached data. So sometimes we do request using source: cache
and if there is no data in cache we try same request using source: server
.
We display a list of items and for each item we fetch its discussion
. The issue is that for one of our teammates somehow after some time of app usage some discussions become empty in the cache, but even doing a request with source: server
does not really go to server, we still get empty data in the response (and yes, by the query we have data in the db). In another browser or after clearing the cache the issue is solved. Changing cache size to unlimited did not solve the problem.
Me and my teammate tried to intentionally reproduce the issue by doing following:
- we tried to limit the cache size to 1 Mb and play with the app. We tried to reach some cache clearings by garbage collector and everything worked fine, we could not get the state when we see incorrect data (I tested in Chrome (119.0.6045.159) and Firefox (120.0.1) on my MacBook (macOS 13.4.1));
- going offline with
source: server
did not throw an error. The code continued working in thetry
block and in the logs we could seenull
data havingfromCache=false
.
So we could not reproduce the issue. But my teammate has this issue in our dev and prod environments in his Firefox.
Steps and code to reproduce issue
As I mentioned in the problem description, we could not intentionally reproduce it.
Here is the code example of how we fetch that data:
const getDiscussionById = async (
discussionId: string,
source: "default" | "server" | "cache" = "default",
): Promise<Discussion | null> => {
try {
const snapshot = await firebase
.firestore()
.collection("discussion")
.withConverter(converter)
.doc(discussionId)
.get({ source });
const discussion = snapshot.data() || null;
if (!discussion && source === "cache") {
return getDiscussionById(discussionId, "server");
}
return discussion;
} catch (error) {
if (source === "cache" && isFirestoreCacheError(error)) {
return getDiscussionById(discussionId, "server");
} else {
throw error;
}
}
};
We tried to remove the logic of fetching with source: cache
by using just source: server
to get data directly from server, but we still get empty data having fromCache=false
. As I mentioned in the problem description, going offline does not throw the error during the request, the code keeps executing in the try
block with empty data in the snapshot.data()
.
const getDiscussionById = async (
discussionId: string,
): Promise<Discussion | null> => {
const snapshot = await firebase
.firestore()
.collection("discussion")
.withConverter(converter)
.doc(discussionId)
.get({ source: "server" });
const discussion = snapshot.data() || null;
return discussion;
};