Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map function into enter, not into handler #14

Open
ikitommi opened this issue Nov 12, 2018 · 7 comments
Open

Map function into enter, not into handler #14

ikitommi opened this issue Nov 12, 2018 · 7 comments
Labels
enhancement New feature or request

Comments

@ikitommi
Copy link
Member

ikitommi commented Nov 12, 2018

If functions would be mapped into interceptor enter, instead of special handler case, it would be easier to write one-way chains:

Instead of:

(def inc-x-interceptor
  {:enter #(update % :request inc)})

(defn handler [request]
  (inc (:x request)))

(s/execute
  [inc-x-interceptor handler]
  40)
;=> 42

one could say:

(def inc-x-interceptor
  #(update % :request inc)))

(def handler
  (s/handler
    #(inc (:x request)))

(s/execute
  [inc-x-interceptor handler]
  40)
;=> 42

... inlined:

(s/execute
  [#(update % :request inc))
   p/promise
   (s/handler #(inc (:x request))]
  40)
;=> 42

https://github.com/metosin/sieppari/blob/develop/src/sieppari/interceptor.cljc#L30-L35

@ikitommi ikitommi added the enhancement New feature or request label Jan 1, 2019
@jarppe
Copy link
Member

jarppe commented Jan 19, 2019

Interceptor enter differs from handler in that interceptor enter is called and is expected to returns ctx, where as the handler is called with request and expected to return response.

If we change IntoInterceptor for functions to returns interceptor with the function as enter, then we need some other way to handle handler.

Perhaps what ever is last in queue is assumed to be handler?

Or, we could make it so that every element in queue is an interceptor, and we just provide utility to convert handler into interceptor and require that the caller does the conversion. Something like:

(s/execute [some-interceptor other-interceptor (handler->interceptor my-handler)])

What do you think?

@ikitommi
Copy link
Member Author

I think it's a good idea. And for ergonomics, s/handler would be better handler->interceptor. Also, like discussed in #15, the request-response could be a extra pattern on top of the core, which just runs contexts e2e.

@nilern
Copy link
Contributor

nilern commented Aug 27, 2019

It would be more symmetric and principled to have both enter-fn->interceptor and leave-fn->interceptor (or perhaps preprocessor and postprocessor) and having the handler be just a function. It would be more verbose but usually there aren't that many interceptors and the code is probably not modified as often as read.

Forcing the handler to be of interceptor type does not make much sense to me since it is a special case anyway because the context turns around and/or request is switched to response.

@jjttjj
Copy link

jjttjj commented Aug 29, 2019

One thing I've been wondering: does the interceptor pattern inherently imply that the context should contain a :request key, "make a request" then return with a :response key? Are these specific keys part of the pattern? Or, if not the specific keys, the idea that something (besides the context) goes through a chain of functions, then something else comes back, and both these things are separated from the surrounding context?

Or is it more general, does the interceptor pattern only imply a context goes through the interceptors one way, then back another, and :request/:response just happen to often be useful?

I think answering this question would help answer how a function should be interpreted as an interceptor. If there is no separate concept of request/response, then clearly a function shouldn't work be a request->response handler.

I have been thinking about using the interceptor pattern. I currently have the request just as subset of the context itself. There is no real "standard" defining my request so I didn't initially see a need to seperate it from surrounding context. The context is built up from the chain of interceptors, then at the end I pick out what I need to make the request and return back up the chain. For what it's worth, I'm beginning to think maybe this is bad and I more clearly define my "request" and put it into a :request key.

@nilern
Copy link
Contributor

nilern commented Aug 29, 2019

The handler could also be a function ctx -> ctx... but really the handler should work like in prior art (Pedestal, re-frame). The request-response convention is nice, but not the only reasonable one (e.g. re-frame has coeffects and effects instead), so a general purpose library like this should not force its use.

@ikitommi
Copy link
Member Author

There is a related issue of making the request & response optional: #18

@ikitommi
Copy link
Member Author

Also #15

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants