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 override WEB_CONCURRENCY if set #926

Closed
wants to merge 1 commit into from

Conversation

dirkkelly
Copy link

We would like to take advantage of the Puma Memory Reduction available through single mode.

However the Heroku/NodeJS buildpack currently overrides WEB_CONCURRENCY when determining the best configuration based on system memorry.

This pull request updates the script to keep the existing default if it is set, I'm not certain this is the best approach but thought this is a good way to start the conversation.

@dzuelke
Copy link
Contributor

dzuelke commented Jul 6, 2021

calculate_concurrency already does this!

The real problem you're encountering, @dirkkelly, is one of buildpack order - if your app is a Ruby app, then you need to set heroku/nodejs as the first, and heroku/ruby as the second buildpack.

Any tasks you'd like to run using node can then be triggered during the Ruby build phase using e.g. https://devcenter.heroku.com/articles/rails-asset-pipeline

@dzuelke
Copy link
Contributor

dzuelke commented Jul 6, 2021

Also see #931

@dirkkelly
Copy link
Author

Hi @dzuelke, thanks for getting back to me and letting me know about the recent updates to the script.

To confirm, the buildpacks are ordered as nodejs then ruby.


When using the official buildpack though the environment variable is overridden within the environment.

heroku buildpacks -a example-app
=== example-app Buildpack URLs
1. heroku/nodejs
2. heroku/ruby
heroku config -a example-app | grep WEB_CONCURRENCY
WEB_CONCURRENCY:                         0
heroku run printenv -a example-app |  grep WEB_CONCURRENCY
Running printenv on example-app... up, run.3716 (Standard-1X)
WEB_CONCURRENCY=1

When I swap out the official buildpack with the official github repository I see the same behavior

heroku buildpacks -a example-app
=== example-app Buildpack URLs
1. https://github.com/heroku/heroku-buildpack-nodejs
2. heroku/ruby
heroku config -a example-app | grep WEB_CONCURRENCY
WEB_CONCURRENCY:                         0
heroku run printenv -a example-app |  grep WEB_CONCURRENCY
Running printenv on example-app... up, run.4582 (Standard-1X)
WEB_CONCURRENCY=1

However when I use this branch which conditionally sets the WEB_CONCURRENCY environment variable I see the expected result.

I understand this branch is now out-of-date though, but I hope it clarifies the point that our usecase is we need WEB_CONCURRENCY not to be overridden during the node build process, and because we set it to 0 for puma purposes it will be by this script.

heroku buildpacks -a example-app
=== example-app Buildpack URLs
1. https://github.com/interexchange/heroku-buildpack-nodejs.git#fix-web-concurrency
2. heroku/ruby
heroku config -a example-app | grep WEB_CONCURRENCY
WEB_CONCURRENCY:                         0
heroku run printenv -a example-app |  grep WEB_CONCURRENCY
Running printenv on example-app... up, run.3082 (Standard-1X)
WEB_CONCURRENCY=0

It looks like the #931 branch still explicitly sets the WEB_CONCURRENCY environment regardless of whether or not it has been https://github.com/heroku/heroku-buildpack-nodejs/pull/931/files#diff-40752ecdd094936e1c62829bfc729666f233365d5defd026d57aedc8f28fe40dR67

It seems like this is expected behavior as validate_concurrency checks that this concurrency value is less than 1, and if so sets it to be 1.

Is there any recommended practice for bypassing this script in the build process to avoid the environment variable being overridden?

Thanks for all your help with this!

@dzuelke
Copy link
Contributor

dzuelke commented Aug 20, 2021

Okay, I see now. This is actually an issue in the Ruby buildpack, which doesn't use the quasi-standard WEB_CONCURRENCY.sh file that each buildpack writes to. Since all buildpacks use the same file name, the last one to run wins.

Could you try the branch from heroku/heroku-buildpack-ruby#1188 please?

