Search code examples
clojurecore.async

core.async: terminate go loop after timeout


I have a function which processes a stream of values from a shared channel and looks for a value which satisfies a specific predicate:

(defn find-my-object [my-channel]
  (go-loop []
    (when-some [value (<! my-channel)]
      (if (some-predicate? value)
        value
        (recur)

Now I want this function to return some 'failure' value after waiting for a timeout, which I have implemented like this:

(alts! [(find-my-object my-channel) (timeout 1000)])

The problem with this is that the go-loop above continues to execute after the timeout. I want find-my-object to drain values from my-channel while the search is ongoing, but I don't want to close my-channel on timeout, since it's used in some other places. What is the idiomatic way to implement this functionality?


Solution

  • Read from the timeout channel inside of find-my-object, not outside of it. You can hardcode that if you like, or make the function take a second channel argument, which is the "please stop reading things" channel. Then you can pass it a timeout channel to get the behavior you want now, or pass it some other kind of channel to control it in a different way.