Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manage connections in Aleph (clojure) based on metadata

I've written a very simple broadcast/echo server that uses web sockets with clojure and aleph.

I spent a lot of time looking through the aleph and lamina sources to get a decent, basic understand what's happening here.

What I want to do

  1. Establish connections from clients
  2. Send occasional instructions to the server
  3. The instructions are executed and a response is sent to others based on some meta-data about the connection

So this can process the data (which is great) and format the response (which is great). How can I get it to send the response only to relevant parties?

What I have so far

(defn do-something
  [arg]
  (str "pickles" "are" "nice" arg))

(defn ws-handler [ch request]
  (siphon (map* #(do-something %) ch) broadcast-channel)
  (siphon broadcast-channel ch))

(defn -main
  "Start the http server"
  [& args]
  (start-http-server ws-handler {:port 8080 :websocket true}))

Example Request

Let's say I had this request in JSON:

{"room":32, "color":"red", "command":"do something..."}

I would want this to execute the "do something..." command, then the resultant output would be sent to everyone else whose most recent command had included {"room":32, "color":"red"}.

I don't understand how to manage connections this way in aleph... any help?

like image 259
Sir Robert Avatar asked Nov 30 '25 15:11

Sir Robert


1 Answers

If you want more granularity in who receives what message, you need something more granular than a "broadcast-channel". Lamina provides a (named-channel ...) function which allows you to create your own namespace of channels.

This would look something like:

(defn broadcast [channel-name message]
  (enqueue (named-channel channel-name nil) message))

(defn subscribe [channel-name client-channel]
  (let [bridge-channel (channel)]
    (siphon 
      (named-channel channel-name nil)
      bridge-channel
      client-channel)
    #(close bridge-channel)))

The subscribe method, in this case, ensures that the client connection will receive all messages from that particular channel, and returns a function that will cancel that subscription. You'll need to have some per-client state that holds onto those cancellation callbacks, but I'll leave that as an exercise for the reader.

like image 129
ztellman Avatar answered Dec 02 '25 04:12

ztellman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!