Build readable async pipelines with channels, go blocks, and explicit backpressure.
core.async gives you CSP-style channels: a channel is a queue-like coordination primitive, and you compose your program as small stages that put values onto channels and take values off channels.
Inside a go block, channel operations park rather than blocking an OS thread, which makes it practical to express a lot of waiting without a lot of threads.
1(require '[clojure.core.async :as a])
2
3(let [ch (a/chan 10)]
4 (a/go (a/>! ch {:event :ping}))
5 (a/go (println (a/<! ch))))
Java mental model: a channel can feel like
BlockingQueue, but the important difference is “parking vs blocking” and the need to keep blocking I/O out ofgo.