flutter firebase with streambuilder: Is server fee going to increase exponentially? - firebase

I'm beginner in flutter-fire app [: And here i've got a simple issue but not easy to figure out.
When we use Streambuilder in the app, we can usually see awesome synchronization between UI and DB on time. I'm really feeling joyful when using Streambuilder. It seemed like only beautiful things would happen with Streambuilder.
Meanwhile, a suspicious question popped out. When we enter print('hello world!'); in the Streambuilder, we can see that RUN console is printing out the phrase every milliseconds, otherwise would be just printed once. It means that RAM usage is extremely increased. When it comes to DB synchronization, we can easily guess that the use of Streambuilder leads to huge usage of client-server communication fee, which in my case is Firebase fee.
So, here is my question.
Can i feel free to use Streambuilder when the stream is connected to DB(in my case, firebase)?
I'm worrying about communication fee between UI and firebase, because streambuilder seems like literally using huge amount of energy every milliseconds(IMO additionally, server fee) unlike normal builders. Especially when the length of collection is so long that reading the collection once may cost a lot of energy, the fee would increase a lot more on and on, because the streambuilder have to check thousands of firebase documents only to figure out a single line of condition.
I guess many backend-connected flutter methods use the Streambuilder, so someone could clearly figure it out how much we're gonna pay for Google when we use Streambuilder. I know it's quite ambiguous question, but hope you understand. [:

Content coming from the Firebase database, whether FutureBuilder or StreamBuilder, pays only for the query value that has been processed once, and after that, in case the same response value is the same for the same query, it does not pay for that cost and displays the stored list stored in the cache on the client screen again. .
And check that it's not being called on something like setState. if so, of course StreamBuilder is called again.

Related

Two StreamBuilder using one stream(); Will it increase the number of reads?

I have two Screens(Scaffold) and I'm thinking to use a single stream() in both StreamBuilder. My question is will I be charged double reads? Or the read will be equivalent to one read?
The Firestore clients try to minimize the amount of data they have to read from the server. It depends on your code of course, but in most cases there will be a lot of re-use of data that was already read - so that you won't get charged again.
Some examples:
If both builders are using the same stream, the data for the second one will come from what was already ready into memory for the first reader. So there will be no charges for the second builder.
If both builder use their own stream, there typically is also a lot of reuse. If the streams are listening at the same time, the SDK will reuse the data between them where possible.
And if you have disk caching enabled (which it is by default on iOS and Android), the streams will even share results if they're not active at the same time.

Firestore Document "Too much contention": such thing in realtime database?

I've built an app that let people sell tickets for events. Whenever a ticket is sold, I update the document that represents the ticket of the event in firestore to update the stats.
On peak times, this document is updated quite a lot (10x a second maybe). Sometimes transactions to this item document fail due to the fact that there is "too much contention", which results in inaccurate stats since the stat update is dropped. I guess this is the result of the high load on the document.
To resolve this problem, I am considering to move the stats of the items from the item document in firestore to the realtime database. Before I do, I want to be sure that this will actually resolve the problem I had with the contention on my item document. Can the realtime database handle such load better than a firestore document? Is it considered good practice to move such data to the realtime database?
The issue you're running into is a documented limit of Firestore. There is a limit to the rate of sustained writes to a single document of 1 per second. You might be able to burst writes faster than that for a while, but eventually the writes will fail, as you're seeing.
Realtime Database has different documented limits. It's measured in the total volume of data written to the entire database. That limit is 64MB per minute. If you want to move to Realtime Database, as long as you are under that limit, you should be OK.
If you are effectively implementing a counter or some other data aggregation in Firestore, you should also look into the distributed counter solution that works around the per-document write limit by sharding data across multiple documents. Your client code would then have to use all of these document shards in order to present data.
As for whether or not any one of these is a "good practice", that's a matter of opinion, which is off topic for Stack Overflow. Do whatever works for your use case. I've heard of people successfully using either one.
On peak times, this document is updated quite a lot (10x a second maybe). Sometimes transactions to this item document fail due to the fact that there is "too much contention"
This is happening because Firestore cannot handle such a rate. According to the official documentation regarding quotas for writes and transactions:
Maximum write rate to a document: 1 per second
Sometimes it might work for two or even three writes per second but at some time will definitely fail. 10 writes per second are way too much.
To resolve this problem, I am considering to move the stats of the items from the item document in Firestore to the realtime database.
That's a solution that I even I use it for such cases.
According to the official documentation regarding usage and limits in Firebase Realtime database, there is no such limitation there. But it's up to you to decide if it fits your needs or not.
There one more thing that you need to into consideration, which is distributed counter. It can solve your problem for sure.

Looking for an efficient way to update the data

I'm writing a small game for Android in Unity. Basically the person have to guess whats on the photo. Now my boss wants me to add an additional function-> after successful/unsuccessful guess the player will get the panel to rate the photo (basically like or dislike), because we want to track which photos are not good/remove the photos after a couple of successful guesses.
My understanding is that if we want to add +1 to the variable in Firebase first I have to make the call and get it then we have to make a separate call with adding 1 to the value we got. I was wandering if there is a more efficient way to do it?
Thanks for any suggestions!
Instead of requesting firebase when you want to add ,you can request firebase in the beginning (onCreate like method) and save the object and then use it when you want to update it.
thanks
Well, one thing you can do is to store your data temporarily in some object, but NOT send it to Firebase right away. Instead, you can send the data to Firebase in times when the app/game is about to get paused/minimized; hence, reducing potential lags and increasing player satisfaction. OnApplicationPause(bool) is one of such functions that gets called when the game is minimized.
To do what you want, I would recommend using a Transaction instead of just doing a SetValueAsync. This lets you change values in your large shared database atomically, by first running your transaction against the local cache and later against the server data if it differs (see this question/answer).
This gets into some larger interesting bits of the Firebase Unity plugin. Reads/writes will run against your local cache, so you can do things like attach a listener to the "likes" node of a picture. As your cache syncs online and your transaction runs, this callback will be asynchronously triggered letting you keep the value up to date without worrying about syncing during app launch/shutdown/doing your own caching logic. This also means that generally, you don't have to worry too much about your online/offline state throughout your game.

How to refresh streambuilder in firestore query?

I'm trying to create a list of cards, those cards take information from Firestore a query (need .where) it all worked out until I passed my quota, a bit later I found out about this: https://www.youtube.com/watch?v=Lb-Pnytoi-8. I need to read specific documents with .where and post them in a streambuilder, I've thought of multiple options (mostly around Future, JSON) which non of them worked. I've theoretically thought of somehow pausing a streambuilder and reenabling it every pull-to-refresh or making a quota through a futurebuilder but I had no luck.
Here's my code:
Code
I couldn't find an efficient way to do this, any luck anyone?
Apologies for this question. For community members who seek the same answer: using methods such as initState, async or anything alike will cause the widget to rebuild - ergo send once more an API-request.

Firebase - Multi Path Updates or Cloud Function Listeners

After watching a fair amount of youtube videos, it seems that Google is advocating for multipath updates when changing data stored in multiple places, however, The more I've messed with cloud functions, it seems like they're and even more viable option as they can just sit in the back and listen for changes to a specific reference and push changes as needed to the other references in real time. Is there a con to going this route? Just curious as to why Google doesn't recommend them for this use case.
NEWER UPDATE: Literally as I was writing this, I received a response from Google regarding my issues. It's too late to turn our apps direction around at this point but it may be useful for someone else.
If your function doesn't return a value, then the server doesn't know how long to wait before giving up and terminating it. I'd wager a quick guess that this might be why the DB calls aren't getting invoked.
Note that since DatabaseReference.set() returns a promise, you can simply return that if you want.
Also, you may want to add a .catch() and log the output to verify the set() op isn't failing.
~firebase-support#google.com
UPDATE: My experience with cloud functions in the last month or so has been sort of a love-hate. A lot of our denormalized data relied on Cloud Functions to keep everything in sync. Unfortunately (and this was a bad idea from the start) we were dealing with transactional/money data and storing that in multiple areas was uncomfortable. When we started having issues with Cloud Functions, i.e. the execution of them on a DB listener was not 100% reliable, we knew that Firebase would not work at least for our transaction data.
Overall the concept is awesome. They work amazingly well when they trigger, but due to some inconsistencies in triggering the functions, they weren't reliable enough for our use case.
We're currently using SQL for our transactional data, and then store user data and other objects that need to be maintained real-time in Firebase. So far that's working pretty well for us.

Resources