This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-01-31
Channels
- # architecture (5)
- # beginners (35)
- # boot (150)
- # cider (1)
- # clara (7)
- # cljs-dev (131)
- # cljsrn (10)
- # clojure (76)
- # clojure-austin (3)
- # clojure-berlin (1)
- # clojure-brasil (1)
- # clojure-chicago (2)
- # clojure-dusseldorf (1)
- # clojure-italy (30)
- # clojure-nl (2)
- # clojure-russia (40)
- # clojure-serbia (2)
- # clojure-spec (25)
- # clojure-uk (13)
- # clojured (2)
- # clojurescript (106)
- # core-async (29)
- # datascript (65)
- # datomic (38)
- # emacs (8)
- # funcool (8)
- # hoplon (6)
- # jobs (3)
- # klipse (93)
- # luminus (16)
- # lumo (4)
- # off-topic (2)
- # om (11)
- # onyx (13)
- # pedestal (4)
- # protorepl (3)
- # re-frame (40)
- # reagent (31)
- # ring (6)
- # ring-swagger (4)
- # slack-help (5)
- # spacemacs (13)
- # untangled (17)
- # vim (2)
I’m getting a stream of values from a chan, I want to get them in batches of n but I don’t want to block if there’s less than n in chan's buffer and get all available instead
take a look at poll!
: http://clojure.github.io/core.async/#clojure.core.async/poll%21
@nooga since you want to do this in batches, you’ll have to roll your own (very simple I would imagine) function that loops using poll!
as @ghosss suggested, and then if it gives nil (meaning there’s no values), then just call <!!
— maybe there’s already a “take n items” function but I can’t find it.
something like this? (not thoroughly tested):
(defn nooga-take* [n ch res]
(if (>= 0 n)
res
(if-let [val (poll! ch)]
(recur (dec n) ch (conj res val))
res)))
(defn nooga-take [n ch]
(if-let [val (or (poll! ch) (<!! ch))]
(nooga-take* (dec n) ch [val])
nil))
looks about right @ghosss — but @nooga — regarding how this works: if you block on an empty channel, do you only want to return the result when n
items are in the channel, or when the first item becomes available?
The situation is following: I’ve got lists of values coming from http clients, one or more item per request, I onto-chan
the lists, and on the other side I’ve got a go block that inserts the items into a db
well, if you block on an empty channel, then “all available” will be when the first comes in, so you can only return one, unless you decide to implement a timeout and wait for a second to come in quickly, etc.
But what if I spend, say 1s inserting the previous batch and during that my handlers wrote >1 items onto the channel?
so you have two choices: 1) block and return the first item that comes from the channel 2) block and return the first item plus as many or few as you want afterward. That policy is what you determine—the quickest return is, return when the first item becomes available. The slowest is, return when n
items have been returned. Another option is to set a timeout that says, return the first and any additional within some timeout period
yeah, I once wrote something similar. to take in batches of at most n values but also after some timeout, take as big of a batch as has been built up
oh, I have one of those too
@nooga then what people are suggesting is correct do a blocking take to get the first item, poll! to get more available items, then stop when you get max-items or get a nil from poll!, insert into the DB then do a blocking take again.
@tbaldridge I’m testing this right now, so far looks like a good idea