@dzuelke
Copy link
Contributor

dzuelke commented Aug 20, 2021

(right now, that branch in the PR will only help you if you have SENSIBLE_DEFAULTS=1; will address the unset case later)

dzuelke added a commit to heroku/heroku-buildpack-ruby that referenced this pull request Aug 23, 2021
The Node.js, PHP and Python buildpacks write their WEB_CONCURRENCY defaults logic to this file name.

This ensures that the last buildpack to run defines the defaults an app will use.

If each buildpack were to use its own filename, then whatever file is evaluated first by the Shell on startup would set an initial value, and following files would see the variable already set and likely skip their calculation, or apply their own lower/upper limit enforcement, as it cannot know whether the variable was set by a user, or by some other buildpack's startup logic

(the Shell sources files using a glob pattern from .profile.d/ on startup, which on GNU Bash is in alnum order, see https://www.gnu.org/software/bash/manual/bash.html#Filename-Expansion)

This change uses the same filename as other buildpacks, ensuring that e.g. if heroku/nodejs is used as the first and heroku/ruby as the second buildpack, the defaults set by this buildpack will apply.

Right now, in this constellation, .profile.d/ruby.sh runs first, and sets a default value, then .profile.d/WEB_CONCURRENCY.sh runs later, and does nothing, as the defaults fit within Node.js's current logic - but if a user sets WEB_CONCURRENCY=0 manually, then Node.js' logic kicks in, and re-sets the value to 1, as Node.js doesn't allow a value of 0.

Ruby's Puma however allows "single mode", and for that, the value needs to be 0: puma/puma#2393

Refs heroku/heroku-buildpack-nodejs#926
@dzuelke
Copy link
Contributor

dzuelke commented Aug 23, 2021

@dirkkelly heroku/heroku-buildpack-ruby#1188 is now fully implemented if you want to test that branch and help verify it fixes your case

@dirkkelly
Copy link
Author

Thank you so much for all your help @dzuelke! 🎉

I can confirm that your ruby buildpack branch has resolved the issue on my test environment.

I will close this PR and subscribe to heroku/heroku-buildpack-ruby#1188

@dirkkelly dirkkelly closed this Aug 24, 2021
schneems added a commit to heroku/heroku-buildpack-ruby that referenced this pull request Aug 24, 2021
* use WEB_CONCURRENCY.sh for WEB_CONCURRENCY default

The Node.js, PHP and Python buildpacks write their WEB_CONCURRENCY defaults logic to this file name.

This ensures that the last buildpack to run defines the defaults an app will use.

If each buildpack were to use its own filename, then whatever file is evaluated first by the Shell on startup would set an initial value, and following files would see the variable already set and likely skip their calculation, or apply their own lower/upper limit enforcement, as it cannot know whether the variable was set by a user, or by some other buildpack's startup logic

(the Shell sources files using a glob pattern from .profile.d/ on startup, which on GNU Bash is in alnum order, see https://www.gnu.org/software/bash/manual/bash.html#Filename-Expansion)

This change uses the same filename as other buildpacks, ensuring that e.g. if heroku/nodejs is used as the first and heroku/ruby as the second buildpack, the defaults set by this buildpack will apply.

Right now, in this constellation, .profile.d/ruby.sh runs first, and sets a default value, then .profile.d/WEB_CONCURRENCY.sh runs later, and does nothing, as the defaults fit within Node.js's current logic - but if a user sets WEB_CONCURRENCY=0 manually, then Node.js' logic kicks in, and re-sets the value to 1, as Node.js doesn't allow a value of 0.

Ruby's Puma however allows "single mode", and for that, the value needs to be 0: puma/puma#2393

Refs heroku/heroku-buildpack-nodejs#926

* it "has a newline between it blocks" do

* named args for add_to_profiled and move ternary

* changelog and... changelogs

Co-authored-by: Richard Schneeman <[email protected]>
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