Fork me on GitHub
Jakub Holý (HolyJak)14:10:36

update: There is a bug in the code, it should use to-chan not onto-chan => the input is never read Could somebody be so kind and tell me why this future is forever :pending:

  (->> ["hello"]
       (a/onto-chan (a/chan)) ; <- error, should be (a/to-chan)
         (map #(throw (ex-info "Fake exc" {:v %})))
         (fn [a v] v)
       (a/into [])
Is it because the map that throws does not consume the item from the input channel and thus the channel will never close? If that is the case then I guess I need to wrap all my transducers into an explicit try-catch (or set an error-handler on a channel, though it is unclear to me where to do it in this code snippet)~ Note: This works as expected if I (map identity) instead of throwing. So it seems that if the transducer throws, the item on the channel is not consumed => the input channel is not closed => <!! never finishes.


a/transduce and a/into require that the source channel be closed before they will produce any results

Jakub Holý (HolyJak)14:10:15

From onto-chan docs: > By default the channel will be closed after the items are copied And this works if I use (map identity) instead of throwing


hm, though maybe a/onto-chan should be closing that chennl


probably, the thrown exception doesn't end up putting anything onto the channel


so it's blocked at <!! forever

Jakub Holý (HolyJak)14:10:40

<!! doesn't wait until there is something on the channel. It will also finish if the channels is closed.


right, but the channel is coming from the into, right?

Jakub Holý (HolyJak)14:10:07

yes, but into will return an empty collection of it gets a closed channel I believe


right, but into is getting the channel from transduce, and it's not getting to the close part of the code because an unhandled exception is being thrown

Jakub Holý (HolyJak)14:10:45

This (a/<!! (a/onto-chan (a/chan) [])) returns (nil)

Jakub Holý (HolyJak)15:10:38

We can presume a lot 🙂 I'd like an explanation from somebody who actually knows.

Jakub Holý (HolyJak)15:10:55

but thank you for trying, I appreciate it!

Jakub Holý (HolyJak)15:10:02

Has somebody written about best practices regarding error handling in core.async, especially in the higher level constructs such as pipeline and transduce? My search hasn't discovered much useful...


I don't know if this is considered best practise, but i'm a fan of writing async functions that return a vector [success-channel error-channel] and handling each case either directly, or with helper functions to handle the error case

Jakub Holý (HolyJak)15:10:47

Ok but eg with transduce, do I need to wrap the body of my xform and reducing fn in try-catch?


I suppose that would be up to you 😛


Also depends on where you're using the functions, your philosophies on how errors might be handled. Some people like their software to fail fast and hard so they can diagnose the issue faster. Some people like to catch everything and print to an error log.


@U04V70XH6 usually has insightful things to say about these sorts of things

Jakub Holý (HolyJak)21:10:32

Well, it is not fully up to me. As demonstrated by, missing error handling will lead to deadlocks.


Yes, but that's because you didn't close your channel. So it isn't entirely related, but I understand your concerns Here's an example, where i'm closing the channels to make sure there are no deadlocks Note that channels return nil when they are closed, so I can use the same pattern if I were consuming from a success channel. I would just check to see if what is returning is nil and then consume the error channel to see if there were any errors to either handle and display an error message, or throw if i'm producing an error that was placed on the channel

👍 4