<< Back to previous view

[ASYNC-172] ClojureScript `catch :default` in `go` fails with non-`js/Error` classes Created: 27/Jul/16  Updated: 27/Jul/16

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Alex Gunnarson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: clojurescript


 Description   

In ClojureScript, `(catch :default e ...) in a `go` block fails with non-`js/Error` classes. That is, throwing e.g. a number, a String, etc. fails (not that this is good practice anyway, but still). I came upon this while porting Slingshot (scgilardi/slingshot) to CLJS.

Given the following tests:

```
(defn test0
"Prints 'Error: nil'."
[]
(go (println "Error:"
(<! (go (throw (js/Error.)))))))

(defn test1
"Prints 'Error: #object[Error Error]'."
[]
(go (println "Error:"
(<! (go (try (throw (js/Error.))
(catch :default e e)))))))

(defn test2
"Doesn't print anything in addition to the console error
msg. Chrome says 'Uncaught 123'."
[]
(go (println "Error:"
(<! (go (try (throw 123)
(catch :default e e)))))))
```

`test2` should print 'Error: 123', but doesn't.

(As a sidenote, shouldn't `test0` return the thrown js/Error instead of printing to the console that there was an uncaught error and returning nil?)



 Comments   
Comment by Alex Gunnarson [ 27/Jul/16 3:59 PM ]

Sorry, I should have specified that this is for ClojureScript version 1.9.93 and core.async version 0.2.385. Also forgive the lack of markup.





[ASYNC-163] Off-by-two in pipeline-async parallelism Created: 17/Mar/16  Updated: 17/Jun/16

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Moritz Heidkamp Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

[org.clojure/clojure "1.8.0"]
[org.clojure/core.async "0.2.374"]



 Description   

The actual parallelism of pipeline-async is greater by 2 than what was passed. Here's the simplest reproduction case I could come up with:

(let [message-count 20
      parallelism 5
      parallel-count (atom 0)
      input (async/to-chan (range message-count))
      output (async/chan message-count)]
  (async/pipeline-async parallelism
                        output
                        (fn [_ result]
                          (async/go
                            (swap! parallel-count inc)
                            (async/<! (async/timeout 1000))
                            (async/>! result @parallel-count)
                            (swap! parallel-count dec)
                            (async/close! result)))
                        input)
  (async/<!! (async/into [] output)))

Results in something like this:

[7 4 7 5 3 7 2 7 7 7 5 3 1 3 6 4 3 1 2 6]


 Comments   
Comment by Kevin Downey [ 17/Mar/16 2:07 PM ]

I suspect this is just a lack of clarity around what parallelism means
in the context of pipeline-async.

A parallelism of 'n' for pipeline-async means there are 'n' logical
threads spinning off async tasks, and because those tasks are async,
those logical threads spin off the task, and proceed to the next. The
other thing that 'n' effects is the size of the buffer for the
`results` channel internally in the pipeline. because the tasks are
asynchronous, the only throttle is effectively the size of the buffer
on the output channel.

If the only throttle is the buffer, which is of size 'n', why do we
seem to have n+2 logical threads running at once, well because there
are a few extra channels involved which combined with the logic for
copying from channel to channel, effectively adds another buffer of
size 2.

This behavior does seem arcane. But I would argue that the
behavior of pipeline-async is so different from pipeline and
pipeline-blocking that it really should be something distinct from
them. The other pipelines take transducers, and using the parallelism
'n' to spin up a number of logical threads for the other pipelines
actually does throttle the number of tasks run in parallel.

If you have not spent time evaluating which `pipeline` variant you
needed to use, and just grabbed `pipeline-async` because that is the
one that seemed intuitively the right choice (because it has `-async`
and this is `core.async`) you almost certainly should be using the
vanilla `pipeline` variant, its behavior is much more intuitive it is
much more likely to be what you want.

Comment by Moritz Heidkamp [ 21/Mar/16 5:30 PM ]

Hi Kevin, thanks for your reply! After reading it, I think your point
regarding clarity around what parallelism means in the context of
pipeline-async is spot on It seems to be quite a different
beast from the other pipelines, indeed.

We actually did evaluate the various options and from the
documentation it seemed to be the right tool in our case: We want to
launch a maximum number of parallel asynchronous HTTP requests. We
immediatley ruled out pipeline-blocking since we are not doing
blocking requests after all and don't want to hog up n threads
just for waiting for the requests to finish. We also figured that this
isn't really "computational parallelism" (as the documentation of
pipeline puts it), so pipeline-async seemed like the best
fit. Its API also looked well suited for this case: We just needed to
launch the HTTP request in af and then fill and close the
conveniently supplied result channel in the the request's completion
callback. This seemed to work fine – until we actually hit the limit
of the connection pool, that is.

I'm not sure how we would use pipeline to the same effect. And
moreover, it's now rather unclear to me what pipeline-async's
intended use case is. Can you perhaps enlighten me some more? That
would be much appreciated

Comment by Kevin Downey [ 21/Mar/16 7:05 PM ]

I dunno.

That does sort of sound like a thing for which you would use pipeline-async, but my experience with nio predates core.async, so I am not sure what the best way to stick the two together is. I am sort of skeptical about combining even "async" io libraries like http clients with core.async, since the async of the io system is different from the async of core.async, and when combining the two it is easy to screw up and use some blocking convenience function because async is hard.

depending on the nature of the http request and how you consume the results it would, of course, be way simpler to use a synchronous http library and pipeline-blocking. if you are bounding the number of http requests at a time to a certain number, I suspect you will run out of io capacity before the jvm has trouble with that number of threads.

if pipeline-async is working for you otherwise, besides the +2 thing, then, uh, maybe just subtract 2





[ASYNC-161] `<!` inside nested `let` inside `go` block erroneously yields "<! not used inside go block" error Created: 21/Feb/16  Updated: 17/Jun/16

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Jonathan Leonard Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Mac OS X.
Node 4.1.1.
Clojure 1.7.0
ClojureScript 1.7.170



 Description   

Title says it all.



 Comments   
Comment by Jonathan Leonard [ 21/Feb/16 3:08 PM ]

Actually, my code is a bit more complicated:

(defn func []
   (go
     (let [...]
       (for [[a b c d] e]
         (let [...]
            (when pred
               (let [val (<! ...)]  ...)))))))
Comment by Nicola Mometto [ 21/Feb/16 3:20 PM ]

You cannot user `for` inside a go block

Comment by Jonathan Leonard [ 21/Feb/16 3:39 PM ]

The `for` cannot appear anywhere inside a `go`? Or the `for` cannot contain inside it any async calls; i.e., is it ok for `for` to appear somewhere in the let binding as a sibling to a call to <!?

Comment by Nicola Mometto [ 21/Feb/16 3:48 PM ]

You can't use `<!` inside a `for` inside a `go` block, code like this OTOH should be valud:

(go 
  (let [.. (for [..] ..)] 
    (<! ..)))
Comment by Jonathan Leonard [ 21/Feb/16 4:45 PM ]

Ahh, perfect! Thx!





[ASYNC-158] and with multiple <! does not short-circuit in go Created: 26/Jan/16  Updated: 14/Mar/16

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Asher Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None
Environment:

org.clojure/clojurescript "1.7.48", org.clojure/clojure "1.7.0-RC1", org.clojure/core.async "0.2.374"



 Description   

I have an and condition inside a go block, where the two conditions take from channels.
When the first condition returns false, I would expect the second condition not to be checked at all. But, it is.

Here is the code:

(defn cc [x]
   (go 
     (println "cc: " x)
   x))

  (defn foo [x]
    (go (when (and (= :ok (<! (cc x)))
                   (= :ok (<! (cc 2))))
          (print "after and"))))

(foo 1)
(foo :ok)

When running (foo 1), I would expect only cc: 1 to be printed, but actually cc: 2 is printed as well.

Happens only in ClojureScript, not in Clojure core.async.



 Comments   
Comment by Asher [ 26/Jan/16 6:14 AM ]

Note: This only happens in ClojureScript. In Clojure it works as expected.

Also, sorry for the poor formatting.. this is my first Jira issue.

Comment by Wang Xing [ 14/Mar/16 9:39 PM ]

Seems and works abnormal in many cases, not just with <!.
I tested this in:
clojure-1.8.0, clojurescript-1.7.228, core.async-0.2.374.
this test need nodejs with the request module.

(def request (js/require "request"))

Now I try to send request to an unaccessible site: google.
Yes, I can't use google.

(def result-chan (chan))

(request
  "http://www.google.com"
  (fn [err res body]
    (go
      (if (and (not err) (= (.-statusCode res) 200))
        (>! result-chan body)
        (>! result-chan [])))))

the result should be "[]" (the request will timeout make "err" non-nil)

(go
  (println "result:" (<! result-chan)))

but actually I get:
TypeError: Cannot read property 'statusCode' of undefined ...
I have printed err and I am sure it's a JS object in this case, not nil or false. that's why res is undefined.
And it also means the short-circuit for and didn't work.
to make things right, use "if" instead of "and"

(def result-chan (chan))

(request
  "http://www.google.com"
  (fn [err res body]
    (go
      (if (not err)
        (if (= (.-statusCode res) 200)
          (>! result-chan body)
          (>! result-chan []))
        (>! result-chan [])))))

then test it again:

(go
  (println "result:" (<! result-chan)))

work as expected now:

result: []




[ASYNC-150] Unordered pipeline Created: 01/Nov/15  Updated: 01/Nov/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Corin Lawson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I have a use case for clojure.core.async/pipeline whereby the order of the outputs is unimportant and it is desirable to have the nth output present on the to channel without having to wait for the first output to be ready.

I don't have a great deal of experience with clojure; I'm wondering if this is something that belongs in the core library or whether there's some idiomatic way of achieving an unordered pipeline without rewriting the pipeline function. In any case, I have made an attempt at rewriting pipeline, and learnt a thing or two in the process

Obviously, this code (below) cannot be merged as it completely breaks the existing behaviour (not to mention I've barely tested it), but I would be appreciative if you could provide some feedback and/or consider adding this functionality. Perhaps a new function, unordered-pipeline?

(defn- pipeline*
  ([n to xf from close? ex-handler type]
     (assert (pos? n))
     (let [ex-handler (or ex-handler (fn [ex]
                                       (-> (Thread/currentThread)
                                           .getUncaughtExceptionHandler
                                           (.uncaughtException (Thread/currentThread) ex))
                                       nil))
           jobs (chan n)
           results (chan n)
           process (fn [[v p :as job]]
                     (if (nil? job)
                       (comment closing results here would be too early)
                       (let [res (chan 1 xf ex-handler)]
                         (>!! res v)
                         (close! res)
                         (put! p res)
                         true)))
           async (fn [[v p :as job]]
                   (if (nil? job)
                     (comment closing results here would be too early)
                     (let [res (chan 1)]
                       (xf v res)
                       (put! p res)
                       true)))]
       (go-loop []
                (let [v (<! from)]
                  (if (nil? v)
                    (close! jobs)
                    (do
                      (comment removed the indirection and pass results as part of the job)
                      (>! jobs [v results])
                      (recur)))))
       (go-loop []
                (let [res (<! results)]
                  (if (nil? res)
                    (when close? (close! to))
                    (do (loop []
                          (let [v (<! res)]
                            (when (and (not (nil? v)) (>! to v))
                              (recur))))
                        (recur)))))
       (go
         (comment ensure results is closed after all jobs have been processed)
         (<! (async/merge
               (map #(case %
                       :blocking (thread
                                   (let [job (<!! jobs)]
                                     (when (process job)
                                       (recur))))
                       :compute (go-loop []
                                         (let [job (<! jobs)]
                                           (when (process job)
                                             (recur))))
                       :async (go-loop []
                                       (let [job (<! jobs)]
                                         (when (async job)
                                           (recur)))))
                    (repeat n type))))
         (close! results)))))


 Comments   
Comment by Corin Lawson [ 01/Nov/15 1:51 AM ]

I've only tried the :compute scenario...

(snooze [] (Thread/sleep (+ 5 (rand-int 10))))
(defn slowly [f] (fn
  ([] (snooze) (let [out (f)] (snooze) out)) 
  ([r] (snooze) (let [out (f r)] (snooze) out))
  ([r i] (snooze) (let [out (f r i)] (snooze) out))))
(def cout (chan))
(pipeline 3 cout (comp slowly (map inc)) (async/to-chan (range 18)))
(<!! (async/into [] cout))
-> [1 3 2 4 5 6 8 9 7 10 12 11 13 14 15 16 17 18]

Each group of 3 (n) is outputted in a random order





[ASYNC-148] Shorten core.async go block variable names Created: 28/Sep/15  Updated: 28/Sep/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Daniel Compton Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: PNG File Screenshot of Google Chrome.png    

 Description   

When using core.async go blocks in ClojureScript, code is transformed into asynchronous functions. When an error occurs inside one of these go blocks, the name is printed as part of the stack trace. These names can get very long, for example one recent stack trace I saw was:

day8.mwi_enhancer.steps.load_mwi.handlers.load_previous_steps_state.cljs.core.async.impl.dispatch.run.call.day8$mwi_enhancer$steps$load_mwi$handlers$load_previous_steps_state_$_state_machine__24889__auto____1

This name is so long that it doesn't even fit on the display of a 13" Macbook in the Chrome console, and part of the name and location of the code is wrapped.

Can anything be done about making the name shorter? In this case there is a lot of duplication in the name, but there is probably a good reason why it was done this way.






[ASYNC-145] mix throws assertion error when many channels are added to a mix. Created: 08/Sep/15  Updated: 08/Sep/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Angus Fletcher Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Found in core.async version 0.1.346.0-17112a-alpha


Attachments: Text File 0001-Change-channel-to-sliding-buffer-090815.patch     Text File 0001-Change-channel-to-sliding-buffer.patch    
Patch: Code

 Description   

When a large number of channels is added to a mix simultaneously, this error is thrown:

java.lang.AssertionError: Assert failed: No more than 1024 pending puts are allowed on a single channel. Consider using a windowed buffer.

We can reproduce the issue with the following in a REPL:

user> (require '[clojure.core.async :as a])
nil
user> (defn mixtest []
(let [out (a/chan 1024)
mix (a/mix out)]
(dotimes [i 2048]
(let [chan (a/chan)]
(a/admix mix chan)
(a/put! chan i)))))

(mixtest)
#'user/mixtestAssertionError Assert failed: No more than 1024 pending puts are allowed on a single channel. Consider using a windowed buffer.
(< (.size puts) impl/MAX-QUEUE-SIZE) clojure.core.async.impl.channels.ManyToManyChannel (channels.clj:150)
user>

This is a consequence of the use of an unbuffered channel in the mix implementation. Since the channel's function is just to update the mix's internal data structure, using a windowed buffered channel appears to clear up this issue. Patch 0001-Change-channel-to-sliding-buffer.patch contains the proposed solution.



 Comments   
Comment by Angus Fletcher [ 08/Sep/15 2:32 PM ]

Update patch to include cljs fix as well.





[ASYNC-144] pipeline-async docstring correction Created: 27/Aug/15  Updated: 27/Aug/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Derek Troy-West Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Currently says:

"af must close! the channel before returning."

more correctly:

"af is responsible for closing the channel.", or similar.

af is asynchronous so should return immediately, the thread or go-block it spawns should close the channel later.






[ASYNC-134] async/alts!! with an empty vector throws ArrayIndexOutOfBoundsException Created: 27/Jul/15  Updated: 28/Jul/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Daniel Compton Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I'm not sure if this is intended, but this code throws an exception.

(async/alts!! [])
;; => ArrayIndexOutOfBoundsException 1  clojure.core.async/random-array (async.clj:182)

Is this desired behaviour, or is there another way we could represent that this collection is empty? I'm thinking of the pattern where we take from any channel, and recur with that channel removed from the collection until the collection is empty. Perhaps this usage should be discouraged. If it should be discouraged, should it be documented in the docstring?



 Comments   
Comment by Alex Miller [ 28/Jul/15 9:08 AM ]

What would you expect this to do?

Comment by Daniel Compton [ 28/Jul/15 5:20 PM ]

You could return [nil nil]? That's not great either though. Documentation is probably a better fix.





[ASYNC-131] go! or "go-now" for CLJS Created: 29/Jun/15  Updated: 06/Jul/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Thomas Heller Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I'd like to see a variant of the "go" macro that executes immediately until the first parkable operation instead of dispatching (effectively calling "setTimeout" twice). This is primarily for CLJS since CLJ can get away with blocking operations but it still might be useful there as well.

My Use-Case:

I currently use core.async to orchestrate CSS animations together and while it works perfectly fine with "go" it does require careful attention to detail on the order of operations since "go" will yield control back to the browser which may decide to reflow/repaint the screen although the animation wasn't properly started yet.

Example:

(defn show-toast [message]
  (let [toast (create-toast-dom message)]
    (dom/append js/document.body toast)
    ;; X - PROBLEM: REPAINT HAPPENS NOW
    (go (<! (anim/slide-in-from-bottom animation-time toast))
        (<! (timeout 3000))
        (<! (anim/fade-out animation-time toast))
        (dom/remove toast)
        )))

This example tries to create a "Toast" [1] DOM node which is animated in from the bottom and removed after 3 seconds. A real implementation would require handling clicks and so forth but the example is easy enough to describe the problem. The (anim/...) functions set the appropriate CSS and return a (async/timeout time) channel which lets us wait for the "completion".

The problem at X is that the go is dispatched and control is given back to the browser. Therefore the "setup" part of the animation is delayed and the toast dom node is rendered by the browser as is. Usually this means that the browser will do a repaint. This will have a "flicker" effect as the node appears and then disappears again and animates (depending on the default CSS).

The simple solution is to move the dom/append call into the go block, which is easy enough in this example but hard for more complex. Another solution is to start the animation outside the go:

(defn show-toast [message]
  (let [toast (create-toast-dom message)]
    (dom/append js/document.body toast)
    (let [slide-in (anim/slide-in-from-bottom animation-time toast)]
      ;; REPAINT, but slide-in animation already started so no "flicker"
      (go (<! slide-in)
          (<! (timeout 3000))
          (<! (anim/fade-out animation-time toast))
          (dom/remove toast)
          ))))

Again, simple enough here, hard for more complex things.

What I would prefer to see is a "go!" variant which instead of dispatching the go block just starts executing it.

(defn show-toast [message]
  (let [toast (create-toast-dom message)]
    (dom/append js/document.body toast)
    (go! (<! (anim/slide-in-from-bottom animation-time toast)) ;; REPAINT ON <!
         (<! (timeout 3000))
         (<! (anim/fade-out animation-time toast))
         (dom/remove toast)
         )))

The subtle difference is that the browser does not get a chance to do anything before we are ready and would wait anyway. After fine-tuning a few of those animation effects myself it always requires moving stuff out of or into go blocks as it stands now.

I'm aware that this is a rather specific use-case and core.async might not even be the best way to do this at all but so far I had great success with it and the code is very easy to reason about.

I have not looked too much into the internals of core.async but go! should be a pretty simple addition. If this change is accepted I would start looking into things and create a patch, just wanted to make sure there were no objections before doing so.

Hope my intent is clear. CSS animations can be a bit counter-intuitive which might not make it obvious where the problem actually lies.

[1] http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs



 Comments   
Comment by Thomas Heller [ 06/Jul/15 6:06 AM ]

I looked into the issue to find out what needed to be done on the core.async side to facilitate this change, turns out nothing.

(defmacro go!
  "just like go, just executes immediately until the first put/take"
  [& body]
  `(let [c# (cljs.core.async/chan 1)
         f# ~(ioc/state-machine body 1 &env ioc/async-custom-terminators)
         state# (-> (f#)
                    (ioc/aset-all! cljs.core.async.impl.ioc-helpers/USER-START-IDX c#))]
     (cljs.core.async.impl.ioc-helpers/run-state-machine state#)
     c#))

Works perfectly fine so far and can live perfectly well inside a library, I'm beginning to think that this might be a better "default" for CLJS since there are no "threads" that could start running the "go".

With the normal "go" the flow of execution is:

code before go
setTimeout/nextTick
code inside go until first take/put
setTimeout/nextTick

With go! it is:

code before go!
code inside go! until first take/put
setTimeout/nextTick

Given the non-blocking nature of Javascript the extra setTimeout does not hurt it doesn't provide much benefit either.

Since no changes to core.async are required I can simply keep this macro in my library. My use-case is rather specific so feel free to close the issue if there is no interest to make this "common".

Comment by Leon Grapenthin [ 06/Jul/15 5:46 PM ]

As a default this would violate the async execution guarantee of go which would be a breaking change. Some observations from my user perspective: For readability I'd prefer both examples you proposed for usage of go over go-now because go conveys async execution of its entire body whereas in go-now I'd have to scan the body for a parkable operation to determine the part which executes synchronously. I find it difficult to convince myself that there could really be problems so complex that go-now would be preferable over refactoring go. (I don't think you can safely rely on impl namespaces in library code )





[ASYNC-130] Improve put! docstring to mention no more than 1024 pending puts are allowed Created: 21/Jun/15  Updated: 21/Jun/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Daniel Compton Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: docstring


 Description   

The put! docstring says:

> "Asynchronously puts a val into port, calling fn0 (if supplied) when
complete. nil values are not allowed. Will throw if closed. If
on-caller? (default true) is true, and the put is immediately
accepted, will call fn0 on calling thread. Returns nil."

It would be good if it also mentioned that it can throw if more than 1024 pending puts are already on the channel. It could be something like:

> "Asynchronously puts a val into port, calling fn0 (if supplied) when
complete. nil values are not allowed. Will throw if closed or if there are more than 1024 pending puts. If
on-caller? (default true) is true, and the put is immediately
accepted, will call fn0 on calling thread. Returns nil."






[ASYNC-121] compilation warning when calling 'satisfies?' inside a go block Created: 21/Apr/15  Updated: 21/Apr/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Yehonathan Sharvit Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: compiler
Environment:

[org.clojure/core.async "0.1.346.0-17112a-alpha"]
[org.clojure/clojurescript "0.0-3196"]



 Description   

This piece of code is causing the following compilation warning:

(defprotocol a)
(defrecord b [])
(go (satisfies? a (b.)))

WARNING: Use of undeclared Var cljs-explore.me/bit_4884auto_ at line 12 src/cljs_explore/me.cljs






[ASYNC-118] (ClojureScript) A let-binding named 'arguments' not bound in go block on nodejs Created: 14/Mar/15  Updated: 14/Mar/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Sean Doig Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: binding, cljs, nodejs
Environment:

OS X 10.10, node 0.10.35, Clojure 1.6.0, ClojureScript 0.0-3030, core.async 0.1.346.0-17112a-alpha



 Description   

Discovered this while using tools.cli 0.3.1 where it's handy to destructure one of their returned maps which has a key :arguments, but you can reproduce it like so:

(let [arguments [:a :b]]
    (println "Args Sync:" arguments)
    (go (println "Args Async:" arguments)))

which prints

Args Sync: [:a :b]
Args Async: #js {:0 #js [#<function (state_12638){
switch(arguments.length){
case 0:
return dls$rip$core$go_BANG__$_state_machine__6252__auto____0.call(this);
case 1:
return dls$rip$core$go_BANG__$_state_machine__6252__auto____1.call(this,state_12638);
}
throw(new Error('Invalid arity: ' + arguments.length));
}> 1 nil nil nil nil #<[object Object]>]}

I haven't tested this in the browser yet, so it might not be limited to node.



 Comments   
Comment by Sean Doig [ 14/Mar/15 12:34 PM ]

Just tried, can't reproduce in Chrome.





[ASYNC-114] Allow a second arity on channel ex-handler which takes val as well as throwable Created: 27/Jan/15  Updated: 19/Feb/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Derek Troy-West Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None

Attachments: Text File 0001-Pass-the-val-along-with-the-exception-to-the-channel.patch    

 Description   

When a transducer is applied to a channel and an exception occurs during transformation the ex-handler will be called with
the Throwable as an argument.

Can we also send the val which caused the transformation exception to the ex-handler? When dealing with transducer errors it might be useful to have the full picture.

If that's agreeable, and the solution is a second-arity on ex-handler that takes val and throwable, and the call applied is:

clojure.core.async.impl.channels becomes:

(defn chan
...
(try
(add! buf val)
(catch Throwable t
(handle buf exh t val)))))))))

