Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread/sleep inside Clojure go block

I'm having internal conflict about using Thread/sleep inside a Clojure go block. It is generally not recommended to have any long-running process inside go blocks, and Stuart Sierra mentions that sleeping in go block is not preferred:

In general, any work which doesn't block, sleep, or do I/O can be safely put in a go block without having a major impact on the throughput of the system.

In my case, I want to listen to the messages on a channel, and group them before notifying user if they come rapidly. Or, if only one message comes along, notify user about it. In my particular use case, it's rather common for several messages to come either in rapid succession or alone, and unlikely for messages to come in regular intervals.

To achieve this, I have a go-loop block that waits input on a channel. When it receives it sleeps a bit (a second or two at most), checks if any other input arrived on a channel in the meantime, and based on that either notifies user about a whole thing or just passes along the first message.

I will not have a bunch of such go blocks in my application, only one. As Clojure always spawns more then one thread to serve go blocks, blocking one thread with sleep shouldn't be a problem in practice. But in theory, I wonder if there's a more elegant way to handle this without tying up a thread like this?

like image 683
Domchi Avatar asked Sep 02 '25 09:09

Domchi


1 Answers

Instead of blocking in Thread/sleep you should rather use clojure.core.async/timeout. There is an example on ClojureDocs very similar to your scenario:

(go-loop [seconds (atom 0)
          add-seconds! #(swap! seconds + %)]
  (println "Waiting 1 second")
  (<! (timeout 1000))
  (add-seconds! 1)
  (println "Waiting 2 seconds")
  (<! (timeout 2000))
  (add-seconds! 2)
  (println
    (format "Waited %s seconds"
            @seconds))) 
like image 150
Piotrek Bzdyl Avatar answered Sep 05 '25 02:09

Piotrek Bzdyl