Reputation: 2124
There is a users subtree in my Firebase Database which keeps basic user info and following/followers for that user, this subtree is structured like this:
"users": {
"userId-1": {
"userName": "Namey McNameface",
"following": {
"followingId-1": true,
"followingId-2": true,
.
.
},
"followers": {
"followerId-1": true,
"followerId-2": true,
.
.
}
},
"userId-2": {},
"userId-3": {},
.
.
}
I want to send a notification to user's phone whenever someone starts to following him/her.
In my own server, I listen to the followers subtree. When a child added, user will see a notification.
The problem is that, at some point I will need to deploy the next version of my server and when I do that OnChildAdded
event will fire for all children (followers) and all users will see wrong notifications about their followers starting to follow them.
I can store the sent-notification info in my database to solve this problem, but this will be a time-consuming job for me.
Another way is that I can skip the initial firing of OnChildAdded
event, if that is possible in Firebase Database.
Thank you in advance.
Edit:
I am using Java and Spring for my server.
This is my FirebaseService
. I am creating a UserListener and starting to listen all users.
@Service
public class FirebaseService {
public FirebaseService() {
UserListener userListener = new UserListener();
FirebaseDatabase.getInstance().getReference(Tag.USERS).addChildEventListener(userListener);
}
}
This is UserListener
. It creates a FollowerListener
to listen followers
subtree for each user.
public class UserListener implements ChildEventListener {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String userId = dataSnapshot.getKey();
FollowerListener followerListener = new FollowerListener(userId);
FirebaseDatabase.getInstance().getReference(Tag.USERS).child(userId).child(Tag.FOLLOWERS).addChildEventListener(followerListener);
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
}
This is FollowerListener
. When a user ID is added to followers
, FollowerListener sends notification. It basically gets the followed user's FirebaseInstanceId and follower user's screen name. Then sends notification.
public class FollowerListener implements ChildEventListener {
private final String followedUserId;
public FollowerListener(String followedUserId){
this.followedUserId = followedUserId;
}
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String followerUserId = dataSnapshot.getKey();
FirebaseDatabase.getInstance().getReference(Tag.USERS).child(followedUserId)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User followedUser = dataSnapshot.getValue(User.class);
if(followedUser != null){
FirebaseDatabase.getInstance().getReference(Tag.USERS).child(followerUserId)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User followerUser = dataSnapshot.getValue(User.class);
if(followerUser != null){
// Send notification to followed user.
NotificationInfo notificationInfo = new NotificationInfo();
notificationInfo.setTitle("test title");
notificationInfo.setText(followerUser.getScreenName() + " seni takip etmeye başladı.");
notificationInfo.setClickAction(Tag.ACTION_GO_TO_PROFILE);
NotificationData data = new NotificationData();
data.setUserId(followerUserId);
NotificationRequestBean bean = new NotificationRequestBean();
bean.setTo(followedUser.getFirebaseInstanceId());
bean.setBody("test body");
bean.setTitle("test title");
bean.setPriority("normal");
bean.setDelayWhileIdle(false);
bean.setNotification(notificationInfo);
bean.setData(data);
AppUtils.sendNotification(bean);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
}
The problem is whenever I deploy the server, FollowerListener attaches to all users's followers
subtree. Then OnChildAdded event is firing for each follower initially. It should not send notifications every time I deploy the server.
Thanks.
Upvotes: 2
Views: 1165
Reputation: 2124
I've found a very simple solution for this problem. I just added a boolean
field in the followers
subtree called processedByServer
. So it became like this:
"followers": {
"followerId-1": {
"processedByServer": true // already processed.
},
"followerId-2": {
"processedByServer": false // not processed yet, but will be.
},
.
.
}
This processedByServer
is initially false
, after I made my necessary processing in the server (send notification etc.) I change this value to true
. The server only needs to process when this field is false
. So after I redeploy/reboot my server, it won't send wrong notifications anymore.
But there is also downsides of this solution:
processedByServer
fields in the followers
subtree, which may be a time consuming job for the server.Upvotes: 1