I have an app where I have up to a few thousand entries in a firebase table.
Now someone is connecting to this table and I need to count and sum these items up.
-itemlist
|
--1
|-x:2
--2
|-x:4
and so on. A user can connect at any time (meaning he never saw this table before) and another user can change some value at any given time or add values.
Now if I try and add a ValueEventListener to "itemlist" it works if there is no new data but as soon as I connect to a new database with 1000 entries or so the listener calls for every one of these 1000 entries.
I tried with onChildlistener but this calls the on ChildItem added for every item extra on the first time.
This takes over 2 minutes sometimes.
Is there a way to get the whole database once, calculate it and then only listen for changes?
The Firebase Database has no server-side aggregation operators, since they would inherently be at odds with the scalability and realtime nature of the database.
That leaves you with two options to calculate aggregates:
perform them client side as you already suggested
keep a running aggregate that you update with every change
Performing the aggregation client-side is a good option if the client already needs to display the data anyway. For example: if you're showing the list of users in a specific chat room, you can easily count the number of users client-side from the same data.
But if you don't need the data client-side, then just downloading it to aggregate it is wasteful and will hurt scalability of your app. In such cases, an option is to keep an extra node that keeps the aggregate and update it with every relevant write operation. For example: if you want to show how many users have registered with your app, you could keep a global /user_count that you update whenever a user registers/unregisters. For this update, you'd typically use a transaction.
Related
I am developing an app using Android & Firebase Realtime Database where users join a room, then when the host presses start game, all clients start the main game Activity (through a ValueEventListener on a "Started" child node in the room). The main game has a 60sec countdown where users make a sentence then at the end of the 60secs all sentences are collected and displayed.
I am having a hard time collecting all of the sentences at the end due to the 60sec timers being so off on different clients. I need a way to ensure all games end at the same time so the collection process is smooth and nothing gets missed.
I know that Firebase has both: /.info/serverTimeOffset and ServerValue.TIMESTAMP but i'm struggling on how to use them to sync timers.
I have tried to use System.currentTimeMillis() + serverTimeOffset to estimate the server time and get all clients to count down to endTime - (System.currenTimeMillis() + serverTimeOffset) where endTime is a time written to the database by the host that all clients read but timers are still way off.
What is the best way to handle this situation?
I would suggest:
Instead of running a timer that updates every second on the server, simply store the start/stop times of the event and allow the clients to manage their own timers.
Not be done by -1 every second (as setInterval and other client-side tools are not very exact) but by comparing the current timestamp to the end, and determining the difference.
I'm developing a Chat style application that could potentially have tons of users chatting at the same time. I'm retrieving a list of chat-rooms when I enter on my Home screen and then adding an SnapshotListenerto each one of the chat-rooms to listen the messages in real time. This can grow exponentially and I can end up having hundred or even thousands of SnapshotListener active at the same time on the client side.
My question is, do this affect performance? I mean, regarding Firebase library, it has any kind of limit or performance issue when having that many listeners active at once? Of course not everyone is gonna be chatting at the same time, so even if there are 1000 open listeners, just 5-10 would be chatting and sending callbacks at once.
According to the Best Practices section of the official Firestore documentation:
You should always try to keep the number of snapshot listeners per
client under 100.
Also you should keep in mind some more generic limits and quotas such as:
The maximum concurrent connections for mobile/web clients per database
= 1,000,000
I know that pagination is a well discussed topic here but... Is there a way to fetch some amount of nodes(something like 5 at a time) and know when the end has been reached? Firebase Database does not have a way of knowing the total number of nodes. So how will I achieve this?
The only way to know if you have all the data at a location is to perform a single 'value' type query on it. Even then, the data may change after that listener is invoked, so all you really have is a snapshot at a particular moment in tim.
For child events, there is no way to know there is no more data after the current event. In fact, child events may keep firing as more data is added, as long as the listener is still added at that location.
This is why pagination is so hard. There is no generalized way to know if you have a full page of data at any given point, or if there's another page.
I'm working on an app using Firebase and Geofire. On running the Geo query at the current location, let's say I receive 10 keys in the OnKeyEntered override method. Each of these keys is essentially a user node in Firebase. I need to listen to each of the user in the query area for any data change so that I can show updates on the map in realtime.
Currently, I'm adding a ValueEventListener for every key entered but I'm not sure if starting so many listeners at the same time is good idea. The users in the query area can potentially be more than 50. That means I could have 50 open listeners!
Is there a better way to go about it? I was trying to figure out a firebase query to filter on only the geo query keys but was unsuccessful.
Any help would be great!
Listeners are not computationally expensive, unless you have one that's going to be triggered very frequently because the data it's listening to is changing often.
Don't fall into the trap of optimizing your code before you actually observe a need to optimize it. When you see that performance is poor, that's the time to make optimizations. If you need a bunch of listeners to get your work done, go ahead and do that. Just know what your practical upper bound it, and be sure to test that upper bound for problems.
I can't find documentation on best practices for the maximum number of messages one should send to the Firebase database (or one like it) over a period of time, like one second, and also what rate an app could handle receiving without slowing down significantly. For example:
//send updated location of user character in MMORG
MyDatabaseReference.child(LOCATIONS).child(charid).setValue . . .
//recieive locations of other characters in a MMORG
MyDatabaseReference.child(LOCATIONS).addValueEventListener(new
ValueEventListener() { . . .
In testing, 3 devices each sending 20 messages per second to the database, and each receiving 60 messages per second, appears to work OK (S8 used, a fast device). I was wondering what would happen with, say, 100 devices, in which case each user app would be getting 2000 messages per second theoretically. I imagine there is some automatic throttling of this.
As mentioned in Firebase officil documentation regarding Firebase database limits, there is a maximum of 1000 write operations/second for the free plan.
If you want to stay on the free plan, remember that when you'll reach the maximum number of writes per second, it doesn't mean that you'll not be able to use Firebase database anymore. When 1001th simultaneous connection occurs, a queue of operations is created and Firebase will wait until one connection is closed, and than it uses your new connection.