I would be happy to supply a patch.

Apologies if I have missed something obvious.
Derek



 Comments   
Comment by Nivedita Priyadarshini [ 19/Feb/15 5:56 AM ]

Found the same need when using core.async/pipeline in my code. Wrote a patch of sorts (demonstrative) which allows you to have val in the exh for clj. Happy to write a full patch if this looks okay.





[ASYNC-113] alt!! should not evaluate the :default expr if a non-default clause is selected Created: 13/Jan/15  Updated: 27/Jul/15

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Caleb Spare Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Clojure 1.5.0, core.async 0.1.346.0-17112a-alpha


Approval: Triaged

 Description   

alt!! will always evaluate the expr given in the :default clause. For instance, consider this code:

(require '[clojure.core.async :as async])
(let [c1 (async/chan 1)
      c2 (async/chan 1)]
  (async/alt!!
    [[c1 "a"]] (println "first")
    [[c2 "a"]] (println "second")
    :default (println "default")))

It will print either "first" or "second", but also (always) "default". Reading the documentation, technically it doesn't say whether the non-selected clauses are evaluated (only that the value of the selected expr is returned) but it's certainly not the behavior I would expect.

I haven't checked whether alt! does the same thing as well.



 Comments   
Comment by Daniel Compton [ 27/Jul/15 7:37 PM ]

It looks to me like :default is expected to be a value, not a function, and println is being run as part of evaluating the alt!! expression, not as the return value.





[ASYNC-111] maps are represented different inside and outside of go blocks Created: 27/Dec/14  Updated: 27/Dec/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Sven Richter Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

clojure 1.6.0, clojurescript "0.0-2371", W7, Oracle JDK 8



 Description   

When initializing a state atom with a set "conjuring" a map behaves differently depending of the scope where it happens:

(def state (atom {:transformations []}))
(reset! state {:transformations #{:foo "bar"}})

; throws: Uncaught Error: compare on non-nil objects of different types
(...(go ;some async stuff
(swap! state conj {:name "baz"}))...)

; works
(...(go ;some async stuff)
(swap! state conj {:name "baz"}))

I am not sure if this is a defect at all as maps are not comparable as Tom in the thread stated. However, the fact that it works in one case and does not in the other is weird.
You can find the complete thread here: https://groups.google.com/forum/#!topic/clojurescript/lmvltpa3k8s






[ASYNC-108] cljs to-chan hangs on infinite lazy sequences Created: 20/Nov/14  Updated: 20/Nov/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Felix Andrews Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: cljs
Environment:

[org.clojure/core.async "0.1.346.0-17112a-alpha"]


Patch: Code

 Description   

e.g. this hangs the browser:

(go-loop [ch (to-chan (range))]
(println (<! ch))
(<! (timeout 1000))
(recur ch))

The problem is in
https://github.com/clojure/core.async/blob/53bf7866f195e6ba247ff7122b99784e66e9f1bb/src/main/clojure/cljs/core/async.cljs#L362
where the order of arguments to bounded-count is wrong.






[ASYNC-107] Improved docstring for alt! Created: 10/Nov/14  Updated: 10/Nov/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Howard Lewis Ship Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: docstring

Attachments: Text File core-async-alt-doc-1.patch    
Patch: Code

 Description   

I had a little remembering exactly how alt! is used, and put together some better documentation that more clearly identifies the differences between taking from and putting to channels.






[ASYNC-98] Less hostile message for #'go stopping at (fn [] ) boundaries Created: 15/Oct/14  Updated: 15/Oct/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ghadi Shayban Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: errormsgs


 Description   

ASYNC-93 has an example of a not nice message when #'go attempts to shred through a (fn []) form. Maybe we can improve this, but then again creating a (fn []) in a block should be permitted, though the inner contents of it will not be transformed.






[ASYNC-96] FixedBuffer's full checking in cljs Created: 13/Oct/14  Updated: 13/Oct/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Nguyễn Tuấn Anh Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs-fixed-buffer-overflow.patch    
Patch: Code and Test

 Description   

In the cljs implementation of fixed buffer, "full?" uses "=" instead of ">=". This makes it incorrect after an overflow.






[ASYNC-91] 'and' does not short circuit within go block in clojurescript Created: 14/Sep/14  Updated: 25/Sep/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Jan Krueger Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Environment:

core.async 0.1.338.0-5c5012-alpha



 Description   

I have the following piece of ClojureScript code within a go block:

(cond
(and (vector? x) (= (first x) :some-key)) ...)

This generates the following piece of JavaScript code for the cond case:

if (40 === f) { return d = b[9], f = cljs.core.vector_QMARK_.call(null, d), d = cljs.core.first.call(null, d), d = cljs.core._EQ_.call(null, d, new cljs.core.Keyword(null, "some-key", "some-key", -978969032)), cljs.core.truth_(f && d) ? b[1] = 42 : b[1] = 43, new cljs.core.Keyword(null, "recur", "recur", -437573268); }

This looks to me like both and arguments would actually get evaluated. As a result my code crashes whenever it hits this cond case and 'x' is not seqable.



 Comments   
Comment by Francis Avila [ 25/Sep/14 2:52 AM ]

CLJS-864 is likely the same issue. (It also has a small test project to reproduce.)





[ASYNC-77] StackOverflowError in go macro with cemerick.cljs.test (CLJS) Created: 04/Jul/14  Updated: 04/Jul/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Daniel Skarda Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

[org.clojure/clojure "1.6.0"]
[org.clojure/core.async "0.1.303.0-886421-alpha"]
[org.clojure/clojurescript "0.0-2261"]
[com.cemerick/clojurescript.test "0.3.1"]



 Description   

I got an StackOverflowError during compilation of CLJS tests using clojurescript.test from Chas Emerick.

I narrowed the problem to following code:

(ns async.overflow.cljs
  (:require-macros [cljs.core.async.macros :refer [go]]
                   [cemerick.cljs.test :refer [deftest is]])
  (:require [cemerick.cljs.test]))

(deftest foobar
  (go
    (is (= 1 1))
    (is (= 1 1))
    (is (= 1 1))
    (is (= 1 1))
    (is (= 1 1))
    (is (= 1 1))
    (is (= 1 1))
    (is (= 1 1))))

If you do not get the exception, try to increase number of repetitions of 'is' call.

I was not able to replicate the issue in CLJ. cemerick.cljs.test/is macro is probably far more complex than original CLJ version in clojure.test/is.






[ASYNC-69] How to better communicate "mix" lifecycle wrt coordination Created: 09/May/14  Updated: 09/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Timothy Baldridge Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Approval: Vetted

 Description   

Confusion regarding 'mix' lifecycle. Users have a false expectation that a mix's output should magically close when its source channels close, not realizing its a dynamic coordination process. Actually ensuring correctness when using mult/mix/pub isn't so straightforward, people need to control consistency from the producer end, and not ad hoc from the consumer side (e.g. late taps of a mult).






[ASYNC-67] Can we get a generic sink operation? Created: 09/May/14  Updated: 07/Oct/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ghadi Shayban Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None

Approval: Triaged

 Description   

Can we get a generic sink operation?

(defn sink
 "Fully consumes and discards a channel, applying f to each val. Returns a channel that
  closes when ch is fully drained"
 [f ch]
 (go-loop []
   (when-some [v (<! ch))]
     (f v)
     (recur))))





[ASYNC-66] Add drain! to consume and discard a channel Created: 09/May/14  Updated: 09/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ghadi Shayban Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Approval: Vetted

 Description   

Do we want this for consumer walkaway scenarios or something baked into the channel impl?

(defn drain!
 "Fully consumes and discards a channel. Returns a channel that
  closes when ch is fully drained"
 [ch]
 (go-loop []
   (if (some? (<! ch))
     (recur))))





[ASYNC-65] Change chan returned from pipe to internal go block out channel Created: 09/May/14  Updated: 09/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ghadi Shayban Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Approval: Vetted

 Description   

Can (pipe src dest close?) return the chan of its internal go block instead of 'dest'? This would provide a useful 'done' channel.






[ASYNC-63] Variable called 'new' in vector in go block in CLJS causes "Object has no method 'call'" error Created: 07/Apr/14  Updated: 05/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: James Henderson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, cljs
Environment:

ClojureScript 0.0-2202, core.async 0.1.267.0-0d7780-alpha, openjdk 7u51


Attachments: File compiled-cljs.js     File test_cases.clj    

 Description   

I seem to be having trouble with the combination of:

  • a variable named 'new'
  • wrapped in a vector
  • after a <! call in a go block.

Removing any of these conditions seems to work fine.

I've attached a few minimal examples in test_cases.clj and the JavaScript that the first error compiles down to in compiled-cljs.js - the errors occur on line 4 (I think inst_39771 is 21 in this case)

An obvious workaround is not to name the variable 'new'

Please let me know if you need anything more from me, and please go easy on me if this is in the wrong place/badly labelled etc - it's my first Clojure JIRA bug report

Thanks,

James



 Comments   
Comment by James Henderson [ 07/Apr/14 4:07 PM ]

Sorry, just spotted there's a newer release of core.async - I've reproduced this with 0.1.278.0-76b25b-alpha as well.

James





[ASYNC-61] Exceptions thrown inside go/thread blocks propagate up and out of ThreadPoolExcecutor Created: 24/Mar/14  Updated: 06/Aug/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Howard Lewis Ship Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: exceptions
Environment:

core.async 0.1.267.0-0d7780-alpha on JDK 1.7



 Description   

If a go or thread blocks throws an exception, there is nothing in Clojure to catch and handle (or report) the exception. Instead, it propagates up to the ThreadExcecutor which invokes its NO-OP afterExecute() method and is re-thrown, ultimately being displayed on the System.err:

Exception in thread "async-dispatch-32" java.lang.IllegalStateException: Fall down, go boom!
at flashiz.resources.orders$index.invoke(orders.clj:26)
at clojure.lang.Var.invoke(Var.java:411)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.core$apply.invoke(core.clj:617)
at io.aviso.rook$rook_dispatcher.invoke(rook.clj:225)
at flashiz.async$wrap_sync_handler$fn__9005.invoke(async.clj:34)
at flashiz.resources$authorize_async_rook_middleware$fn_9356$fn9402$state_machine3245auto__9403$fn_9405.invoke(resources.clj:21)
at flashiz.resources$authorize_async_rook_middleware$fn_9356$fn9402$state_machine3245auto___9403.invoke(resources.clj:21)
at clojure.core.async.impl.ioc_macros$run_state_machine.invoke(ioc_macros.clj:945)
at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invoke(ioc_macros.clj:949)
at clojure.core.async.impl.ioc_macros$take_BANG_$fn__3261.invoke(ioc_macros.clj:958)
at clojure.core.async.impl.channels.ManyToManyChannel$fn__2256.invoke(channels.clj:80)
at clojure.lang.AFn.run(AFn.java:24)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)

It would be nice if execution of the go/thread block was wrapped in an exception handler that delegated to a default function to report the exception. My goal is to be able to alter that function to report it more nicely and/or write it to a persistent log file.



 Comments   
Comment by Alex Miller [ 06/Aug/14 10:30 AM ]

Patches on ASYNC-76 have been applied and exceptions will now flow up to the top of the thread, where they can be caught by the standard Thread uncaught exception handler mechanism or ultimately by the default uncaught exception handler, which can be set for the application. There may still be further changes to support exception handling in thread/go.





[ASYNC-55] Notification of items dropped from sliding/dropping buffers Created: 12/Feb/14  Updated: 05/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Chris Perkins Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None

Attachments: File drop-notification.diff    
Patch: Code and Test

 Description   

I would like to know when items are dropped from sliding or dropping buffers, so that I can do things like logging and keeping metrics.

The attached patch has one possible mechanism for doing this, by adding an optional second argument to sliding-buffer and dropping-buffer - a one-argument function that will be called with dropped items.



 Comments   
Comment by Ghadi Shayban [ 22/Apr/14 10:41 AM ]

Hi Chris, I think this use-case can be handled the combination of a go process + collection directly without modification to the existing buffer impls. I'd be concerned about making buffers pay for a non-essential field.

I like using the library primitives to make sure they are minimally complete.

(If you really really want to make your own buffer, no one will stop you =) It's still an impl protocol, but it's relatively stable. Just beware that buffer operations run within the context of a channel lock, so make sure to dispatch the overflow function to the async threadpool using dispatch/run).





