Fork me on GitHub

Am I correct in that the usage of Thread/sleep is not recommended as in example from Brave clojure?

(defn upload
  [headshot c]
  (go (Thread/sleep (rand 100))
      (>! c headshot)))
Should one use thread instead (with >!! since >! cannot be used outside of go)?


And btw. why does this keep printing different channel "strings" (I expected the same channels/pictures would lead to the same .toString representation):

(let [c1 (a/chan)
        c2 (a/chan)
        c3 (a/chan)]
    (upload "serious.jpg" c1)
    (upload "fun.jpg" c2)
    (upload "sassy.jpg" c3)
    (let [[headshot channel] (a/alts!! [c1 c2 c3])]
      (printf "Sending headshot notification for %s (%s)\n" headshot channel)))

Sending headshot notification for fun.jpg ([email protected])
Sending headshot notification for fun.jpg ([email protected])
Sending headshot notification for fun.jpg ([email protected])
Sending headshot notification for fun.jpg ([email protected])
Sending headshot notification for serious.jpg ([email protected])
Sending headshot notification for serious.jpg ([email protected])


thread sleep will block worker thread that execute go-block code


Calling append-to-file inside the go block ( also doesn't look like the best approach


another question: how do people monitor core.async channels in practice? I couldn't find much about this stuff, only this


The more appropriate thing to do in that snippet would be (a/timeout (rand 100)) rather than the sleep

👍 4

Yes, thanks, also found that option. In general, it seems that blocking calls are tricky. Either you have some sort of non-blocking IO lib or use threads with limited thread pool?


yep. The only "blocking" calls that should be in go blocks are the parking >! <! operations.


besides that you can quickly get around things by tossing the call into a a/thread call.


and also remember that channels are very useful even outside of a core.async, go block context


@U1XTUTPMY you mean using the blocking variants like >!!, <!!, alts!!, etc., perhaps with buffered channels? kind of like queues for decoupling components of your system?


right. you can just use those with plain threads.


The channels don't even need to have buffers, but if you give them buffers then they are perfectly fine queues.


There are plenty of reasons to have them without buffers still. See SynchronousQueue in Java


for instance, you could have a plain thread that is blocking on io and then >!! into a channel. one or more go blocks could be parked on that channel waiting for the input.


a potential way to push the I/O to the outer edges of the program and ferry it into the core.async machinery if needed.


Perfect, thanks a lot for the details


I was wrestling with similar questions a while back. Seems like there a very common need for a companion library that deals with this kind of stuff.


we don't really monitor channels at work. we have some custom buffer types that report metrics, but those aren't really used, we mostly generate metrics for processes reading and writing to channels. how often they loop, how long each loop takes, how many messages they are sending out as they loop

👍 4

using custom buffer types for monitoring channels isn't that great, because buffers are only used if a channel cannot immediately hand off


a lot of the system where we use core.async the heaviest is very actor like, loops around reading from an input channel, and handling the message