Skip to content

Conversation

caius
Copy link
Contributor

@caius caius commented Oct 29, 2024

Description

Sometimes (usually for overriding values temporarily) shells can unset environment variables by setting them to a blank value, ruby interprets this as an empty string. Doing so with Puma's default environment parsing would previously blow up because Integer("") is not valid.

$ WEB_CONCURRENCY= bundle exec puma
bundler: failed to load command: puma (/Users/caius/.asdf/installs/ruby/3.3.5/lib/ruby/gems/3.3.0/bin/puma)
<internal:kernel>:307:in `Integer': invalid value for Integer(): "" (ArgumentError)
  • Add tests for WEB_CONCURRENCY, PUMA_MIN_THREADS and PUMA_MAX_THREADS being ""
  • Check in code we're not trying to parse empty strings before parsing values
  • Update existing test for PUMA_MAX_THREADS to match PUMA_MIN_THREADS test

Your checklist for this pull request

  • I have reviewed the guidelines for contributing to this repository.
  • I have added (or updated) appropriate tests if this PR fixes a bug or adds a feature.
  • My pull request is 100 lines added/removed or less so that it can be easily reviewed.
  • If this PR doesn't need tests (docs change), I added [ci skip] to the title of the PR.
  • If this closes any issues, I have added "Closes #issue" to the PR description or my commit messages.
  • I have updated the documentation accordingly.
  • All new and existing tests passed, including Rubocop.

@dentarg
Copy link
Member

dentarg commented Oct 29, 2024

I see how this is useful but I'm a tiny bit worried that this may hide the configuration errors from the user. Maybe this should be part of Puma v7.

@dentarg dentarg added the v7 Breaking changes for v7 label Oct 29, 2024
@caius
Copy link
Contributor Author

caius commented Oct 29, 2024

I think I'd expect this to work like --workers "" which doesn't blow up, but parses it to 0 internally. Same outcome as this PR specifying WEB_CONCURRENCY="" (or WEB_CONCURRENCY= for shorthand.)

It'll fall back to 0 if nothing is specified in the concurrency, so I don't think this will hide mis-configuration issues. If you're setting a variable to nothing and then nothing is being configured it's correct.

Not from puma's internals, but I found a bug in a config/puma.rb recently where setting WEB_CONCURRENCY=2 caused the app to not boot. Specifying nothing caused it to successfully boot with two workers. (We were reading the environment variable but not casting to Integer before checking if greater than 1. ArgumentError.)

I wonder if I might be slightly special in how I use the shell, but having run into this with both a crappy config file of my own making, and natively with Puma 6 and the internals exploding I figured I'd raise the PR.

The case where it's overridden in one command locally for testing purposes was where our app specifies WEB_CONCURRENCY=2 in our local .env file, so we run with two workers in development. Whilst testing something else I wanted to run with no workers so it was all in same process. The shorthand in shell for unsetting an environment variable is to just set it to nothing (ie, "") rather than unset FOO; command; export FOO=$original for completeness. Except kaboom in this case.

Also (tongue in cheek 😛) if you squint in the right way, this is a regression in behaviour. Puma 4 runs fine, then Puma 5 blows up.

$ WEB_CONCURRENCY= BUNDLE_GEMFILE=Gemfile.puma4 bundle exec puma
Puma starting in single mode...
* Version 4.3.12 (ruby 3.3.5-p100), codename: Mysterious Traveller
* Min threads: 0, max threads: 16
* Environment: development
ERROR: No application configured, nothing to run

$ WEB_CONCURRENCY= BUNDLE_GEMFILE=Gemfile.puma6 bundle exec puma
bundler: failed to load command: puma (/Users/caius/.asdf/installs/ruby/3.3.5/lib/ruby/gems/3.3.0/bin/puma)
<internal:kernel>:307:in `Integer': invalid value for Integer(): "" (ArgumentError)
	from /Users/caius/.asdf/installs/ruby/3.3.5/lib/ruby/gems/3.3.0/gems/puma-6.4.3/lib/puma/configuration.rb:233:in `puma_options_from_env'

Mostly I think it should behave the same as --worker "" and also not blow up when overriding an existing value in shell - fall back to good defaults at that point.

@caius caius force-pushed the cd/puma-env-blank branch from 76958ce to 620291a Compare October 29, 2024 18:31
@caius
Copy link
Contributor Author

caius commented Oct 29, 2024

Fixed the jruby tests and corrected the first commit to say "max", not "min".

@caius caius force-pushed the cd/puma-env-blank branch from 620291a to ff24f09 Compare October 30, 2024 10:17
@dentarg
Copy link
Member

dentarg commented Oct 30, 2024

I think I'd expect this to work like --workers "" which doesn't blow up, but parses it to 0 internally

I did not know that – then I agree, this sounds more like a bug fix

@dentarg dentarg added bug waiting-for-review Waiting on review from anyone and removed v7 Breaking changes for v7 labels Oct 30, 2024
This mirrors the test above for min threads, creating a configuration instance wasn't checking anything here previously
Sometimes (usually for overriding values temporarily) shells can unset environment variables by setting them to a blank value, ruby interprets this as an empty string. Doing so with Puma's default environment parsing would previously blow up because `Integer("")` is not valid.

    $ WEB_CONCURRENCY= bundle exec puma
    bundler: failed to load command: puma (/Users/caius/.asdf/installs/ruby/3.3.5/lib/ruby/gems/3.3.0/bin/puma)
    <internal:kernel>:307:in `Integer': invalid value for Integer(): "" (ArgumentError)

Add tests for `WEB_CONCURRENCY`, `PUMA_MIN_THREADS` and `PUMA_MAX_THREADS` and then check we're not trying to parse a blank value before doing so.
@MSP-Greg
Copy link
Member

This conflicted with #3550. Rebased and fixed the merge issues.

@dentarg dentarg removed the waiting-for-review Waiting on review from anyone label Nov 20, 2024
@dentarg dentarg merged commit b444c10 into puma:master Nov 20, 2024
78 checks passed
@caius caius deleted the cd/puma-env-blank branch November 20, 2024 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants