Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@gmethvin
Copy link
Member

Backport of #8166

@gmethvin
Copy link
Member Author

@richdougherty You might want to review this also. I had to use a different signature on Server.getHandlerFor so I think we might want to forward-port and deprecate the method on master.

@gmethvin gmethvin force-pushed the try-app-2.6.x branch 2 times, most recently from 5798578 to f6e6b6c Compare January 18, 2018 00:20
@marcospereira marcospereira changed the title Avoid multiple calls to ApplicationProvider#get for a single request [2.6.x]: Avoid multiple calls to ApplicationProvider#get for a single request Jan 18, 2018
val decodedRequest = HttpRequestDecoder.decodeRequest(request)
val requestId = requestIDs.incrementAndGet()
val (convertedRequestHeader, requestBodySource) = modelConversion.convertRequest(
val tryApp = applicationProvider.get
Copy link
Member

@richdougherty richdougherty Jan 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, at this point you could take the logic in reloadValue(tryApp: Try[Application]): ReloadCacheValue method and change it to return a LoadedApplication, then pass that LoadedApplication around. e.g.

case class LoadedApplication(val tryApp: Try[Application], resultUtils: ServerResultUtils, modelConversion: AkkaModelConversion)

Then you could pass around the LoadedApplication object instead of a Try[Application]. You could also remove the reloading/caching code, which would be nice.

If you want to keep Play 2.6 changes minimal then this is an idea to consider for the master branch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm not sure about making major changes in 2.6, but I'm still not happy with adding API like I'm doing now. I think anything we do will require some change to the API.

The main difference is that in 2.6 we still need handleWebCommand, so we need to pass around something that has that functionality. That's why I added a method that took ApplicationProvider. I guess LoadedApplication could have handleWebCommand as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'd say put whatever things you want into it. I'd try to keep it as private/opaque as possible so we minimise the API that is exposed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I might take a more conservative approach in 2.6 and avoid making any public API changes. Then I'll implement your ideas on 2.7. It's going to be kind of a mess to do it both places.

Copy link
Member

@richdougherty richdougherty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few suggested changes, but looks good. 👍

private def getHandler(
requestHeader: RequestHeader, tryApp: Try[Application]
): (RequestHeader, Handler, Try[Application]) = {
Server.getHandlerFor(requestHeader, new ApplicationProvider {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about making a new, named, local class called FixedApplicationProvider or LoadedApplicationProvider? Might make reading the code and debugging a bit clearer.

def clientError(statusCode: Int, message: String) = {
val unparsedTarget = modelConversion.createUnparsedRequestTarget(request)
val requestHeader = modelConversion.createRequestHeader(channel, request, unparsedTarget)
val unparsedTarget = modelConversion(tryApp).createUnparsedRequestTarget(request)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you did go with the idea of having a LoadedApplication object then this code would change to something like:

val unparsedTarget = loadedApp.modelConversion.createUnparsedRequestTarget(request)

which looks a bit nicer. :)

override def handleWebCommand(requestHeader: RequestHeader): Option[Result] =
server.applicationProvider.handleWebCommand(requestHeader)
override def get: Try[Application] = tryApp
}) match {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, maybe introduce a name class for this. Since it's shared between the Netty and Akka HTTP servers, it could be private[play] in the play.core.server package.

* - If an exception is thrown.
*/
def getHandlerFor(request: RequestHeader): Either[Future[Result], (RequestHeader, Handler, Application)] = {
private[server] def getHandlerFor(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note I made this private[server]

@gmethvin gmethvin merged commit 73c2e04 into playframework:2.6.x Jan 24, 2018
@gmethvin gmethvin deleted the try-app-2.6.x branch January 24, 2018 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants