Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Rename post_routing pipeline config param? #266

Closed
RalfEggert opened this issue Jan 11, 2016 · 12 comments
Closed

Rename post_routing pipeline config param? #266

RalfEggert opened this issue Jan 11, 2016 · 12 comments

Comments

@RalfEggert
Copy link
Contributor

When I started working with Zend\Expressive I stumbled upon the post_routing parameter in the middleware pipeline configuration. Coming from Zend\Mvc I thought that these middleware will be executed directly after the routing. But through investigating it I noticed that these middleware are executed after the middleware for the current route. From that point of view the name sounds correct, but is leading to misunderstandings like here: #259

My suggestion would be to rename post_routing to post_dispatching to reduce future misinterpretations from new users.

@weierophinney
Copy link
Member

There's a number of confusions that I'm observing.

First "pipeline". Many are pointing out that a pipe is typically unidirectional. However, with middleware, we actually have two directions, as the middleware that first returns a response causes execution to return back out the path it traveled. This means that so-called "pre_routing" middleware might operate on the response returned by routed middleware, making it more like a "post" operation! As an example, consider the following middleware that adds a header to the returned response before returning it itself:

function ($request, $response, $next)
{
    $response = $next($request, $response);
    return $response->withHeader('X-Clacks-Overhead', 'GNU Terry Pratchett');
}

The above would be registered as pre_routing middleware if you want it to execute for any response returned!

The next issue is then, of course, with the naming of pre_routing and post_routing as configuration keys. The "pre" and "post" here refer to the order in which they are piped to the application. This is not necessarily the order in which operations are executed, however, for the reasons outlined above. Additionally, if you consider error middleware, these are often registered towards the end of the pipeline; if a middleware calls $next() with an error argument, this will result in skipping over all other middleware until the first error middleware is reached, and any further calls to $next() then start from that offset.

The term "routing" was chosen for these configuration variables for affinity with the already established "routing middleware". Since we don't make any reference to "dispatching" in the code (other than Zend\Stratigility\Dispatch, which is an internal class), choosing that terminology seemed like it would require a fair amount of explanation, and might confuse readers.

So, the questions I have are:

  • Do you have any better suggestions for the term "pipeline" that would disambiguate how the execution flow actually works?
  • Knowing that "pre" and "post" refer to when the middleware is registered to the pipeline in relation to the routing middleware, do the terms require more disambiguation, or would documentation to that effect solve the issue?

@RalfEggert
Copy link
Contributor Author

@weierophinney Thanks for the explanations.

The first term that came to my mind was "queue". If people queue in a bank they normally get "processed" consecutively. But people can swap their positions in the queue and some times some one is in such a hurry that he pushes to the front.

For the "pre" and "post" terms I have no better suggestion. But I think it doesn't matter how these terms are called. A proper documentation will be essential, I think

@weierophinney
Copy link
Member

@RalfEggert The problem with queue as a term here is that typically once a queue item is processed, it's removed; with Stratigility, and thus Expressive, the response is returned back through every item; processing is not handed off to the $next(), but, rather, we get the response from that, potentially do something with it, and return it.

I'm not sure if there's a good, more specific term, unfortunately, which makes me think that both terms (pipeline, pre/post-routing) simply need more explaining in the manual. Making a todo item for myself.

@RalfEggert
Copy link
Contributor Author

👍

@nesl247
Copy link

nesl247 commented Jan 11, 2016

Why not use Stack instead of Pipeline? This at least removes the thought of it being linear in my opinion. Whatever it ends up as, the documentation needs a lot of work.

I also feel like the implementation seems kinda weird to me now that I know it moves back through the stack. What's the benefit to this over a simple pipeline?

@weierophinney
Copy link
Member

@nesl247 Stack has the same issues as Queue; items are not processed and then discarded, but, rather, the response is returned back through the execution path.

With regards to this:

I also feel like the implementation seems kinda weird to me now that I know it moves back through the stack. What's the benefit to this over a simple pipeline?

I suggest you do some reading on middleware, and how it's used across the various languages. The approach used in Stratigility and Expressive mimics that in Sencha Connect, and is a pattern used in Rack (Ruby), WSGI (Python), and most major middleware implementations in other languages. The main difference between Connect and Rack is that the "next" middleware (or, rather, the function for calling it) is passed on invocation, rather than as a property to the middleware. Regardless, the execution path is the same: each layer calls the next, and the response travels back out through the layers it traversed.

The benefit is that you can layer your applications, and implement functionality such as caching without requiring multiple "hooks" or an event system.

@nesl247
Copy link

nesl247 commented Jan 11, 2016

Thanks for the explanation. Was talking to a few people and we were curious about it. Guess there's no better name, so I'm looking forward to the improved documentation in the future.

@Isinlor
Copy link

Isinlor commented Jan 12, 2016

I would suggest renaming "pre_routing" and "post_routing" to "outer_routing" and "inner_routing" respectively as registering them in a pipeline defines a position and not a time of execution. It also fits well visually to the metaphor of an onion. Also if to follow that logic wouldn't the term "onion" be better suited than "pipeline" to the concept we operate on? The only problem with "onion" is that it is not well established computer science terminology ;).

@danizord
Copy link
Contributor

If we separate routing from dispatching (#259) then I'd suggest these keys:

  • pre_routing
  • Routing happens here (add RouteResult as $request attribute)
  • post_routing
  • pre_dispatching
  • Dispatching happens here (fetch RouteResult from $request attribute and call routed middleware)
  • post_dispatching

Yeah, post_routing and pre_dispatching would do the same, but I'd prefer to keep these 2 for consistency.

@weierophinney
Copy link
Member

@RalfEggert and @danizord — please see #270 for an approach to this. In discussion with @ezimuel, we decided that we could have middleware_pipeline be exactly that: the pipeline of all middleware. This allows removing the pre/post verbiage entirely.

I'm still working on solutions for how to handle config merging (to ensure order is preserved), but feel it's a solvable problem. Please review!

@RalfEggert
Copy link
Contributor Author

@weierophinney

That PR will solve my problems within this issue. So it could be closed. I will comment in #270

@weierophinney
Copy link
Member

Fixed with #270.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants