Page MenuHomePhorge

User presence persistence
Closed, ResolvedPublic

Description

The user status should be the same across clients (or browser windows).

Right now whenever user logs into the KolabChat app or API or even opens a chat window his status is set to "online". Internally every client has his own user-reference-ID in Phoenix.Presence "format", so the same user can have many different statuses at a time. I'm not yet sure how to do this, but we should have one status at a time for each user. So, for example if user changes the status in Roundcube, his status will change in e.g. mobile client.

So, two things here:

  1. Remember the user status in database and don't reset it on logon nor any other operation, except system/set-status.
  2. Make sure there's always only one status at a time possible.

@seigo, any take on this?

Details

Ticket Type
Task

Event Timeline

Remember the user status in database and don't reset it on logon nor any other operation, except system/set-status

I think this is up to the client to do; let it remember what its last presence was (or not, and just accept the current default). If, and perhaps only if, this is the first connection (presence) for that user should the chat server accept the new client's on-connect presence setting, otherwise ignore it (because there are already other clients connected which are managing the current presence). The result would be: on first connect, set the presence to what it was on last disconnect; on connect-when-other-clients-are-connected-already just use the current presence

Make sure there's always only one status at a time possible.

Looking into this at some length today, I think the "correct" (?) way to do this is to subscribe each user to their own control channel (e.g. clientsync:%username) and broadcast presence changes via that so all clients can set their individual presence accordingly. We may need/want to do the same / similar for chat rooms joined as well (can all go over that clientsync:username channel ..). Joining that channel would check that the user is correctly authenticated before allowing to join, of course. So, perhaps give that a try?

We already use (authenticated) system channel for that and I think it should/can be used still. I just wasn't sure channel about data persistence or channel data size limitations. So, it looks that if we use the system channel all we need is to properly handle user joins to the channel. I'll go this route for now.

@seigo, I'm having trouble with this. Would you mind taking a look? I thought it will be a simple change in system_channel.ex, but I can't make it working.

Ok, so FINALLY got time to look at this this afternoon :)

I have implemented this in the feature/syncd_status branch. Please take a look.

I did implement it using the system room, but that required filtering on the username in a handle_out function ... using a room:usersync_<username> is easier and should be more efficient from what i understand.

This does raise a few new issues, however:

  • not all sessions probably want to be syncronized .. imagine your smartphone and your roundcube sessions on your desktop .. you may want your phone marked away (and not receive msgs there), but ALL the roundcube browser tabs should share the same status .. which may mean adding another key to the metas such as "status_context" and only synchronize with status changes to status_contexts that match (with an empty context meaning "nothing syncs with this"). So all roundcube tabs would have "roundcube" as their context (or similar), but your smartphone might have an empty context (so it is settable separate from all other devices).
  • everything is currently keyed on username. would it be better to key on user_id, even if for now user_id == username?

Otherwise, take a peek at the branch. It's just one commit at the moment, but it works nicely with multiple browser tabs open :)

p.s. What is the system ping message for? Can we get rid of it? Makes the javascript console rather noisy over time :)

Ah, one other "little" issue .. in the listBy() javascript function there is this:

listBy(user, {metas: metas})
{
  return {
    user: user,
    status: metas[0].status
  }
}

I have modified this to now pick the "best" status, not just the first one. So if a user is away on one device, but available on another, show them as available. Pushed to the same branch as commit 9195bcd

See D363. Still I prefer to use system channel for presence operations. Additionally implemented "client context". Still does not implement status persistence.

machniak claimed this task.
machniak moved this task from Ready to Done on the Kolab Chat board.
machniak closed subtask T2124: User status as Resolved.