This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-20
Channels
- # admin-announcements (1)
- # announcements (1)
- # beginners (115)
- # calva (31)
- # cider (25)
- # clj-kondo (47)
- # cljdoc (23)
- # cljs-dev (5)
- # clojars (1)
- # clojure (60)
- # clojure-australia (1)
- # clojure-europe (23)
- # clojure-nl (3)
- # clojure-norway (2)
- # clojure-spec (3)
- # clojure-uk (18)
- # clojurescript (49)
- # community-development (1)
- # cursive (4)
- # datahike (2)
- # datascript (3)
- # datomic (36)
- # deps-new (2)
- # emacs (2)
- # events (9)
- # fulcro (6)
- # graphql (2)
- # gratitude (13)
- # holy-lambda (1)
- # introduce-yourself (10)
- # macro (2)
- # malli (5)
- # meander (9)
- # news-and-articles (5)
- # nextjournal (1)
- # off-topic (32)
- # pathom (17)
- # pedestal (13)
- # polylith (4)
- # protojure (4)
- # reagent (4)
- # sci (27)
- # shadow-cljs (2)
- # show-and-tell (2)
- # specter (3)
- # tools-deps (7)
- # xtdb (16)
Hello. I'm wondering if I'm misunderstanding something about pedestal's async handling in interceptors. The below code returns nil
, rather than a context map.
(def async-example
(interceptor
{:name :async-example
:enter (fn [context]
(go
(assoc context :async-result "some result")))}))
(chain/execute {} [async-example])
If I remove the go
block, I get the context map I expect. I wonder if it's something related to using execute
, though looking in pedestal's source, it seems execute
does perform the async handling if a channel is returned. https://github.com/pedestal/pedestal/blob/6b518f1403132e0474daa5edaf08b1de1df267b5/interceptor/src/io/pedestal/interceptor/chain.clj#L173
Is something not working as it should, or am I doing something incorrectly for this to work?I see this in the code: https://github.com/pedestal/pedestal/blob/6b518f1403132e0474daa5edaf08b1de1df267b5/interceptor/src/io/pedestal/interceptor/chain.clj#L102-L108
I think it has something to do with the repl and threading, though I'm not sure what exactly is happening.
If I change the body of execute
in the pedestal source to this:
([context]
(let [context (some-> context
begin
enter-all
terminate
leave-all
end)]
(prn "context" context)
(if-let [ex (::error context)]
(throw ex)
(do
(prn "returning:" context)
context))))
... then run my example, I get these logs and result:
"context" nil
"returning:" nil
"context" {:async-result "some result"}
"returning:" {:async-result "some result"}
nil
I need to go afk for now, but thanks for taking a look earlier @U08JKUHA9.
(chain/execute
{}
[(interceptor/interceptor
{:name :leave
:leave (fn [{:keys [response]
:as context}]
(prn [:response response])
context)})
(interceptor/interceptor
{:name :async-example
:enter (fn [context]
(async/go
(assoc context :response {:status 202})))})])
ret => nil
stdout => [:response {:status 202}]
From the http://pedestal.io/reference/interceptors#_interceptor_return_values and as demonstrated ^^: > Any interceptor downstream of an asynchronous interceptor will be executed in the `core.async` thread pool.
Understandable that it can't be synchronous, but wouldn't it make sense to return the result asynchronously in some way, like is done for the synchronous path?
I believe this behavior is expected. https://github.com/pedestal/pedestal/blob/6b518f1403132e0474daa5edaf08b1de1df267b5/interceptor/src/io/pedestal/interceptor/chain.clj#L110-L117 The docs call out that if a channel is received instead of a context it will return immediately with a nil.
Pedestal itself doesn't need the context when everything has finished executing. One of the last interceptors that will be executed is responsible for writing the response to the response output stream. Once that is done there is really nothing left to do. https://github.com/pedestal/pedestal/blob/6b518f1403132e0474daa5edaf08b1de1df267b5/service/src/io/pedestal/http/impl/servlet_interceptor.clj#L288 https://github.com/pedestal/pedestal/blob/6b518f1403132e0474daa5edaf08b1de1df267b5/service/src/io/pedestal/http/impl/servlet_interceptor.clj#L218
Thanks for the replies. @U0FL657GR Yes, that's the part of the docs I linked earlier in the thread. I suppose I just didn't fully understand the implications.