Is there a way to find the list of ServerSession associated with the given userId?
public boolean associate(final String userId, final ServerSession session)
{
if (session == null)
throw new NullPointerException();
LocalLocation location = new LocalLocation(userId, session);
boolean wasAssociated = isAssociated(userId);
boolean added = associate(userId, location);
if (added)
{
session.addListener(location);
if (_logger.isDebugEnabled())
_logger.debug("Associated session {} to user {}", session, userId);
if (!wasAssociated)
{
if (_logger.isDebugEnabled())
_logger.debug("Broadcasting association addition for user {}", userId);
// Let everyone in the cluster know that this session is here
_session.getChannel(SETI_ALL_CHANNEL).publish(new SetiPresence(true, userId));
}
}
return added;
}
If the user is already associated, seti doesn't publish on SETI_ALL_CHANNEL to notify other comets.
Detail Explanation-
I have implemented cometd oort cluster to push the database change notification to the browser.
Two nodes are considered as master/slave. Master node only receives the notification from the database.
Users are connected through the slave node. When the user first handshake with the slave node, seti publishes an event user presence added.
Both the nodes in the cluster know about the users in the cloud. When, user refreshes the browser a new(second) handshake is initiated. The userId(loginUserId) remains the same. Seti doesn’t publishes it to the cluster which is correct by design.
After certain time, the session through the first handshake is removed due to inactivity. The presence removed event is fired by seti, which is also the expected by design.
Slave nodes only know the user is connected through second handshake, however the master node doesn’t know that the user is present in the cloud.
When new event arrives from database, the master node doesn’t see the user in the cloud and thus no events are transferred to the browser. Moreover, the master and slave nodes are connected at this point of time. The users connected to the cluster is not synchronized between two nodes.
I was thinking to seti/disassociate and then seti/associate the session for the same user.
We can get a list of sessions connected-
seti.getOort().getBayeuxServer().getSessions();
// clientId - previous client session id need to be identified
ServerSession serverSession=seti.getOort().getBayeuxServer().getSession(clientId);
Through client Id, Server Session can be retrieved and the disassociation can be done for the user.
seti.disassociate(loginUserId, serverSession);
boolean association=seti.associate(loginUserId, serverSession);//new handshake- serverSession
If you have two sessions connected to the slave node, and one of them goes away, then Seti will not broadcast a presence removed event, because that is only fired when all associations for a userId
on a node are gone.
This is exactly to avoid that one node still has an association, but other nodes think the user is gone from the cloud.
If you have evidence that this is happening, then it's a bug, but this specific behavior is tested in the CometD test suite.