[ASYNC-40] do not transform forms that have :no-transform metadata attached Created: 29/Nov/13  Updated: 05/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None


 Description   

Interaction between core.match clauses and the core.async transform is undesirable. core.async should respect some hook so that some forms are left alone. For example:

(match [x y]
  [1 2] ...
  [3 4] ...)

All code generated for [1 2] and [3 4] would have this metadata attached to it.



 Comments   
Comment by Rich Hickey [ 30/Nov/13 9:25 AM ]

Can you be more specific? This seems like a bad idea, and I wonder why it's desired.

Comment by David Nolen [ 30/Nov/13 2:12 PM ]

To show how bad the interaction is between core.async and a library like core.match that also generates a lot of code consider the following:

(defn foo [e]
  (match [e]
    [{:type :mouse :client-x x :client-y y}] [x y]
    [{:type :mouse :page-x x :page-y y}] [x y]
    [{:type :touch :page-x x :page-y y}] [x y]
    [{:type :key :char-code c}] c))

Without core.async, core.match produces a reasonable amount of code for this typical use of core.match to efficiently match maps - ~230 lines of pretty printed JavaScript.

But if the user wraps this typical expression in a go block:

(defn foo [in]
  (go (while true
        (let [[e c] (<! in)]
          (match [e]
            [{:type :mouse :client-x x :client-y y}] [x y]
            [{:type :mouse :page-x x :page-y y}] [x y]
            [{:type :touch :page-x x :page-y y}] [x y]
            [{:type :key :char-code c}] c)))))

