问题
I am working on a Spring-MVC based web-app which uses Cometd for chat purposes. For real-time management of which user is online, we are sending notifications when the user is online. So when window is closed, then notifications don't appear and after 30 seconds it is determined that the user is offline or not reachable.
Now the problem happens when user is over multiple browsers. Lets just keep it for 2 now. So, after 10 minutes we are setting user status to 'Away from Keyboard'(AFK). But if the user is online in one browser, then we are getting a blinking status, for few seconds because of the browser in 'Idle Mode', we get a AFK, and from the active machine we get an 'Available' status.
How can we solve this problem? Any ideas, suggestions. I thought of using a boolean flag, and couple with IP address, which will be checked before overwriting the notification, but it has a problem of stale notifications.
This is my code for sending out notifications for online to all listeners(Friends of user).
Code :
@Listener(value = "/service/online")
public void OnlineNotifications(ServerSession remote, ServerMessage.Mutable message) {
Person sender = this.personService.getCurrentlyAuthenticatedUser();
Map<String, Object> input = message.getDataAsMap();
String onlineStatus = (String) input.get("status");
Map<String, Object> output = new HashMap<>();
output.put("status", onlineStatus);
output.put("id", sender.getId());
ServerChannel serverChannel = bayeux.createChannelIfAbsent("/online/" + sender.getId()).getReference();
serverChannel.setPersistent(true);
serverChannel.publish(serverSession, output);
}
Any ideas are welcome. Thanks a lot. :-)
回答1:
Your application can easily associate multiple devices with the same userName
.
You can do this from your SecurityPolicy
, just associate the userName
string with a List<ServerSession>
or whatever data structure fits better your case.
Your online state for a particular userName
is therefore a function of all the ServerSession
s of this particular userName
.
As such, it's a mapping from the userName
to a list of online states.
If you imagine user bob
logged in from two browsers, the mapping for its online status can be:
"bob" -> ["afk", "online"]
To compute the online status for bob
you just run through all the online statuses for each ServerSession
and if there is at least one online
then it's online, if all are afk
then it's away from the keyboard, and so on.
You can implement this logic in several ways (e.g. storing the online status as a ServerSession
attribute, use a different data structure, cache the per-user online status, etc.), but you get the idea.
Whenever you get an online status change from one ServerSession
, you update your server-side data structure, and then recompute the online status from all ServerSession
s for that user, and that is what you send to the other users.
来源:https://stackoverflow.com/questions/31512310/cometd-multiple-tabs-for-online-users-management-creating-false-online-status