This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-07-24
Channels
- # aleph (3)
- # beginners (17)
- # boot (8)
- # cider (61)
- # cljdoc (13)
- # cljs-dev (2)
- # clojure (66)
- # clojure-boston (1)
- # clojure-italy (4)
- # clojure-nl (7)
- # clojure-russia (7)
- # clojure-spec (19)
- # clojure-uk (80)
- # clojurescript (73)
- # core-async (4)
- # cursive (6)
- # data-science (1)
- # datomic (33)
- # docs (13)
- # emacs (17)
- # figwheel-main (28)
- # fulcro (12)
- # graphql (1)
- # jobs (3)
- # leiningen (4)
- # luminus (1)
- # off-topic (1)
- # parinfer (1)
- # pedestal (46)
- # protorepl (3)
- # re-frame (30)
- # reagent (47)
- # reitit (10)
- # ring (1)
- # shadow-cljs (94)
- # spacemacs (12)
- # specter (16)
- # tools-deps (6)
- # uncomplicate (1)
- # vim (9)
I have an async interceptor that returns a channel. For example:
(def my-async-interceptor
{:enter
(fn [context]
(println "start processing")
(async/go
(println "inside go block")
;; imitate some time consuming process
(async/<! (async/timeout 10000))
(assoc context :response {:status 200
:body "ok"
:headers {}})))})
If I get a bunch of these request piled up (the go block takes some time to return), then the println
inside the go
no longer prints "inside go block"
but "start processing"
is still printed. Any idea why this would happen?@kenny the backing threadpool for go
is small. I suggest using thread
with io-bound operations. Keep in mind that once you go async, the remaining interceptors are processed on a go
thread once your async interceptor returns.
@ddeaguiar Do you recommend for handlers that could have lots of longish (~10s) requests pending to simply be "synchronous"? i.e. no go
block?
@kenny no, I’d move those off the servlet thread. I typically perform any heavy-lifting/integration in interceptors and limit the final handler to response handling
Not sure I totally understand what you mean. In my case my handler sends a message to an external service that processes the request. The handler then takes the response from the external service and constructs a HTTP response. All of that is happening in the final handler in the interceptor chain.
so you can move the integration piece to an interceptor and leave the response processing to the handler
if your handler returns a channel then that channel is expected to return a response body
if an interceptor returns a channel, then that channel is expected to return a context map
The way it is written now is it waits for a response from the external service for up to 10s, if no response is returned when 10s is hit then an error response is returned.
Depending on what type of system you are building and the traffic you expect, you can end up exhausting your thread pool
if, for example, the system you are integrating with goes down for a long period of time
with a circuit breaker you can detect errors and trip the breaker causing additional requests to fail fast
Hystrix is commonly used here https://github.com/Netflix/Hystrix/wiki
but there’s a bit of ceremony involved so you’d use something like this if you really need it
go blocks are dispatched over an internal thread pool, which
defaults to 8 threads. The size of this pool can be modified using
the Java system property `clojure.core.async.pool-size`.