It generates nearly 4200 lines of pretty-printed JavaScript. I fail to see the value of core.async transforming the optimized conditionals generated by core.match, it just generates 18X more code and the extra generated code is obviously useless - a user is matching a value, they cannot put arbitrary computations in the patterns.

https://gist.github.com/swannodette/7723758





[ASYNC-39] Processes spawned by mix never terminate Created: 21/Nov/13  Updated: 05/May/14

Status: Open
Project: core.async
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Leon Grapenthin Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: chan, mix
Environment:

"0.1.256.0-1bf8cf-alpha"



 Description   

Once a mix has been created, the go-loop inside mix will always recur. Obviously, input-channels can be unmixed and the output-channel could be closed, but the process would still never terminate.

Probably mixes should support something like (stop) to to make the mix-associated process garbage-collectable. Operations on a stopped mix should probably throw.



 Comments   
Comment by Ghadi Shayban [ 22/Apr/14 10:44 AM ]

On 0.1.278 the mix process terminates when its output channel closes [1].

[1] https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L778

Comment by Leon Grapenthin [ 24/Apr/14 3:16 AM ]

Yes, it has been fixed using the new return behavior of put!. (I can't find an option to close this issue)





Generated at Thu Jul 28 03:50:33 CDT 2016 using JIRA 4.4#649-r158309.