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

Don't call builder on every request. #1201

Merged
merged 1 commit into from
Nov 12, 2015

Conversation

marshall-lee
Copy link
Member

Hello!

This is an attempt to fix a most wrong thing in Grape: middleware stack is initializing on every request and even more Grape dup them when they're called.

I don't know should it be merged or not. It might break someone's code even when specs are green.

@marshall-lee
Copy link
Member Author

The most scary thing here is that if I put build_app call to initialize there is exactly one failing spec: rspec spec/grape/api_spec.rb:2431 that was caught by accident, I think.

I need someone to carefully review this change.

@dblock
Copy link
Member

dblock commented Nov 12, 2015

I actually think this is absolutely right, it's amongst the oldest pieces of code that nobody dared touch. It also used to be much more involved when we didn't have all those stackable settings. I read the code and ran your branch against my large API test suite and everything but grape-newrelic worked, too.

I'd like to merge this, as "in specs we trust". I'll debug that one unless someone beats me to it.

It would be also great to get some benchmarks wrt what this change means to performance. Then I think you should send an email to the mailing list asking people to try HEAD, maybe someone will be brave enough to even try it in production :)

@dm1try
Copy link
Member

dm1try commented Nov 12, 2015

Such a nice PR,

everything but grape-newrelic worked

it overrides the original behaviour

Anyway, the changes LGTM!

dblock added a commit that referenced this pull request Nov 12, 2015
@dblock dblock merged commit a9a29a4 into ruby-grape:master Nov 12, 2015
@dblock
Copy link
Member

dblock commented Nov 12, 2015

Right on @dm1try. I merged this and opened xinminlabs/newrelic-grape#31, lets come up with a better, documented, interface to register middleware other than a monkey patch?

@dm1try
Copy link
Member

dm1try commented Nov 12, 2015

@dblock I agree.

@dblock dblock mentioned this pull request Nov 12, 2015
marshall-lee added a commit to marshall-lee/grape that referenced this pull request Nov 15, 2015
This PR follows the same logic as ruby-grape#1201.
@@ -188,6 +188,7 @@ def compile_path(prepared_path, anchor = true, requirements = {})
end

def call(env)
build_app
Copy link
Contributor

Choose a reason for hiding this comment

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

is it threadsafe to do @app lazy initialization here?

Copy link
Member

Choose a reason for hiding this comment

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

theoretically #build_stack can be called multiple times but I don't see any side effect here( see the implementation of #build_stack); just extra an extra calculation, if many threads will try to set @app.

Anyway if we create the interface which allows to extend an endpoint middleware stack(see #1202) and we guarantee that the build_stack only executed once, this part should be synchronized.

UPDATED

Copy link
Member

Choose a reason for hiding this comment

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

@etehtsea , I updated the comment sorry :)

Copy link
Member Author

Choose a reason for hiding this comment

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

@dm1try @etehtsea personally i didn't want lazy initialization but when i put it in initialize there're failing test :(

marshall-lee added a commit to marshall-lee/grape that referenced this pull request Nov 18, 2015
This PR follows the same logic as ruby-grape#1201.
marshall-lee added a commit to marshall-lee/grape that referenced this pull request Nov 19, 2015
Now I'm working on reducing calls to `extend` in `Grape` because they
invalidate Ruby's method cache slowing everything down. I applied a
*clever* trick with subclassing `Endpoint` and including helpers into
this subclass.

It also forced me to fix a thread safety issue reported by @etehtsea
here: ruby-grape#1201 (comment)
because calling `include` twice would be really inconsistent.

Also I'm sorry, 06930da does not actually fix anything, I overlooked it :)
marshall-lee added a commit to marshall-lee/grape that referenced this pull request Nov 19, 2015
Now I'm working on reducing calls to `extend` in `Grape` because they
invalidate Ruby's method cache slowing everything down. I applied a
*clever* trick with subclassing `Endpoint` and including helpers into
this subclass.

It also forced me to fix a thread safety issue reported by @etehtsea
here: ruby-grape#1201 (comment)
because calling `include` twice would be really inconsistent.

Also I'm sorry, 06930da does not actually fix anything, I overlooked it :)
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.

4 participants