This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-24
Channels
- # announcements (30)
- # asami (9)
- # babashka (37)
- # beginners (120)
- # calva (26)
- # cider (3)
- # clara (9)
- # clj-commons (7)
- # clj-kondo (17)
- # cljsrn (2)
- # clojure (32)
- # clojure-europe (56)
- # clojure-nl (1)
- # clojure-norway (13)
- # clojure-uk (4)
- # clojurescript (34)
- # conjure (1)
- # copenhagen-clojurians (8)
- # core-async (21)
- # cursive (2)
- # datahike (2)
- # datascript (5)
- # events (4)
- # fulcro (32)
- # graalvm (10)
- # heroku (3)
- # introduce-yourself (1)
- # jobs (2)
- # lsp (3)
- # luminus (1)
- # malli (8)
- # meander (15)
- # minecraft (1)
- # nrepl (2)
- # off-topic (57)
- # pathom (2)
- # polylith (35)
- # reagent (6)
- # reitit (8)
- # releases (1)
- # rewrite-clj (7)
- # shadow-cljs (21)
- # timbre (4)
- # tools-build (1)
- # tools-deps (33)
- # vrac (8)
Hello! I am trying to put together a list of "golden rules" of core.async. What do you think about this: General 1. Respect back-pressure, i.e. do not try to put stuff into a channel faster than it is consumed (beware of the “max 1024 pending puts”) 2. Have a strategy for error handling Go blocks 1. Never call a blocking operation within a go block (including <!!, >!!) 2. Go blocks stop at the function boundary, i.e. if you call a function using parking channel operations, it must have its own go block and return its channel to enable back-pressure ? Anything missing? Anything wrong? 🙏
do not try to put stuff into a channel faster than it is consumed
I would say, in this case, to use parking/blocking operations >! >!!, instead of put! . That will wait until the message is accepted by the channel. When different channels are connected on a pipeline using these operations in loops, you guarantee that the producer won’t be faster than the consumer, because it will always wait until messages can be consumed. That’s how you achieve backpressure. Avoid using put! or (go (>! …)) as these don’t wait for messages to be consumed, so then you can end up with faster producers than consumersIf you look at the implementations of pipe
, mult
, pub
etc they all use >!
in go-loops, so they will never put into channels faster than what the consumer (and buffers) can support
When I set put i did not mean (just) put!
🙂 It was exactly to cover what you said. Do you have an eloquent way to change my sentence to make it clearer while still keeping it short?
yes, this is more of a heuristic - try to not do anything "significant" in go blocks
the less obvious, don't do heavy CPU. What's the difference between doing blocking IO and heavy CPU operations? They both hog the thread
Since the go-blocks thread pool is global and is not a fork-join pool, if you fill it up with cpu ops the threads will be too busy to transfer stuff between channels
Another heuristic I've adopted is separate logistics, wiring and business logic. Try to write business logic which is unaware of channels, and async functions which are unaware of business logic
@U0522TWDA Maybe something along these? What do you think?
Respect backpressure, i.e don't do unbounded puts in channels, things like put! or (go (>! ...)) in loops
Or to your original sentence, maybe I would add a small note like Use >! or >!! in loops instead of put! to adapt to consumers speed
Great, thank you, Alberto!
You could say parking put for >! and parking take for <!. Blocking put is >!!, and blocking take is <!!. And async put is put!, and async take is take!
Can someone explain the naming convention of core.async with regards to one !
or two !!
?
At first I thought the single !
was reserved to things you must use inside a go
block. But that's not true, for example for put!
or poll!
.
So now all I'm seeing is that !!
means that it is blocking. And that something ends with !
or not seems to be irrelevant, since it could be that you have to use it inside go or not.
! is parking op, ok in go. !! is blocking, do not use in go