Open Shanzid01 opened 2 years ago
Thanks for reporting @Shanzid01 . I'll take a look.
Hi @Shanzid01 Would you be able to provide a repo that we can clone to reproduce the issue?
I have the same issue, the only way to get it to work is disabling enableIndexedDbPersistence
@yoannes Would you be able to provide a minimal code repo that we can clone to reproduce the issue?
@ehsannas Here you go: https://github.com/Shanzid01/firestore-db-persistence-error
I've also deployed the code here: https://firestore-db-persistence-error.pages.dev So you should be able to see the error in the browser logs as soon as the page loads.
Edit: Added you as a collaborator on the repo. Feel free to push commits to the repo and test live on the Cloudflare Pages environment.
hello @ehsannas, were you able to access the repo?
Thanks a lot for creating this @Shanzid01 . Yes, I'm able to access it.
The issue seems to be specific to Vue and how it interacts with IndexedDb (local caching). While it may take a bit of time to pin down and fix this, you can avoid enableIndexedDbPersistence
as a temporary workaround.
@ehsannas is there a workaround to still enable caching so that accessing the same firestore data every time doesn't cause a new read
(i.e. doesn't cause a billable event)? And any approximate timeline on when this may be patched?
For context, we're running an app where users are accessing large volumes of the same (read-only) data many times from the same device, and we're concerned that this may become an issue for us in terms of the firestore bill that comes through.
Hi @Shanzid01 , unfortunately I don't think there's a workaround which keeps the caching enabled. I understand this can affect the amount of your reads. But since this seems to be a Vue-specific issue, we'll need some time for prioritization against other work and investigation and can't provide a specific timeline.
Would you be able to check whether you get the same error on newest Firebase SDK version?
Thank you @ehsannas, I really appreciate your transparency. I'll keep an eye out for potential fixes/workarounds.
As for the versioning, the project I shared with you previously is on SDK v9.6.10 (which I believe is the latest?) and it still throws the error. I'm not sure if there's a beta/canary that I can install, though.
Hi @ehsannas. I was able to diagnose and fix this issue in PR#6173. I've also updated the demo repository to reflect these changes and show that the patch works [see live demo].
Sidenote: This definitely isn't the most elegant work, but this is the best I could do given my limited knowledge of the firestore codebase. Even if the PR isn't merged, I hope others who face this issue can use this workaround to at least temporarily address this.
@Shanzid01 That's awesome! Thanks for you contribution to the codebase 🎉 Will review and comment on the PR.
Hi there, has this issue been fixed? I noticed the https://github.com/firebase/firebase-js-sdk/pull/6173 fix was not applied. We're having the exact same issue, however ours only appears when we try to access paginated data with enableIndexedDbPersistence
Code that's failing:
if (entry[0].isIntersecting && this.lastDoc && this.messages.length >= 20) { const messageRef = query(collection(db, 'conversations', this.conversationId, 'messages'), orderBy('created', 'desc'), startAfter(this.lastDoc), limit(20)) try { const newMessages = await getDocs(messageRef) this.lastDoc = newMessages.docs[newMessages.docs.length-1] } catch (erorr) { console.log('here in error') console.log(erorr) }
This fails with the same error mentions above on the getDocs call.
Environment is the same, Vue3 with the Firebase JS SDK version 9.
Hi @typefox09 , unfortunately this issue is currently not prioritized. Due to the concerns that were raised in #6173 we haven't merged this change. It seems that a function is being added outside of our codebase and only applies to Vue. The proposed fix will cause a performance hit.
While I cannot reproduce the issue with your repo, I might know the fix after looking at discussion in your PR. In order to prevent Vue from wrapping variables with Proxy (which enables reactivity), you can use markRaw
. The code would look like this:
initFirestore(): Promise<void> {
/** NOTE: This entire function runs without any errors! */
this.db = markRaw(initializeFirestore(this.firebaseApp, {
cacheSizeBytes: CACHE_SIZE_UNLIMITED,
}));
return enableIndexedDbPersistence(this.db);
}
Use markRaw
if you want to store Firestore instances, document or collection references, etc. in component data, Vuex/Pinia module state.
Docs: https://vuejs.org/api/reactivity-advanced.html#markraw
@typefox09
Also as for using markRaw(), from looking at the documentation, this is available on the Composition API, we are using the Options API.
Not sure why it's put at Composition API section, it works in any place Vue enables reactivity, that's why I mentioned Vuex/Pinia. I'm not a huge fan of Composition API myself, I mostly use it as a replacement for mixins.
Still, I would consider wrapping Firestore instances or references with markRaw
a good practice, might help with performance and reduce possibility of similar bugs, and you don't need reactivity on those anyway. Just leaving it here for other folks passing by.
As I mentioned, you need to put your instance/reference in component data or Vuex/Pinia state, that's when Vue will make it reactive and that's what @Shanzid01 was doing. If you were to log this.db
in reproduction repo with and without markRaw
, you would see a difference.
For anyone coming across this and looking for at least a temporary fix, you can try using the patch-package library to create a fix for this. I've done so in my demo repository. I've been using this change in production for over five months and haven't seen any side effects.
The proposed fix will cause a performance hit.
That's true, however, the disadvantages of simply not using the cached DB were too significant to ignore, especially considering how insignificant the performance hit associated with this patch actually is in my project.
Use
markRaw
if you want to store Firestore instances, document or collection references, etc. in component data, Vuex/Pinia module state. Docs: https://vuejs.org/api/reactivity-advanced.html#markraw
Thanks! this solved the problem
This worked for me also, thanks. Problem came from storing the last document in data() for pagination. Adding markRaw to that solved the issue.
Just came across this issue myself. This thread was really helpful.
In my case it was caused by one of my queries was being executed with a proxy. Just need to call toRaw()
on this.
Setting firestore logging to debug allowed me to see the query.
It seemed to only be an issue when there was also a snapshot listener on the same collection.
It was also interesting that if this document had been queried before but without the vueRef it worked fine. I'm guessing the query is stored with the cached data.
const doc = (
await db
.collection("blah")
.where("game", "==", toRaw(this.vue3Ref))
.get()
).docs[0];
toRaw()
saved my day. Thank you!
Describe your environment
Problem
Adding firestore persistence to Vue3 web app (followed instructions here) results in console errors when setting up snapshot listeners in firestore:
Steps to reproduce:
enableIndexedDbPersistence
Relevant Code:
Setting firestore persistence (this works fine):
Setting up snapshot listener (this throws error at runtime):
I've tried clearing all application data in browser but the problem persists. Happy to provide additional logs/details about my implementation.