Re: core.async | compojure ... odd error ... help!!

2014-09-28 Thread Mike Fikes
Hi mond,

I've been using HTTPkit with Compojure and core.async (all fronted by Nginx 
so the entire stack is async FWIW).

To glue core.async with HTTPkit when handling inbound requests, I have a 
utility function

(defn handle-async! [handler req]
  (http-server/with-channel req channel
(take! (handler req) #(http-server/send! 
channel %

and I make use of that utility function when defining routes

(defroutes all-routes
   (GET "/covers/v1/:cover" [] (partial http/handle-async! 
fetch-cover!))
   (context "/books/v1" []
(GET "/search" [] (partial http/handle-async! 
search-handler!))
(GET "/:isbn" [] (partial http/handle-async! 
get-book-by-isbn!

The handler functions fetch-cover!, search-handler!, get-book-by-isbn!, all 
return channels (they either call go for stuff that needs to be async, or 
to-chan on collections read directly from memory.

- Mike 

On Saturday, September 27, 2014 5:01:36 AM UTC-4, mond wrote:
>
> Hi James,
>
> Er, nice tip on the routes - that was another thing that I didn't expect 
> to work but was happy when it did ;-) I will of course adapt it to your 
> recommendation.
>
> Speaking to the main point, no I don't want to put a channel on to the 
> response so that's a mistake that I see and would like to avoid. I would 
> like to understand where I have gone wrong.
>
> Maybe I need to use HTTPkit instead?
>
> Thanks
>
> Ray
>
>
>
> On Saturday, 27 September 2014 02:08:50 UTC+2, James Reeves wrote:
>>
>> Hi Ray,
>>
>> I don't entirely understand why you expected this to work. Channels 
>> aren't a valid Ring response body. The error message is essentially telling 
>> you that Compojure has no way of turning the channel object you've returned 
>> into a valid response.
>>
>> The other problem you have is that the Ring Jetty adapter doesn't have 
>> any support for asynchronous operations.
>>
>> Another small point. You're using "*" as an argument name, but this isn't 
>> really recommended. This only works by coincidence, and it may be removed 
>> in future versions. Instead use something like:
>>
>> (GET ["/:brand/:country/:resource" :resource #".*"] [brand country 
>> resource] ...)
>>
>> - James
>>
>> On 27 September 2014 00:14, mond  wrote:
>>
>>> My first core.async program ... all works outside of the web app but 
>>> barfs once I put the functions inside a web container. I hope somebody in 
>>> the group can point to my obvious mistake...
>>>
>>> The idea is that the function 'respond-within-sla' will give back a 
>>> result or a come back later message after N milliseconds. It is passed a 
>>> number of ms, three functions and the arguments for the final function ... 
>>> which is the one that should operate within the SLA.
>>>
>>> (defn respond-within-sla [expected-result-milliseconds respond-ok 
>>> respond-later data-fetcher & args]
>>>   (let [data-channel (timeout expected-result-milliseconds)]
>>> (go (if-let [data (>>   ((async/close! data-channel)
>>>(respond-ok data))
>>>   (respond-later)))
>>> (go
>>>   (>! data-channel (apply data-fetcher args)
>>>
>>> To keep the volume of code to parse to a minimum I have made a few toy 
>>> functions that demonstrate the failure...
>>>
>>> ; test funcs
>>>
>>> (defn ok [data]
>>>   (prn (str "send HTTP 200 ... got data " data)))
>>>
>>> (defn later []
>>>   (prn (str "send HTTP 202 ... request received, come back later")))
>>>
>>> (defn fetcher [arg1 arg2 arg3]
>>>   (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
>>>   "response-data")
>>>
>>> (defn failer [& args]
>>>   (Thread/sleep 1000)
>>>   (str "never gets here " args))
>>>
>>> ; test funcs
>>>
>>> (defn ok [data]
>>>   (prn (str "send HTTP 200 ... got data " data)))
>>>
>>> (defn later []
>>>   (prn (str "send HTTP 202 ... request received, come back later")))
>>>
>>> (defn fetcher [arg1 arg2 arg3]
>>>   (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
>>>   "response-data")
>>>
>>> (defn failer [& args]
>>>   (Thread/sleep 1000)
>>>   (str "never gets here " args))
>>>
>>> (defn generate-response [brand country resource]
>>>   (let [sla (or (env :sla-milliseconds) 100)]
>>> (respond-within-sla sla ok later fetcher brand country resource)))
>>>
>>> (defn generate-fail [brand country resource]
>>>   (let [sla (or (env :sla-milliseconds) 100)]
>>> (respond-within-sla sla ok later failer brand country resource)))
>>>
>>> From within the REPL it all works fine...
>>>
>>> (generate-response "A" "B" "C")
>>> => #>> clojure.core.async.impl.channels.ManyToManyChannel@4b7ae3f7>
>>> "fetching data with args A B C"
>>> "send HTTP 200 ... got data response-data"
>>> (generate-fail "A" "B" "C")
>>> => #>> clojure.core.async.impl.channels.ManyToManyChannel@4eb8b5a9>
>>> "send HTTP 202 ... request received, come back later"
>>>
>>> Here is the compojure route..
>>>
>>> (defroutes app
>>>(GET "/:bran

Re: core.async | compojure ... odd error ... help!!

2014-09-28 Thread Ray McDermott
Excellent - thanks. Nice to see core.async getting the ring middleware love :)

On 28 Sep 2014 at 10:48:57, Max Penet (m...@qbits.cc) wrote:

Jet supports what you were trying to do, it accepts a channel as return value 
to send the response to the client, and in the :body of the response (no matter 
the kind of response via a channel or map) to trigger chunked responses.

see here https://github.com/mpenet/jet#ring-async

On Saturday, September 27, 2014 8:08:48 PM UTC+2, mond wrote:
Thanks for the tips. I wasn't expecting magic but otherwise your points are 
well taken

Ray

Sent from my iPhone

On 27 Sep 2014, at 16:55, James Reeves  wrote:

On 27 September 2014 10:01, mond  wrote:

Speaking to the main point, no I don't want to put a channel on to the response 
so that's a mistake that I see and would like to avoid. I would like to 
understand where I have gone wrong.

You're trying to use core.async with a library that has no understanding of 
core.async. It's important to understand that core.async isn't magic; it won't 
work with libraries that weren't designed for it.
 
Maybe I need to use HTTPkit instead?

HTTP Kit has good support for async, but uses its own lightweight protocol. 
Check out the examples on their website, and if you still want to connect a 
core.async channel up to HTTP Kit, you'll need something like:

    (async/take! async-ch (fn [msg] (httpkit/send! http-ch msg)))

This tells core.async to take values off the async channel and pass them onto 
HTTP Kit.

- James
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google 
Groups "Clojure" group.
To unsubscribe from this topic, visit 
https://groups.google.com/d/topic/clojure/gOsd2Zzc1Vk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to 
clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: core.async | compojure ... odd error ... help!!

2014-09-28 Thread Max Penet
Jet supports what you were trying to do, it accepts a channel as return 
value to send the response to the client, and in the :body of the response 
(no matter the kind of response via a channel or map) to trigger chunked 
responses.

see here https://github.com/mpenet/jet#ring-async

On Saturday, September 27, 2014 8:08:48 PM UTC+2, mond wrote:
>
> Thanks for the tips. I wasn't expecting magic but otherwise your points 
> are well taken
>
> Ray
>
> Sent from my iPhone
>
> On 27 Sep 2014, at 16:55, James Reeves  > wrote:
>
> On 27 September 2014 10:01, mond > wrote:
>
>>
>> Speaking to the main point, no I don't want to put a channel on to the 
>> response so that's a mistake that I see and would like to avoid. I would 
>> like to understand where I have gone wrong.
>>
>
> You're trying to use core.async with a library that has no understanding 
> of core.async. It's important to understand that core.async isn't magic; it 
> won't work with libraries that weren't designed for it.
>  
>
>> Maybe I need to use HTTPkit instead?
>>
>
> HTTP Kit has good support for async, but uses its own lightweight 
> protocol. Check out the examples on their website, and if you still want to 
> connect a core.async channel up to HTTP Kit, you'll need something like:
>
> (async/take! async-ch (fn [msg] (httpkit/send! http-ch msg)))
>
> This tells core.async to take values off the async channel and pass them 
> onto HTTP Kit.
>
> - James
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: core.async | compojure ... odd error ... help!!

2014-09-28 Thread Max Penet
Jet supports what you were trying to do, it accepts a channel as return 
value to send the response to the client, and in the :body of the response 
(no matter the kind of response via a channel or map) to trigger chunked 
responses.

see here https://github.com/mpenet/jet#ring-async

On Saturday, September 27, 2014 8:08:48 PM UTC+2, mond wrote:
>
> Thanks for the tips. I wasn't expecting magic but otherwise your points 
> are well taken
>
> Ray
>
> Sent from my iPhone
>
> On 27 Sep 2014, at 16:55, James Reeves  > wrote:
>
> On 27 September 2014 10:01, mond > wrote:
>
>>
>> Speaking to the main point, no I don't want to put a channel on to the 
>> response so that's a mistake that I see and would like to avoid. I would 
>> like to understand where I have gone wrong.
>>
>
> You're trying to use core.async with a library that has no understanding 
> of core.async. It's important to understand that core.async isn't magic; it 
> won't work with libraries that weren't designed for it.
>  
>
>> Maybe I need to use HTTPkit instead?
>>
>
> HTTP Kit has good support for async, but uses its own lightweight 
> protocol. Check out the examples on their website, and if you still want to 
> connect a core.async channel up to HTTP Kit, you'll need something like:
>
> (async/take! async-ch (fn [msg] (httpkit/send! http-ch msg)))
>
> This tells core.async to take values off the async channel and pass them 
> onto HTTP Kit.
>
> - James
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: core.async | compojure ... odd error ... help!!

2014-09-27 Thread Ray McDermott
Thanks for the tips. I wasn't expecting magic but otherwise your points are 
well taken

Ray

Sent from my iPhone

> On 27 Sep 2014, at 16:55, James Reeves  wrote:
> 
>> On 27 September 2014 10:01, mond  wrote:
> 
>> 
>> Speaking to the main point, no I don't want to put a channel on to the 
>> response so that's a mistake that I see and would like to avoid. I would 
>> like to understand where I have gone wrong.
> 
> You're trying to use core.async with a library that has no understanding of 
> core.async. It's important to understand that core.async isn't magic; it 
> won't work with libraries that weren't designed for it.
>  
>> Maybe I need to use HTTPkit instead?
> 
> HTTP Kit has good support for async, but uses its own lightweight protocol. 
> Check out the examples on their website, and if you still want to connect a 
> core.async channel up to HTTP Kit, you'll need something like:
> 
> (async/take! async-ch (fn [msg] (httpkit/send! http-ch msg)))
> 
> This tells core.async to take values off the async channel and pass them onto 
> HTTP Kit.
> 
> - James

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: core.async | compojure ... odd error ... help!!

2014-09-27 Thread James Reeves
On 27 September 2014 10:01, mond  wrote:

>
> Speaking to the main point, no I don't want to put a channel on to the
> response so that's a mistake that I see and would like to avoid. I would
> like to understand where I have gone wrong.
>

You're trying to use core.async with a library that has no understanding of
core.async. It's important to understand that core.async isn't magic; it
won't work with libraries that weren't designed for it.


> Maybe I need to use HTTPkit instead?
>

HTTP Kit has good support for async, but uses its own lightweight protocol.
Check out the examples on their website, and if you still want to connect a
core.async channel up to HTTP Kit, you'll need something like:

(async/take! async-ch (fn [msg] (httpkit/send! http-ch msg)))

This tells core.async to take values off the async channel and pass them
onto HTTP Kit.

- James

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: core.async | compojure ... odd error ... help!!

2014-09-27 Thread mond
Hi James,

Er, nice tip on the routes - that was another thing that I didn't expect to 
work but was happy when it did ;-) I will of course adapt it to your 
recommendation.

Speaking to the main point, no I don't want to put a channel on to the 
response so that's a mistake that I see and would like to avoid. I would 
like to understand where I have gone wrong.

Maybe I need to use HTTPkit instead?

Thanks

Ray



On Saturday, 27 September 2014 02:08:50 UTC+2, James Reeves wrote:
>
> Hi Ray,
>
> I don't entirely understand why you expected this to work. Channels aren't 
> a valid Ring response body. The error message is essentially telling you 
> that Compojure has no way of turning the channel object you've returned 
> into a valid response.
>
> The other problem you have is that the Ring Jetty adapter doesn't have any 
> support for asynchronous operations.
>
> Another small point. You're using "*" as an argument name, but this isn't 
> really recommended. This only works by coincidence, and it may be removed 
> in future versions. Instead use something like:
>
> (GET ["/:brand/:country/:resource" :resource #".*"] [brand country 
> resource] ...)
>
> - James
>
> On 27 September 2014 00:14, mond > wrote:
>
>> My first core.async program ... all works outside of the web app but 
>> barfs once I put the functions inside a web container. I hope somebody in 
>> the group can point to my obvious mistake...
>>
>> The idea is that the function 'respond-within-sla' will give back a 
>> result or a come back later message after N milliseconds. It is passed a 
>> number of ms, three functions and the arguments for the final function ... 
>> which is the one that should operate within the SLA.
>>
>> (defn respond-within-sla [expected-result-milliseconds respond-ok 
>> respond-later data-fetcher & args]
>>   (let [data-channel (timeout expected-result-milliseconds)]
>> (go (if-let [data (>   ((async/close! data-channel)
>>(respond-ok data))
>>   (respond-later)))
>> (go
>>   (>! data-channel (apply data-fetcher args)
>>
>> To keep the volume of code to parse to a minimum I have made a few toy 
>> functions that demonstrate the failure...
>>
>> ; test funcs
>>
>> (defn ok [data]
>>   (prn (str "send HTTP 200 ... got data " data)))
>>
>> (defn later []
>>   (prn (str "send HTTP 202 ... request received, come back later")))
>>
>> (defn fetcher [arg1 arg2 arg3]
>>   (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
>>   "response-data")
>>
>> (defn failer [& args]
>>   (Thread/sleep 1000)
>>   (str "never gets here " args))
>>
>> ; test funcs
>>
>> (defn ok [data]
>>   (prn (str "send HTTP 200 ... got data " data)))
>>
>> (defn later []
>>   (prn (str "send HTTP 202 ... request received, come back later")))
>>
>> (defn fetcher [arg1 arg2 arg3]
>>   (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
>>   "response-data")
>>
>> (defn failer [& args]
>>   (Thread/sleep 1000)
>>   (str "never gets here " args))
>>
>> (defn generate-response [brand country resource]
>>   (let [sla (or (env :sla-milliseconds) 100)]
>> (respond-within-sla sla ok later fetcher brand country resource)))
>>
>> (defn generate-fail [brand country resource]
>>   (let [sla (or (env :sla-milliseconds) 100)]
>> (respond-within-sla sla ok later failer brand country resource)))
>>
>> From within the REPL it all works fine...
>>
>> (generate-response "A" "B" "C")
>> => #> clojure.core.async.impl.channels.ManyToManyChannel@4b7ae3f7>
>> "fetching data with args A B C"
>> "send HTTP 200 ... got data response-data"
>> (generate-fail "A" "B" "C")
>> => #> clojure.core.async.impl.channels.ManyToManyChannel@4eb8b5a9>
>> "send HTTP 202 ... request received, come back later"
>>
>> Here is the compojure route..
>>
>> (defroutes app
>>(GET "/:brand/:country/*" [brand country *]
>> (generate-response brand country *))
>>
>>(ANY "*" []
>> (route/not-found "You must use a REST style to specify 
>> brand and country keys in the URL")))
>>
>> If I now start it up 'lein run' and try to exercise the functions from 
>> the web server...
>>
>> $ curl -I http://localhost:5000/A/B/D.jpg
>> HTTP/1.1 500 Server Error
>> Date: Fri, 26 Sep 2014 23:02:03 GMT
>> Content-Length: 0
>> Connection: close
>> Server: Jetty(7.6.8.v20121106)
>>
>> And on the server I see this:
>>
>> $ lein run
>> Compiling redirector.web
>> 2014-09-27 01:01:48.426:INFO:oejs.Server:jetty-7.6.8.v20121106
>> 2014-09-27 01:01:48.458:INFO:oejs.AbstractConnector:Started 
>> SelectChannelConnector@0.0.0.0:5000
>> 2014-09-27 01:02:03.535:WARN:oejs.AbstractHttpConnection:/A/B/D.jpg
>> java.lang.IllegalArgumentException: No implementation of method: :render 
>> of protocol: #'compojure.response/Renderable found for class: 
>> clojure.core.async.impl.channels.ManyToManyChannel
>> at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:544)
>> at compojure.response$fn__213$G__208__220.in

Re: core.async | compojure ... odd error ... help!!

2014-09-26 Thread James Reeves
Hi Ray,

I don't entirely understand why you expected this to work. Channels aren't
a valid Ring response body. The error message is essentially telling you
that Compojure has no way of turning the channel object you've returned
into a valid response.

The other problem you have is that the Ring Jetty adapter doesn't have any
support for asynchronous operations.

Another small point. You're using "*" as an argument name, but this isn't
really recommended. This only works by coincidence, and it may be removed
in future versions. Instead use something like:

(GET ["/:brand/:country/:resource" :resource #".*"] [brand country
resource] ...)

- James

On 27 September 2014 00:14, mond  wrote:

> My first core.async program ... all works outside of the web app but barfs
> once I put the functions inside a web container. I hope somebody in the
> group can point to my obvious mistake...
>
> The idea is that the function 'respond-within-sla' will give back a result
> or a come back later message after N milliseconds. It is passed a number of
> ms, three functions and the arguments for the final function ... which is
> the one that should operate within the SLA.
>
> (defn respond-within-sla [expected-result-milliseconds respond-ok
> respond-later data-fetcher & args]
>   (let [data-channel (timeout expected-result-milliseconds)]
> (go (if-let [data (   ((async/close! data-channel)
>(respond-ok data))
>   (respond-later)))
> (go
>   (>! data-channel (apply data-fetcher args)
>
> To keep the volume of code to parse to a minimum I have made a few toy
> functions that demonstrate the failure...
>
> ; test funcs
>
> (defn ok [data]
>   (prn (str "send HTTP 200 ... got data " data)))
>
> (defn later []
>   (prn (str "send HTTP 202 ... request received, come back later")))
>
> (defn fetcher [arg1 arg2 arg3]
>   (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
>   "response-data")
>
> (defn failer [& args]
>   (Thread/sleep 1000)
>   (str "never gets here " args))
>
> ; test funcs
>
> (defn ok [data]
>   (prn (str "send HTTP 200 ... got data " data)))
>
> (defn later []
>   (prn (str "send HTTP 202 ... request received, come back later")))
>
> (defn fetcher [arg1 arg2 arg3]
>   (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
>   "response-data")
>
> (defn failer [& args]
>   (Thread/sleep 1000)
>   (str "never gets here " args))
>
> (defn generate-response [brand country resource]
>   (let [sla (or (env :sla-milliseconds) 100)]
> (respond-within-sla sla ok later fetcher brand country resource)))
>
> (defn generate-fail [brand country resource]
>   (let [sla (or (env :sla-milliseconds) 100)]
> (respond-within-sla sla ok later failer brand country resource)))
>
> From within the REPL it all works fine...
>
> (generate-response "A" "B" "C")
> => # clojure.core.async.impl.channels.ManyToManyChannel@4b7ae3f7>
> "fetching data with args A B C"
> "send HTTP 200 ... got data response-data"
> (generate-fail "A" "B" "C")
> => # clojure.core.async.impl.channels.ManyToManyChannel@4eb8b5a9>
> "send HTTP 202 ... request received, come back later"
>
> Here is the compojure route..
>
> (defroutes app
>(GET "/:brand/:country/*" [brand country *]
> (generate-response brand country *))
>
>(ANY "*" []
> (route/not-found "You must use a REST style to specify
> brand and country keys in the URL")))
>
> If I now start it up 'lein run' and try to exercise the functions from the
> web server...
>
> $ curl -I http://localhost:5000/A/B/D.jpg
> HTTP/1.1 500 Server Error
> Date: Fri, 26 Sep 2014 23:02:03 GMT
> Content-Length: 0
> Connection: close
> Server: Jetty(7.6.8.v20121106)
>
> And on the server I see this:
>
> $ lein run
> Compiling redirector.web
> 2014-09-27 01:01:48.426:INFO:oejs.Server:jetty-7.6.8.v20121106
> 2014-09-27 01:01:48.458:INFO:oejs.AbstractConnector:Started
> SelectChannelConnector@0.0.0.0:5000
> 2014-09-27 01:02:03.535:WARN:oejs.AbstractHttpConnection:/A/B/D.jpg
> java.lang.IllegalArgumentException: No implementation of method: :render
> of protocol: #'compojure.response/Renderable found for class:
> clojure.core.async.impl.channels.ManyToManyChannel
> at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:544)
> at compojure.response$fn__213$G__208__220.invoke(response.clj:9)
> at compojure.core$make_route$fn__332.invoke(core.clj:100)
> at compojure.core$if_route$fn__320.invoke(core.clj:46)
> at compojure.core$if_method$fn__313.invoke(core.clj:33)
> at compojure.core$routing$fn__338.invoke(core.clj:113)
> at clojure.core$some.invoke(core.clj:2515)
> at compojure.core$routing.doInvoke(core.clj:113)
> at clojure.lang.RestFn.applyTo(RestFn.java:139)
> at clojure.core$apply.invoke(core.clj:626)
> at compojure.core$routes$fn__342.invoke(core.clj:118)
> at clojure.lang.Var.invoke(Var.java:379)
> at
> ring.middleware.keyword_params$wrap_keyword_params$fn__534.invoke(keyword_params.clj:35)
> at
> ring

core.async | compojure ... odd error ... help!!

2014-09-26 Thread mond
My first core.async program ... all works outside of the web app but barfs 
once I put the functions inside a web container. I hope somebody in the 
group can point to my obvious mistake...

The idea is that the function 'respond-within-sla' will give back a result 
or a come back later message after N milliseconds. It is passed a number of 
ms, three functions and the arguments for the final function ... which is 
the one that should operate within the SLA.

(defn respond-within-sla [expected-result-milliseconds respond-ok 
respond-later data-fetcher & args]
  (let [data-channel (timeout expected-result-milliseconds)]
(go (if-let [data (! data-channel (apply data-fetcher args)

To keep the volume of code to parse to a minimum I have made a few toy 
functions that demonstrate the failure...

; test funcs

(defn ok [data]
  (prn (str "send HTTP 200 ... got data " data)))

(defn later []
  (prn (str "send HTTP 202 ... request received, come back later")))

(defn fetcher [arg1 arg2 arg3]
  (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
  "response-data")

(defn failer [& args]
  (Thread/sleep 1000)
  (str "never gets here " args))

; test funcs

(defn ok [data]
  (prn (str "send HTTP 200 ... got data " data)))

(defn later []
  (prn (str "send HTTP 202 ... request received, come back later")))

(defn fetcher [arg1 arg2 arg3]
  (prn (str "fetching data with args " arg1 " " arg2 " " arg3))
  "response-data")

(defn failer [& args]
  (Thread/sleep 1000)
  (str "never gets here " args))

(defn generate-response [brand country resource]
  (let [sla (or (env :sla-milliseconds) 100)]
(respond-within-sla sla ok later fetcher brand country resource)))

(defn generate-fail [brand country resource]
  (let [sla (or (env :sla-milliseconds) 100)]
(respond-within-sla sla ok later failer brand country resource)))

>From within the REPL it all works fine...

(generate-response "A" "B" "C")
=> #
"fetching data with args A B C"
"send HTTP 200 ... got data response-data"
(generate-fail "A" "B" "C")
=> #
"send HTTP 202 ... request received, come back later"

Here is the compojure route..

(defroutes app
   (GET "/:brand/:country/*" [brand country *]
(generate-response brand country *))

   (ANY "*" []
(route/not-found "You must use a REST style to specify 
brand and country keys in the URL")))

If I now start it up 'lein run' and try to exercise the functions from the 
web server...

$ curl -I http://localhost:5000/A/B/D.jpg
HTTP/1.1 500 Server Error
Date: Fri, 26 Sep 2014 23:02:03 GMT
Content-Length: 0
Connection: close
Server: Jetty(7.6.8.v20121106)

And on the server I see this:

$ lein run
Compiling redirector.web
2014-09-27 01:01:48.426:INFO:oejs.Server:jetty-7.6.8.v20121106
2014-09-27 01:01:48.458:INFO:oejs.AbstractConnector:Started 
SelectChannelConnector@0.0.0.0:5000
2014-09-27 01:02:03.535:WARN:oejs.AbstractHttpConnection:/A/B/D.jpg
java.lang.IllegalArgumentException: No implementation of method: :render of 
protocol: #'compojure.response/Renderable found for class: 
clojure.core.async.impl.channels.ManyToManyChannel
at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:544)
at compojure.response$fn__213$G__208__220.invoke(response.clj:9)
at compojure.core$make_route$fn__332.invoke(core.clj:100)
at compojure.core$if_route$fn__320.invoke(core.clj:46)
at compojure.core$if_method$fn__313.invoke(core.clj:33)
at compojure.core$routing$fn__338.invoke(core.clj:113)
at clojure.core$some.invoke(core.clj:2515)
at compojure.core$routing.doInvoke(core.clj:113)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invoke(core.clj:626)
at compojure.core$routes$fn__342.invoke(core.clj:118)
at clojure.lang.Var.invoke(Var.java:379)
at 
ring.middleware.keyword_params$wrap_keyword_params$fn__534.invoke(keyword_params.clj:35)
at 
ring.middleware.nested_params$wrap_nested_params$fn__576.invoke(nested_params.clj:84)
at ring.middleware.params$wrap_params$fn__507.invoke(params.clj:64)
at 
ring.middleware.multipart_params$wrap_multipart_params$fn__612.invoke(multipart_params.clj:118)
at ring.middleware.flash$wrap_flash$fn__1286.invoke(flash.clj:35)
at ring.middleware.session$wrap_session$fn__1273.invoke(session.clj:98)
at ring.adapter.jetty$proxy_handler$fn__1426.invoke(jetty.clj:18)
at 
ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown
 
Source)
at 
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:363)
at 
org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:483)
at 
org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:920)
at 
org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:982)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
"fetching data with args A B D.jpg"
at