I am trying to build a scalable chat server in Clojure. I am using http-kit, compojure and redis pub/sub to communicate between diffrent nodes (fan-out approach). The server will use websockets for connection b/w client-server with a fallback to long polling. A single user can have multiple connections to chat with one connection per tabs in the browser and message should be delivered to the all the connections.
So basically when the user connects I store the channel in a atom with a random uuid as
{:userid1 [{:socketuuid "random uuid#1 for uerid1" :socket "channel#1 for userid1"}
{:socketuuid "random uuid#2" :socket "channel#2"}]
:userid2 [{:socketuuid "random uuid#1 for userid2" :socket "channel#1 for userid2}]}
the message is POSTed to a common route for both websockets and long polling channels, the message structure looks like
{:from "userid1" :to "userid2" :message "message content"}
the server finds all the channels in the atom for the :from and :to user ids and send the message to the connected channels for the respective users, also it publishes the message over the redis server where the connected nodes look for channels stored in their own atom and deliver message to the respective users.
So the problem I am running into is, how to properly implement presence. Basically http-kit send you a status when a channel disconnects the status can be "server-close" or "client-close", while I can handle server disconnects (the client will reconnect automatically) but I am running into problem when the disconnect happens from client side, for eg. the user navigates to another page and will connect after a few seconds. How do I decide that the user has went offline when the client disconnects. Also I am concerned about message arrival b/w reconnects in long polling mode (my long polling timeout is 30 seconds).
Also please suggest a good presence mechanism for the above architecture. Thanks.
Please comment if you need more info. Thanks
Edit #1:
Can you recommend a good tutorial/ material on implementing presence in a chat server, I cant seem to find anything on it.
My current solution -> I am currently maintaining a global count and a last connected timestamp for the connected channels of a particular userid and when a user disconnects the count is decreased, and a timeout is implemented for 10 seconds which will check if the user has reconnected again (i.e. the last connected stamp is 10 seconds old and count is still zero), if not then the user is said to have gone offline, would you recommend this solution, If not why, or any improvements or better methods are appreciated. Also please note I am using the timer/scheduled-task in http-kit, would these timeout significant performance effects?