This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # babashka (17)
- # beginners (166)
- # calva (97)
- # cider (4)
- # clara (2)
- # clj-kondo (46)
- # cljsrn (5)
- # clojure (334)
- # clojure-canada (1)
- # clojure-dev (144)
- # clojure-europe (14)
- # clojure-germany (5)
- # clojure-nl (10)
- # clojure-spec (1)
- # clojure-uk (46)
- # clojurescript (50)
- # conjure (1)
- # core-async (52)
- # core-typed (5)
- # cursive (3)
- # datomic (3)
- # emacs (11)
- # figwheel (16)
- # figwheel-main (9)
- # fulcro (29)
- # graalvm (19)
- # graphql (14)
- # helix (46)
- # hoplon (4)
- # hugsql (2)
- # jobs (2)
- # jobs-discuss (1)
- # juxt (15)
- # kaocha (6)
- # off-topic (9)
- # pedestal (7)
- # portkey (7)
- # re-frame (10)
- # reagent (29)
- # shadow-cljs (13)
- # spacemacs (70)
- # sql (13)
- # tools-deps (26)
- # xtdb (23)
Is there a way to know when a channel has closed? Like if I want to do some cleanup in the process using it?
@colinkahn It will return
nil when you take from it, I believe.
@seancorfield right, I guess I'm talking about a channel I'm putting values into.
I saw that
put! will return false if it's closed, but that isn't immediate feedback, requires something attempts a put first
Well, it's async so you pretty much have to interact with it in order to tell whether it has closed or not.
What people often do is have an extra "control" channel and then you "alt" across the actual channel and the control channel...
(let [ch (chan) _ (clojure.core.async/close! ch)] (clojure.core.async.impl.protocols/closed? ch))
Whenever I’ve needed to check that, there was almost always a way around it… it’s not very idiomatic usage of CSP channels as far as I understand
My situation is like this:
but I was wondering if there's a way if
(defn read-from-client  (let [out-chan (a/chan) client (make-client)] (.on client "change" #(a/put! out-chan %)) out-chan))
out-changets closed if there's a way to setup something in my
read-from-clientfunction that can destroy the client etc.
@raspasov yeah it's not checking necessarily that it's closed, but having something happen when it closes
but then all values will get read in that loop, so I couldn't have consumers. I guess I could have it be a mult?
Multiple potential consumers that need to receive the same value? In that case you can use (promise-chan)
Use the put! arity that takes a callback, it will get called with true when a value is written to a channel, and false if not because the channel is closed
@hiredman my issue with that was that if my client "change" callback isn't called again the client doesn't get cleaned up because another put is never attempted
@colinkahn how can that channel get closed? do you call (close! …) on it potentially in your code?
that was my plan, whoever calls the
read-from-client function could later close the
out-chan, and I was hoping I could have a side effect of closing it be destroying the client instance
I would say… since you control the (close! … ), just cleanup right after you call close
yea… that’s why closing channels is just not a very good idea in general… are you sure you need to do this cleanup stuff? Maybe you can arrange it so that this “change” handler just persists for the duration of the program
Maybe there’s a way to have a long-lived/global out-chan that is just one channel and constantly receives “stuff”
not really, it needs to be created/destroyed when certain state changes, so new information can be used to create it
Maybe there’s a way to have a channel with a transducer, that does some sort of logic?
Or even have a global out-chan, and then have one (go (loop … )) that does the processing and decides there and then what to do with that data
Setting up/destroying a new handler on every message or frequently is just a recipe for race conditions and further issues like @hiredman very well pointed out
You’re almost getting nothing out of core.async then vs regular callbacks… you might be even making your life harder
At least that’s my feeling from my partial information perspective about the problem 🙂
well I think the answer to the original question is pretty clearly a no, which makes sense for those reasons
Yea… the one reliable way, again, is to have a loop, and when that returns a nil -> means closed, and exhausted of all messages
But actually thinking about what @hiredman said about the race condition… cleaning up after a (close! …) might not be a problem, since we’re only talking about removing that callback… that wouldn’t interfere with any leftover data on the channel as long as there’s active takers that will process that data (as far as I understand)… but again that can create a problem where in between calling (close! ..) and actually removing that callback you might try to put! onto a closed channel!
So it’s not really a problem about the channel… but the fact that you might accidentally drop data: 1. (close! ch) 2. DATA SHOWS UP, we try to (put! ch-that-just-closed) 3. remove handler