Firebase having thousands of on() event listeners good design - angularjs

We need to run some operation on our Firebase DB and manipulate data after certain input is given by user from the Mobile Device modifying a flag.
Currently we are using on() to listen to particular flag in each users node. We are running this listener from a Nodejs server hosted on Heruku.
If we plan to have 100 thousand users we will have 100 thousand listener. One listener for each users flag which is waiting to be manipulated by user on the Mobile device.
Is this a good design in terms of Firebase?
Ideally we can create a REST API which is called by users and then on the Node JS server we can manipulate the data.
What is the best way to run background operation on Data on Firebase based on user input?
We were using Parse earlier and it was easy to achieve this using Parse Cloud code. With Firebase we are having issues because of this.

If we plan to have 100 thousand users we will have 100 thousand listener. One listener for each users flag which is waiting to be manipulated by user on the Mobile device.
This sounds like a bad data design. While it is definitely possible to listen for changes to hundreds of thousands of items, it shouldn't require hundreds of thousands listeners.
My guess (because you didn't include a snippet of your JSON) is that you have a structure similar to this:
users
$uid
name: "user6155746"
flag: "no"
And you're attaching a listener in just the flag of each user with something like:
ref.child('users').on('child_added', function(userSnapshot) {
userSnapshot.ref().child('flag').on('value', function(flagSnapshot) {
console.log('the flag changed to '+flagSnapshot.val());
});
})
In code this is simple, in practice you'll have a hard time managing the "flag listeners". When will you remove them? Do you keep a list of them?
All of these things become a list simpler if you isolate the information that you're interested in in the JSON tree:
users
$uid
name: "user6155746"
userFlags
$uid: "no"
Now you can just listen on userFlags to see if the flag of any user has changed:
ref.child('userFlags').on('child_changed', function(userSnapshot) {
console.log('Flag of user '+userSnapshot.key()+' changed to '+userSnapshot.val());
});
With this you have a single listener, monitoring the flag of potentially hundreds of thousands of users.

Related

In CQRS with multiple databases, should I call database functions inside Command or inside repositories?

I'm using cqrs pattern with multiples databases (one for query and another for search). Should I put the insert inside Repository
CommunityRepository{
Add(Community community){
Database1.Insert(community);
Database2.Insert(community);
}
}
and then:
CommunityCommands{
Handler(AddCommunityCommand community){
communityRepository.Add(community);
}
or should i put this in Commands, like this:
CommunityCommands{
Handler(AddCommunityCommand community){
db1.Insert(community);
db2.Insert(community);
}
or maybe something like this, using the main repository + database2
CommunityCommands{
Handler(AddCommunityCommand community){
communityRepository.Add(community);
db2.Insert(community);
}
I would do neither of those options as you'd be basically coupling the Command and Query immplementations.
Instead, publish events from the Command side, like OrderPlacedEvent and subscribe to them from the Query side. This not only allows you to separate the implementations of the Command and Query sides, but it will also allow you to implement other side effects of the events without coupling the code from the multiple features (eg. "when an order is placed, send a confirmation email").
You can implement the pub/sub synchronously (in process) or asynchronously (with a messaging system). If you use messaging, note that you'll have to deal with eventual consistency (the read data is slightly behind the write data, but eventually it catches up).
refreshing the Query Models should be handled in an offline operation. You should do something like this:
process your Command logic (whatever it is)
right before your Command handler returns, send an Event to a message bus
then in a background service you can listen to those Events and update the Query side.
Bonus tip: you can use the Outbox pattern to get more reliability. The idea is to store the Event messages in a table on your Write DB in the same transaction as your previous write operation, instead of sending them directly. A background service would check for "pending" messages and dispatch them. The rest is unchanged.

Notify Users on User Defined Events on Data changes on server

I have a node.js webservice with 10k users.each user can monitor price changes of 1k items(realtime or every second).
my problem started here:
each user can listen 4 event : start/stop/higher/lower for each item.
when event fired i need to send sms or email to user.
which design pattern or database model i need to implement this ?
how to implement it? any book or reference?
thank you
If you have an object which must notify subscribers about changes - you have to use Observer.
If you have relationships many to many you can use Mediator - pattern which encapsulates how a set of objects interact.
But in your case (10k users & 1k items) - you have to have good abstration layer... Split your items and users into groups and use these groups for design pattern...

How to keep track of chat messages seen by user

I am building a simple Chat App using Firebase and Ionic. I am trying to keep track of number of messages that are unread for different groups that the user is member of (like WhatsApp).
I have the messages linked to $scope through $firebaseArray
$scope.messages = $firebaseArray(<ref to message path in firebase>);
$scope.messages is iterated over and shown in the view. When a new message arrives it automatically shows up in the group being viewed. I want to keep track of messages not viewed. I am not quite sure of the best way to keep track of which messages the user has seen. I see suggestions here to keep track of timestamp when a user last visited a group but am wondering if there is a better/simpler solution to this.
The things that come to mind that I need to do are -
Setup some sort of monitoring for all groups the user is member of not just the one being viewed by the user. If user is member of 50 groups I need to monitor all 50 of them individually (wonder what, if any, performance implications that has). Here I will need to setup a child_added monitoring for each of the groups the user is member of
Track timestamp for last time a user was in a group
As the user switches groups, change the $firebaseArray to monitor the new group and cancel the $firebaseArray setup for the previous. Change the child_added monitoring for the new group to the group being viewed previously
If the user moves to another part of the app where he is not looking at any group messages (perhaps in a setting section) then again be aware of that and monitor all groups - remove the firebeaseArray from the group last being viewed and add a child_added monitoring when user moves away
If the user goes to another application and pushes the Chat application in the background then I am a little unsure of what to do
How does the code determine that the group whose messages the user was looking at is no longer active and new messages coming in now need to be counted
I am assuming I need to monitor for the App Pause and Resume events to address that. Is there a better way?
Trying to keep my code simple but feels like monitoring for unread messages is a significant chunk of work. Thanks for any ideas or pointers to sample code or to simplify this.
-S

Keeping repository synced with multiple clients

I have a WPF application that uses entity framework. I am going to be implementing a repository pattern to make interactions with EF simple and more testable. Multiple clients can use this application and connect to the same database and do CRUD operations. I am trying to think of a way to synchronize clients repositories when one makes a change to the database. Could anyone give me some direction on how one would solve this type of issue, and some possible patterns that would be beneficial for this type of problem?
I would be very open to any information/books on how to keep clients synchronized, and even be alerted of things other clients are doing(The only thing I could think of was having a server process running that passes messages around). Thank you
The easiest way by far to keep every client UI up to date is just to simply refresh the data every so often. If it's really that important, you can set a DispatcherTimer to tick every minute when you can get the latest data that is being displayed.
Clearly, I'm not suggesting that you refresh an item that is being edited, but if you get the fresh data, you can certainly compare collections with what's being displayed currently. Rather than just replacing the old collection items with the new, you can be more user friendly and just add the new ones, remove the deleted ones and update the newer ones.
You could even detect whether an item being currently edited has been saved by another user since the current user opened it and alert them to the fact. So rather than concentrating on some system to track all data changes, you should put your effort into being able to detect changes between two sets of data and then seamlessly integrating it into the current UI state.
UPDATE >>>
There is absolutely no benefit from holding a complete set of data in your application (or repository). In fact, you may well find that it adds detrimental effects, due to the extra RAM requirements. If you are polling data every few minutes, then it will always be up to date anyway.
So rather than asking for all of the data all of the time, just ask for what the user wants to see (dependant on which view they are currently in) and update it every now and then. I do this by simply fetching the same data that the view requires when it is first opened. I wrote some methods that compare every property of every item with their older counterparts in the UI and switch old for new.
Think of the Equals method... You could do something like this:
public override bool Equals(Release otherRelease)
{
return base.Equals(otherRelease) && Title == otherRelease.Title &&
Artist.Equals(otherRelease.Artist) && Artists.Equals(otherRelease.Artists);
}
(Don't actually use the Equals method though, or you'll run into problems later). And then something like this:
if (!oldRelease.Equals(newRelease)) oldRelease.UpdatePropertyValues(newRelease);
And/Or this:
if (!oldReleases.Contains(newRelease) oldReleases.Add(newRelease);
I'm guessing that you get the picture now.

How can i make 2 Apsalar segments that do not overlap?

So I am running into an issue with where i need to divide my users into segments in Apsalar but it's based off of one event
The event only happens when running in debug (so testers), and while i can still make a segment for them in Apsalar i will run into the issue where testers have their events mixed in with players
The end result of this is that tester data and player data are separate and I keep track of both.
I can do this with Flurry because they allow me to segment based on NOT having an event, but I was wondering if there was a way to do something similiar with Apsalar?
To accomplish your goal - separating tester data from player data - I recommend creating a unique application from within the Apsalar dashboard.
Doing so will allow you to divide your events, segments, cohorts, and other application data into two clear buckets on Apsalar's platform. I believe it is better to ensure you are not duplicating the data you are reporting and analyzing in Apsalar than to create an event based on the absence of an event. If you create multiple segments based on NOT having an event, I guarantee it will be difficult to parse which segments belong to your testing and production purposes.
Let me know if this helps.
Image URL:
http://ge.tt/4tJJSJR/v/0

Resources