SSE implementation using individual channel per user

14 views
Skip to first unread message

Росен Христов (Rossen Hristov)

unread,
Mar 27, 2024, 1:02:52 PM3/27/24
to pedestal-users
Hello,

I am working on an application that used to use websockets but due to scaling issues with them, we decided to replace them with server-sent events (SSE).

Our goal is to make it possible to create an SSE channel for every successfully logged user in order to be able to close this channel after user logout or session timeout in order not to consume unnecessary resources by unused channels remaining opened after the given user is logged out. These user channels we store in an atomic map registry and want to access the channel of the specific logged user (recognized by its session token used as a key in the registry) to send the messages to the frontend.

We used initally the io.pedestal.http.sse namespace but the problem with it is that it expects the handler to accept a "default" channel as route handler input argument:

 and  if I try to use the separate user channel the messages are not received, for example in Postman I get empty response, the response contains the expected messages only if you rely on te default channel that the handler gets as input aregument:
This the route using   start-event-stream   which returns an interceptor that uses the handler whenever a message has to be sent:
(defn sse-handler [channel ctx]
...)


This is the route:
(def sse-route ["/rest/sse" :get (sse/start-event-stream sse-handler)
    :route-name :sse])


This is the handler:
(defn sse-handler [channel ctx]
  (doseq [[id {:keys [name data] :as payload}] @LIVE-NOTIFICATIONS]
    (when-not (chan/closed? channel)
      (async/>!! channel payload)
      (swap! LIVE-NOTIFICATIONS dissoc id)
      (Thread/sleep 1000)))
  (async/close! channel))


My question is: Is it possible to implement such a scenario using the individual user channel not the input one coloured in red above and how? Do I have to implement my own custom interceptor or I still can use the   io.pedestal.http.sse ns somehow?Or if I have to use the input argument channel is it possible for example to access it somehow to close it when the user is logged out?

Thank you in advance for the help!
Rossen Hrisrov 
Reply all
Reply to author
Forward
0 new messages