I'm looking to start using Missionary instead of core.async but still wrapping my head around it. I am currently starting with managing websockets.
(defn send-heartbeat [delay send!]
(m/ap (loop []
(m/? (m/sleep delay))
(send!)
(println "sent ping")
(recur))))
(defn init-websocket! [url ws-conns in-chan]
(let [ws @(ws/websocket url
{:on-open (fn [ws]
(println "connected")
(ws/send! ws (json/write-str {:op "ping"}))
(m/park (send-heartbeat 1000 #(ws/send! ws (json/write-str {:op "ping"})))))
:on-message (fn [ws msg last?]
(let [{:keys [topic data]} (clojure.walk/keywordize-keys (json/read-str (str msg)))]
(println msg)))
:on-close (fn [ws status reason]
(println "WebSocket closed!"))})
ts (System/currentTimeMillis)]
(swap! ws-conns conj {:conn ws
:created ts
:url url
:id (nano-id)})))
The ws/send! is not working as I am not getting back a pong. I have tried many variations of functions and am a little confused. I also want to be able to ensure that this stops running when I close it down. I was using core.async alts before for this.This also blocks my repl and just loops printing the println. But does not call the ping.
Maybe you should take some time to play with missionary on small examples, before trying to mimic a core.async code.
Missionary is almost two different api: one about task and an other one about flow, with only one function to make a task out of a flow.
In your code you create a flow with ap but you want to park it like a task š¤
I don't know anything about websocket. Do on-open and ws/send! run on their own thread or on some js main thread?
Maybe you just need to create a flow of heartbeats and https://cljdoc.org/d/missionary/missionary/b.39/api/missionary.core#reduce over it to call ws/send! (in a task... or not. It depends on the execution model of on-open) š¤
When on-close is called do you need to notify the on-open function to make it stop?
I have been playing with it, gone through all the tutorials. Iām simply misunderstanding it and came here for clarity. Code was just copy pasted at some arbitrary point of my experiments.
This is also the smallest example I have where I am implementing it into something I am actually building.
With core.async one just creates a go-loop with a timeout and then closes that channel when they shut down the websocket.
https://github.com/ReilySiegel/missionary-websocket/blob/master/src/com/reilysiegel/missionary/websocket.cljs Maybe you can refer to this code repository
To have a code that look "kind of like" what you did with core.async, you may do something like this in your init-websocket! function.
;; create a scoped dataflow variable
;; to notify that the websocket will close
(def stop (m/dfv))
;; `on-open` will race two tasks: one to wait a stop notification
;; and an other one to send ping messages regularly
((m/race (m/sp (m/? stop)
(println :done))
(m/sp (while true
(println "send ping")
(m/? (m/sleep 1000)))))
#(println :ok %)
#(println :KO %))
;; `on-close` should notify a stop by assigning a value to the dfv
(stop :close)
I have just written things in my repl but you can incorporate it in your function let and callbacks. This code snippet only uses the Task concept of m_issionary_.Thanks. I have moved forward with a bunch of core.async but am going to bookmark this and circle back because i would like to dive deeper for missionary
I just learn better when applying it to something I am actually doing.