help with noir-async

71 views
Skip to first unread message

Samrat Man Singh

unread,
Sep 4, 2012, 9:48:46 PM9/4/12
to clj-...@googlegroups.com
In a Noir web app I'm working on, I'm trying to move the processing from the web instance to a `future`. So, I want some of the content(that depends on the processing) to load upon the future's completion. I can use Noir-async for the job, right? How do I do it?

I tried adding some futures in the Noir-async code provided in the docs but the future seemed to be taking place in the web instance anyway. 

  (def f (future (do (Thread/sleep 10000) "chunk three")))                                                                                   
  (async-push conn @f)

Am I doing something wrong?

Andrew Cholakian

unread,
Sep 4, 2012, 9:54:37 PM9/4/12
to clj-...@googlegroups.com
It is executing on a separate thread, but dereferencing via @ makes the thread that spawned the future block. So you have two threads, but the main thread is blocked because of @.

What you most likely want to do instead is:

(future (Thread/sleep 1000 async-push "chunk three"))

What may in fact be preferable to that as well is to use a thread pool via the executors framework. You can enqueue futures onto a fixed or cached thread pool for a little more efficiency.

BTW, if you just want a sleep interval, it's best to use an instance of a Timer instead of sleeping a thread, as that will be much more efficient. Noir-async comes with some convenient set-timeout and set-interval functions in its util class. So you could write (set-timeout 1000 #(async-push "chunk three")). Assuming you've imported noir-async.utils

Hope that helps! Let me know if you have any other questions.

Samrat Man Singh

unread,
Sep 4, 2012, 11:15:41 PM9/4/12
to clj-...@googlegroups.com
I don't want a sleep interval, I just used that because it seemed to emulate what I want. There seems to be a typo in:

  (future (Thread/sleep 1000 async-push "chunk three")) 

because that gives me an error, instead I tried wrapping those in parantheses and when that didn't work I tried to put the whole thing in a do block. But it still didn't give me the result I wanted (ie push the data after the page has already been loaded.)

Samrat Man Singh

unread,
Sep 4, 2012, 11:17:00 PM9/4/12
to clj-...@googlegroups.com
I'll also check out the Executors framework you mentioned.


On Wednesday, September 5, 2012 7:39:42 AM UTC+5:45, Andrew Cholakian wrote:

Andrew Cholakian

unread,
Sep 5, 2012, 3:08:30 AM9/5/12
to clj-...@googlegroups.com
Ah, yes, those weren't full examples, and they were untested.

Some simple async routes can be found here:
https://github.com/andrewvc/engulf/blob/master/src/engulf/web_views/test_responses.clj

For an example of using the executors framework see this page:

http://clojure.org/concurrent_programming

I'd recommend browsing the java docs at
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html
a bit too. You can just pass a fn in to an executor, is clojure FNs
implement both callable and runnable.

On Tue, Sep 4, 2012 at 8:17 PM, Samrat Man Singh

Samrat Man Singh

unread,
Sep 5, 2012, 6:57:24 AM9/5/12
to clj-...@googlegroups.com, and...@andrewvc.com
Thanks for the examples, but I'm still not sure that's what I want. I just don't see how I can use those async routes to make something like a push notification. Am I missing something?

Also, are there any examples of websocket usage, that you'd recommend I check out? 

Andrew Cholakian

unread,
Sep 5, 2012, 11:10:05 AM9/5/12
to clj-...@googlegroups.com
Well, there's an example of a web socket on the noir-async README https://github.com/andrewvc/noir-async

(defpage-async "/echo" [] conn
  (on-receive conn (fn [m] (async-push conn m))))


Aleph automatically  detects a web socket connection and handles it correctly. You can push to it any time you like. 

You can also send a streaming chunked response as well. There's an example on the README for that as well.

You may want to look at the source-code to the noir-async-chat example https://github.com/andrewvc/noir-async-chat Specifically views/chatroom.clj
Message has been deleted

Samrat Man Singh

unread,
Sep 5, 2012, 12:11:49 PM9/5/12
to clj-...@googlegroups.com
I'm sorry if I'm missing the point but why doesn't either of the two routes below work?

(defpage-async "/chunky" [] conn                                                                                                        
  (async-push conn "chunk one")                                                                                                         
  (future (async-push (str (apply + (range 1e8))))))                                                                                    
                                                                                                                                        
(defpage-async "/chunky2" [] conn                                                                                                       
  (async-push conn "chunk2 one")                                                                                                        
  (async-push conn (future (str (apply + (range 1e8)))))) 

They give the initial message but not the second one.

Andrew Cholakian

unread,
Sep 5, 2012, 12:16:50 PM9/5/12
to clj-...@googlegroups.com
Both of those examples do work with a web socket.

For plain HTTP clients you'll need to send the 'chunked' header first.

To send the chunked header simply invoke:

(async-push conn {:status 200 :chunked true})

You'll want to detect whether the connection is a web socket or not first. You can use noir-async's websocket? function to do this. Something like:

(when (not (websocket? conn)) (async-push conn {:status 200 :chunked true}))

With that at the top both a  websocket and plain connection will send incremental messages just fine.
Reply all
Reply to author
Forward
0 new messages