Currently learning core.async and it's seems that I don't get how to handle exceptions. I try to resume my experiments in a gist. https://gist.github.com/Charlynux/86a46dc721153ab7679a858533950376 My main concern is why this code doesn't works.
(defn consume-values [ch]
(go
(try
(throw (Exception. "my exception message"))
(catch Throwable t (println (.getMessage t)) :error)
(finally (a/close! ch)))))
It works for the producer, but not for the consumer, I need to move close!
in the catch body.
In my mind, finally
is called just after the try (or catch), but no.
Can someone point me an explanation or may be a better pattern ?hard to say, you wrote that up nice, but it is still a bunch of text to tear through to just figure out what you are doing, what you expect, and what you get that surprises you
there are lots of possible things going on
one thing is that a go block without any channels operations like in many of your examples, is basically the same thing as the code without the go macro
so very likely whatever thing you are having trouble understanding, happens without involving core.async at all, so you haven't finished shrinking your test case
the other thing is there are some long standing bugs in how the go macro transforms try/catch/finally, which I don't think you are triggering because you aren't doing any channel ops, so the go macro isn't doing any transformations, but it is hard to say
I try to reduce the code at the minimum, but you're right by removing all channels ops, I probably generate strange (and useless) cases. I'll try to create a more useful example.
the issue is your producer doesn't check the result of writing to the channel to see if that succeeded or not
there is a bug, if I recall, where if you write to a channel, and then that channel is closed, you never resume from writing to the channel
I don't think I run in to that bug much because when I use closing a channel as a signal of completion I always do it from the producer signaling no more output to the consumer, and very often I don't use closing the communication channel to signal that, but have a specific "stop" channel that the producer and consumer both consume from and using closing of that to signal that both should stop
Thanks for all this content. There's a lot of strategies/patterns possibles with core.async, the difficulty is to find the one which fits your case and coding style.