Firebase Limit on the Number of Observers/Listeners

Firebase limit on the number of observers/listeners

There is no limit on the number of listeners that may be attached from one client. Also note that listeners are generally inexpensive, so it is recommended that you use them as most convenient in your application.

How can I effectively manage the amount of observers/listeners on a document in Firebase?

SOLVED! Big thanks to Renaud Tarnec for his original comment referencing documentation I had not yet seen. I was missing the keyword 'presence' in my Google searches. Please upvote his comment if you find this answer helpful!

SOLUTION: Using https://firebase.google.com/docs/firestore/solutions/presence

SWIFT:

var connectionReference: DatabaseReference = Database.database().reference(withPath: ".info/connected")
var personalReference: DatabaseReference?
var connectionIssued: Bool = false
func connect(room: String) {
// Remove any existing observations to ensure only one exists.
connectionReference.removeAllObservers()
// Start observing connection.
connectionReference.observe(.value) { (isConnected) in
if isConnected.value as! Bool {
// Connected!
// Use Bool connectionIssued to ensure this is run only once.
if !self.connectionIssued {
self.connectionIssued = true
self.personalReference = Database.database().reference(withPath: "OnlineUsers/\(userID)")
// Set onDisconnect before setting value.
self.personalReference!.onDisconnectRemoveValue()
self.personalReference!.setValue(room)
// Now the user is "online" and can proceed.
// Allow user to "enter" room.
} else {
// Connection already issued.
}
} else {
// The user has either disconnected from an active connection or they were already disconnected before connect() was called.
// Stop observing connection.
self.connectionReference.removeAllObservers()
// If the user disconnects after they have entered a room, kick them out.
if self.connectionIssued {
// User lost connection.
kickUserOutOfRoom()
self.connectionIssued = false
} else {
// User cannot log in.
}
}
}
}
// Call when users leave a room when still connected.
func leaveRoomManually() {
// Remove connection observation.
connectionReference.removeAllObservers()
// Attempt to remove "online" marker in database.
personalReference?.removeValue(completionBlock: { (error, reference) in
if error != nil {
// Removal failed, but that should be okay!
// onDisconnect will still be called later!
// This failure might result in ghost users if the user proceeds to join another room before disconnecting.
// Consider writing an onUpdate() cloud function in conjunction with the following onCreate() and onDelete() cloud functions to take care of that case.
} else {
// "Online" marker removed from database!
// We can now cancel the onDisconnect()
self.personalReference?.cancelDisconnectOperations()
}
})
leaveRoom()
}

CLOUD FUNCTIONS (javascript):

The following cloud functions update the respective room's guest count in Cloud Firestore.

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const firestore = admin.firestore();
exports.userCameOnline = functions.database.ref('/OnlineUsers/{userID}').onCreate(
async (snapshot, context) => {
const room = snapshot.val();
const guestCountRef = firestore.doc(`Rooms/${room}`);
return guestCountRef.update({
Guests: admin.firestore.FieldValue.increment(1)
});
});
exports.userWentOffline = functions.database.ref('/OnlineUsers/{userID}').onDelete(
async (snapshot, context) => {
const room = snapshot.val();
const guestCountRef = firestore.doc(`Rooms/${room}`);
return guestCountRef.update({
Guests: admin.firestore.FieldValue.increment(-1)
});
});

Firebase simultaneous connection limit if adding more listeners

The number of connections to Realtime Database is almost certainly not going to be related to the types of data you're storing, or the way that data is organized.

Every mobile client establishes exactly one websocket to Realtime Database, and that socket is only active when the app is running in the foreground (and maybe a bit outside of that in some cases). That socket is considered a single connection, and all traffic between the database and the client go over that socket. It doesn't matter what data is being transferred - there is only that one socket.

Don't confuse listeners with connections. All added listeners/observers in an app use the same socket. Reducing the number of listeners will not reduce the number of connections.

Firebase limit on the number of nodes/data returned in Snapshot

Firebase will "return" all child nodes, unless you explicitly limit the number of nodes with queryLimitedToFirst: or queryLimitedToLast:. See the section of the Firebase documentation on queries for some good examples of these.

One thing to constantly keep in mind when working with Firebase is that you're not just querying the data source, you're actively synchronizing, listening for changes as they happen. Say for example that you have a Firebase that contains status updates from you and your friends. And you have a page that shows the latest 10 updates.

  1. Set up a query ordered by timestamp (a field in your status updates) with queryOrderedByChild.
  2. Limit the query to latest 10 updates with queryLimitedToLast:.
  3. You will receive 10 FEventTypeChildAdded events (assuming that there are at least that many status updates).
  4. A friend posts a new status update.
  5. Your page will receive a FEventTypeChildRemoved for the oldest status update and a FEventTypeChildAdded for the new status update.

Is it acceptable to have many 'WHERE' based listeners

You'll have to be more specific about "bazillion". In general, listeners are cheap and you shouldn't worry too much about it. But everything has a practical limit, and I think you'll discover what that is as you approach your hypothetical "bazillion".

1 listener doesn't invoke billing any different than 10 or 100 or 1000 listeners. You can expect the billing for a single listener to scale linearly. Each one will cost exactly what it would normally cost on its own, for each document that is different between all their queries.

Each listner also shares a single connection, so you don't have to worry about running out of open file descriptors or anything like that. Your limit is, practically speaking, going to be memory and bandwidth.

Is it a good practice to have big number of childEventListeners?

Yes you can have multiple ChildEventListeners is it a good practice no. You should really use one and have a LinkedHashMap type structure so that you can allocate your data to a certain Key which you can then call back later on.

Check if I have an observer listening in firebase swift

I could not find a firebase api to achieve this. I solved it using this workaround

var handle = ref.child("child").observe()

// check if nil before detaching listener
guard self.handle != nil else { return }
self.ref.removeObserver(withHandle: self.handle)


Related Topics



Leave a reply



Submit