spring icon indicating copy to clipboard operation
spring copied to clipboard

Environment variables changed by rails cannot be reloaded

Open mildred opened this issue 4 years ago • 3 comments

The following piece of code handle environment variable reloads in Spring

https://github.com/rails/spring/blob/770b2b15b2ecb04fc0c3bda106a89d4a111a3a6c/lib/spring/application.rb#L163-L167

What it does is:

  • iterate over environment variables from when spring was started and remove those that rails did not change
  • iterate over client environment variables and if those are not present in the environment already, replace them

My problem is that I have a Rails application where there is an environment variable that triggers if the app is in master mode or slave mode. I use ENV! to manage environment variable, and if a variable is not set, ENV! sets a default value. The following sequence of events cause an issue:

  • spring server starts without the MASTER environment variable
  • app sets MASTER=false which is its default value
  • some time later...
  • I start the app again with MASTER=true on the command-line
  • Spring server receives a client request with MASTER=true
  • the process above is followed:
    • it considers MASTER to be unset when the spring server started but it has now MASTER=false. It received a client request with MASTER=true
    • it does not removes MASTER from the environment because it sees the variable changed (fron no value to false)
    • it does not replace MASTER=false with MASTER=true because it already has a value.
  • the app is started in slave mode despite having specified MASTER=true on the command-line.

I don't know the rationale behind this code, but in some cases it is completely wrong.

I believe this might be a reason behing the https://github.com/rails/spring/issues/420 issue

mildred avatar Sep 28 '21 14:09 mildred

@mildred Can I ask a question? Do you think this would cause this problem I am facing since upgrading Spring from 2.1.1. I have the following command:

bin/rails db:drop RAILS_ENV=test DATABASE_URL=test_lib

Since upgrading Spring, the DATABASE_URL env variable is being ignored. Just wondering if I need to report a new issue or is this the same issue.

jasonperrone avatar Dec 14 '21 15:12 jasonperrone

I'm having a similar issue with MYSQL_SOCKET being ignored, even though I can see it is set after Spring forks.

Running via Spring preloader in process 41869
ENV['MYSQL_SOCKET']: "/tmp/mysql.sock"

An error occurred while loading ./spec/jobs/my_job_spec.rb.
Failure/Error: ActiveRecord::Migration.maintain_test_schema!

ActiveRecord::ConnectionNotEstablished:
  Can't connect to local MySQL server through socket '' (2)
# ./spec/support/config/migrations.rb:3:in `<top (required)>'
# ./spec/rails_helper.rb:18:in `<top (required)>'
# ./spec/jobs/my_job_spec.rb:1:in `<top (required)>'
# -e:1:in `<main>'
# ------------------
# --- Caused by: ---
# Mysql2::Error::ConnectionError:
#   Can't connect to local MySQL server through socket '' (2)

where the file spec/support/config/migrations.rb looks like:

puts "ENV['MYSQL_SOCKET']: #{ENV['MYSQL_SOCKET'].inspect}"
# Ensure that all migrations have been run before running specs
ActiveRecord::Migration.maintain_test_schema!

I'm not sure how this is possible. The ENV variables are set and managed by direnv in an .envrc file. I'm on Rails 7.0.7.2 and spring 4.1.1

pboling avatar Aug 31 '23 19:08 pboling

For me it was a case of two different spring processes running. One in the foreground in my terminal, which worked, and responded to commands also sent from the terminal, and the other was running hidden in RubyMine, and it had not been restarted when I was manually restarting the one in my Terminal. See: https://www.jetbrains.com/help/ruby/spring.html#stop_spring

pboling avatar Aug 31 '23 19:08 pboling