core-async

Jakub Holý 2019-10-21T14:50:36.015600Z

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:

(future
  (->> ["hello"]
       (a/onto-chan (a/chan)) ; <- error, should be (a/to-chan)
       (a/transduce
         (map #(throw (ex-info "Fake exc" {:v %})))
         (fn [a v] v)
         {})
       (a/into [])
       (a/<!!)))
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.

markmarkmark 2019-10-21T14:54:00.016100Z

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

Jakub Holý 2019-10-21T14:55:15.016800Z

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

markmarkmark 2019-10-21T14:55:16.016900Z

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

markmarkmark 2019-10-21T14:56:02.017200Z

ah

markmarkmark 2019-10-21T14:56:49.017800Z

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

markmarkmark 2019-10-21T14:57:04.018100Z

so it's blocked at &lt;!! forever

Jakub Holý 2019-10-21T14:57:40.018500Z

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

markmarkmark 2019-10-21T14:58:37.018800Z

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

Jakub Holý 2019-10-21T14:59:07.019200Z

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

markmarkmark 2019-10-21T14:59:40.019400Z

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

markmarkmark 2019-10-21T14:59:45.019600Z

presumably

Jakub Holý 2019-10-21T14:59:45.019800Z

This (a/&lt;!! (a/onto-chan (a/chan) [])) returns (nil)

Jakub Holý 2019-10-21T15:00:38.020Z

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

markmarkmark 2019-10-21T15:02:27.020200Z

k

Jakub Holý 2019-10-21T15:02:55.020400Z

but thank you for trying, I appreciate it!

Jakub Holý 2019-10-21T15:28:02.022900Z

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...

2019-10-21T15:48:35.024900Z

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

2019-10-22T14:04:16.027300Z

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 https://github.com/district0x/ethlance/blob/newlance/src/ethlance/server/filesystem.cljs#L10 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

👍 1
Jakub Holý 2019-10-21T15:49:47.025Z

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

2019-10-21T15:57:39.025200Z

I suppose that would be up to you 😛

2019-10-21T16:01:04.025400Z

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.

2019-10-21T16:02:58.025600Z

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

Jakub Holý 2019-10-21T21:36:32.026Z

Well, it is not fully up to me. As demonstrated by https://clojurians.slack.com/archives/C05423W6H/p1571669436015600, missing error handling will lead to deadlocks.