I’m trying to build a chat-like feature using websockets, and I need users (only 2) to send some initial data to each other. this is an example of what I’ve done so far, but i’m missing something:
(def signals (chan))
(def publication (pub signals :source))
(defn user-handler [signals publication room user_id other_id data]
(let [user-chan (chan)
topic (keyword (str room "_" user_id))]
(sub publication topic user-chan)
(go
(>! signals {:source (keyword (str room "_" other_id))
:room room
:user_id user_id
:other_id other_id
:data data}))
(go
(let [timeout-chan (timeout 15000)]
(alt!
timeout-chan :timeout
user-chan ([received-data] (println received-data)))))))
(comment
(user-handler signals publication "room1" 1 2 "Hello from user1")
(user-handler signals publication "room1" 2 1 "Hello from user2")
)
;; expect to print:
{:source :room1_2, :room "room1", :user_id 1, :other_id 2, :data "Hello from user1"}
{:source :room1_1, :room "room1", :user_id 2, :other_id 1, :data "Hello from user2"}
;; got:
{:source :room1_1, :room "room1", :user_id 2, :other_id 1, :data "Hello from user2"}
Edit
Finally, I decided to go with a different approach, instead of using pub
and sub
with channels, I just use one channel per user:
(def all-channels (atom {}))
(defn user-handler [room user_id other_id data]
(let [data {:room room
:user_id user_id
:other_id other_id
:data data}
user-chan (chan)
other-chan (get @all-channels other_id)]
(swap! all-channels assoc user_id user-chan)
(when other-chan (go (>! other-chan data)))
(go
(let [timeout-chan (timeout 30000)]
(alt!
timeout-chan (println user_id " Timeout !")
user-chan ([received-data]
(println received-data)
(>! (get @all-channels other_id) data)))))))
(user-handler "room1" 1 2 "Hello from user1")
(user-handler "room1" 2 1 "Hello from user2")
it prints:
{:room room1, :user_id 2, :other_id 1, :data Hello from user2}
{:room room1, :user_id 1, :other_id 2, :data Hello from user1}