@ikitommi I really like that the queue and stack are first order parts of the context — what are your thoughts on that with regards to what should be part of the interceptor-spec?
@ikitommi, I’ll be out-of-pocket for the next couple of weeks but will give it thought. Thanks!
@martinklepsch I think the spec should be just data, with no implementing classes. Spec would be about the latter example: an interceptor map with optional :enter
, :leave
and :error
stages, all of ctx => ->ctx
, a context map, with :request
, :response
, :queue
(in enter stage), :stack
(implementation detail) and unwrapped exception as :error
(in error stage).
the ctx => ->ctx
would mean "from context to something that can be turned into a context", like a core.async
channel.
btw, Sieppari should work now on cljs too, thanks to @richiardiandrea (core.async & promesa)
We have it now in a couple of cljs lamdbas, however some colleagues are finding a bit tough to wrap their around the flow, top down and the bottom up. I am not sure we will keep it in cause in lamdba functions, especially in JS ones, you don't have many use cases where you want to wrap...or put it in another way, you can always write things pipeline style with the last step returning the response. I would really like to see a fully fledged interceptor app to understand if we are doing things correctly tbh
I would actually find it a bit sad if the concepts of request and response would be baked in since interceptors are a much more generic pattern
But just so I understand - is your primary idea to spec the map describing an interceptor or also how the chain gets executed?
Request and response could be anything?
it’s either request->request steps or context->context steps where the original payload is under request.
Right but mentioning/expecting those keys could be confusing in other situation s
maybe better name for those?
What’s a payload?
something that is the input to the execution?
(def i {:enter #(update :request inc)})
(execute [i i] 1) ; => 3
(defn execute [interceptors request] …)
But isn’t the input just the context? Like in pedestal interceptors just receive the context and nothing else
could be that too, but as the context needs to be a map, you need to store the input value(s) somewhere:
(execute [i i] {:request 1})
I have to do something else now but would love to chat more about this. Maybe it’s easiest if we just chat about this in a hangout some time?
sure!
You can send me an invite to <mailto:martinklepsch@googlemail.com|martinklepsch@googlemail.com> - I’m flexible most days so just send me something that works for you (Except tomorrow where I’m busy all day)
@richiardiandrea I think the normal promise/promesa chain is much better for simple things. The two-way Interceptors are good for base for reusable abstractions like in the web-servers: mounting an exception-handling interceptor to the root will ensure that all exceptions are always handled gracefully. Same for request/response formatting: :enter
decodes the body, :leave
encodes the response body and :error
returns the formatting errors in the negotiated format. Also, as interceptors are data, one can inspect & inventory them, re-order, add request/response specs etc.
that’s from Sieppari context inspector.
Yep I like that part very much and the only thing I don't see in our use case is the leave part - the handler is usually returns data validated in the enters and it is pretty "dumb". The callback on success does content-specific wrapping of it
But that's the thing, you can do things in many ways
And we as a team noticed that there is a mental overhead and we were always discussing if things should be in enter or leave or handler...while it technically can go in any of those
Not sure would be of any help, but one could create a one-way “ctx=>->ctx” function chain with the interceptors too. Manifold (and thus, Yada) does this.
“enterceptors” 😉
(enter [#(update % :request inc) p/promise #(update % :request * 2)] 1 respond raise)
; => eventually respond 4
… but I think promesa & manifold (JVM) are much better at one-way chaining.
… the enter
fn would be actually same as execute
if the 1-arity function would be mapped into a interceptor with :enter
, not into a handler of request -> response
. :thinking_face:
I think we are thinking exactly about enterceptors only 😺
And we had a couple of ideas around sugaring the error handling and associng in the context
But it deviates from interceptors a lot
https://github.com/pedestal/pedestal/blob/master/interceptor/src/io/pedestal/interceptor.clj#L32-L41
^:--- if that would be (interceptor {:enter t})
, then functions would be turned into enters and the spec would cover both 1-way & 2-way flows easily.
https://github.com/metosin/sieppari/blob/develop/src/sieppari/interceptor.cljc#L30-L35
Ah ok yes I have always wondered what was the usage of that part
It seems that a spec would definitely greatly help understanding the use case. We picked it because of the behaviour as data aspect and layer on top of async computation
So we will be experimenting with the one way flow and come up with some lib...we'll see. What sieppari definitely allowed us was too get to the "functional cori imperative shell" approach so hard to get with asyec stuff
@richiardiandrea Was just wondering with the sieppari + promesa stuff — would it be possible to also just use regular JS promises?
@martinklepsch yep I posted everything to support channels, promesa and native
@richiardiandrea ah right, just noticed — so the promesa extension is basically for people who already use promesa to enable a more streamlined integration?
Yeah
Sweet, thanks for the context and sorry for not spotting that in the PR 🙂
Also I hope you're doing well ☺️
Ahah yeah @martinklepsch doing well, are you coming to the Conj?
Unfortunately not! Submitted a talk but didn't get accepted and covering trip/accomodation etc. on my own is a bit too much after spending the summer on mostly unpaid work 😄
Have fun though, I'm very curious to see the talks, seems like there are quite a few announcements coming up
Yeah it looks like interesting for sure I hope to see you at the next one of in Europe at some point!