Rails trying to connect to unconfgured MySQL on request - ruby-on-rails

Seeing a weird problem starting a Unicorn server - bundle exec ruby unicorn_rails.rb starts okay, but when I visit a URL, it shows:
Mysql2::Error (Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2))
So it seems unicorn isn't connecting to the remote server that's configured in database.yml (as it's trying to connect locally), despite other commands, e.g. bundle exec rails console, working fine. It seems to be ignoring that setting even though the environment is set right. This was working before, but something has broken it.
I put the full stack trace here:
https://gist.github.com/mahemoff/6029630
database.yml:
staging:
adapter: mysql2
database: slide_staging
host: 192.168.1.255
port: 3306
pool: 5
username: deploy
password: <%= ENV['DB_PASS'] || "notconfiguredyet" %>
timeout: 5000
reconnect: true

It might be linked to the unicorn configuration..
Especially if you preload the app.
Do you have these lines inside?
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
# the following is *required* for Rails + "preload_app true",
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end

I finally solved this. It turns out the Rails environment was being overridden, as I'd introduced a config snippet that included a bug, using Rails.env = 'test' instead of Rails.env=='test'. I figured it out after noticing my development mode was running in test environment even though ENV['RAILS_ENV'] was correctly set to development.

Related

Deploying to Heroku, Rails app

I am trying to deploy my rails app to heroku. The app is uploaded but does not run properly for some reason. When I type
heroku run rake db:migrate
I get an error saying
ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
I am using puma for the server and I will post some of the files that might cause the problem... Please ask for anything that might cause this error!
config/database.ymi
production:
adapter: postgresql
host: localhost
encoding: unicode
database: FastOrder_production
pool: 5
username: <%= ENV['FASTORDER_DATABASE_USER'] %>
password: <%= ENV['FASTORDER_DATABASE_PASSWORD'] %>
template: template0
url: <%= ENV["DATABASE_URL"] %>
pool: ENV['RAILS_MAX_THREADS']
config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
You should create your db first:
heroku run rake db:create
Also, check this Heroku doc about DB connections: https://devcenter.heroku.com/articles/concurrency-and-database-connections
use
production:
pool: <%= ENV["DB_POOL"] || ENV['RAILS_MAX_THREADS'] || 5 %>
Now you can set the connection pool size by setting a config variable on Heroku. For instance if you wanted to set it to 10 you could run:
$ heroku config:set DB_POOL=10
This doesn’t mean that each dyno will now have 10 open connections, but only that if a new connection is needed it will be created until a maximum of 10 have been used per Rails process.

ActiveRecord::StatementInvalid (RuntimeError: The connection cannot be reused in the forked process

Hi I am using CANCAN Gem for user roles and
database ->oracle
oracle adaptor - > oracle_enhanced_adaptor 1.4.1
ruby 1.9.3
rails 3.2.16
web server -> unicorn
when i refresh broser after some time ( 2 or 3 minutes) . It gives us ActiveRecord::StatementInvalid (RuntimeError: The connection cannot be reused in the forked process.:
Anyone help me
I found a answer from google community
dbconfig = ActiveRecord::Base.remove_connection
child_pid = fork do
# establish new db connection for forked child
ActiveRecord::Base.establish_connection(dbconfig)
# do stuff...
end
# re-establish db connection
ActiveRecord::Base.establish_connection(dbconfig)
# detach the process so we don't wait for it
Process.detach(child_pid)
in environment.rb file and it works like a charm
You need to add this to your unicorn.rb file
#config/unicorn.rb
after_fork do |server, worker|
defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
and you can run the server with the command unicorn -c config/unicorn.rb to use the config.

Rails Unicorn Web Server Won't Start on Heroku

I can't get my app to successfully start at Heroku. Here's the basics:
Ruby 1.9.3p392 (when I run Ruby -v in my dev terminal this is what is returned, however the Heroku logs seem to indicate Ruby 2.0.0)
Rails 3.2.13
Unicorn Web Server
Postgresql DB
I have deployed my app to Heroku but getting "An error occurred in the application and your page could not be served."
Here's the final entries in the Heroku log:
+00:00 app[web.1]: from /app/vendor/bundle/ruby/2.0.0/bin/unicorn:23:in `<main>'
+00:00 heroku[web.1]: Process exited with status 1
+00:00 heroku[web.1]: State changed from starting to crashed
When I try to run Heroku ps, I get:
=== web (1X): `bundle exec unicorn -p $PORT -c ./config/unicorn.rb`
web.1: crashed 2013/06/22 17:31:22 (~ 6m ago)
I think it's possible the problem is stemming from this line in my app/config/application.rb
ENV.update YAML.load(File.read(File.expand_path('../application.yml', __FILE__)))
This line is useful in dev to read my environment variables from my application.yml file. However, for security purposes I gitignore it from my repo and can see the Heroku logs complain that this file not being found. For production, I have set my environment variables at Heroku via:
heroku config:add SECRET_TOKEN=a_really_long_number
Here's my app/config/unicorn.rb
# config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
And here's my Procfile
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
Both my app/config/unicorn.rb and Procfile settings come from https://devcenter.heroku.com/articles/rails-unicorn
Based on some IRC guidance, I installed Figaro, but alas that did not resolve the issue.
If you want to see the full app, it's posted at: https://github.com/mxstrand/mxspro
If you have guidance on what might be wrong or how I might troubleshoot further I'd appreciate it. Thank you.
You're spot on with you analysis. I've just pulled your code, made some tweaks and now have it started on Heroku.
My only changes;
config/application.rb - moved lines 12 & 13 to config/environments/development.rb - if you're using application.yml for development environment variables then keep it that way. Other option is to make line 13 conditional to your development environment with if Rails.env.development? at the end.
config/environments/production.rb - line 33 missing preceeding # mark

Resque is not picking up Redis configuration settings

I am having unexpected and significant problems trying to get a Rails app, running under Unicorn, to connect to a password-protected Redis server.
Using bundle exec rails c production on the command line, I can issue commands through Resque.redis. However, it seems that my configuration is being lost when it's forked under Unicorn.
Using a non-password-protected Redis server Just Works. However, I intend to run workers on other servers than where the Redis server lives, so I need this to be password protected.
I have also had success in using a password protected (using the same technique) but using Passenger rather than Unicorn.
I have the following setup:
# config/resque.yml
development: localhost:6379
test: localhost:6379
production: redis://user:PASSWORD#oak.isc.org:6379
.
# config/initializers/redis.rb
rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
rails_env = ENV['RAILS_ENV'] || 'development'
$resque_config = YAML.load_file(rails_root + '/config/resque.yml')
uri = URI.parse($resque_config[rails_env])
Resque.redis = Redis.new(host: uri.host, port: uri.port, password: uri.password)
.
# unicorn.rb bootup file
preload_app true
before_fork do |server, worker|
Redis.current.quit
end
after_fork do |server, worker|
Redis.current.quit
end
.
Ok, for the sake of other people who might be googling this problem, I've solved this for myself at least
Basic problem is calling Redis.new other places in the code ,e.g. in your geocoder setup or unicorn config file.
just make sure that every time you call initialize Redis you pass in the appropriate values
e.g. something like
REDIS = Redis.connect(:url => ENV['REDISTOGO_URL'])
everywhere and you should never have
Redis.new
as it will default to localhost and the default port
UPDATED Totally different idea based on #lmarlow's comment to a resque issue.
I bet it breaks wherever you have Redis ~>3 (I mean the ruby client version, not the server version).
As of this writing, Resque needs Redis ~>2 but doesn't specify that in its gemspec. Therefore you have to help it out by adding this to your Gemfile:
gem 'redis', '~>2' # until a new version of resque comes out
gem 'resque'
Also, make sure that bundler is being used everywhere. Otherwise, if your system has a new version of the Redis gem, it will get used and Resque will fail like before.
Finally, a cosmetic note... you could simplify the config to:
# config/initializers/redis.rb
$resque_redis_url = uris_per_environment[rails_env] # note no URI.parse
Resque.redis = $resque_redis_url
and then
# unicorn.rb bootup file
after_fork do |server, worker|
Resque.redis = $resque_redis_url
end
This was helpful to me:
source: https://github.com/redis/redis-rb/blob/master/examples/unicorn/unicorn.rb
require "redis"
worker_processes 3
# If you set the connection to Redis *before* forking,
# you will cause forks to share a file descriptor.
#
# This causes a concurrency problem by which one fork
# can read or write to the socket while others are
# performing other operations.
#
# Most likely you'll be getting ProtocolError exceptions
# mentioning a wrong initial byte in the reply.
#
# Thus we need to connect to Redis after forking the
# worker processes.
after_fork do |server, worker|
Redis.current.quit
end
What worked for me was the unicorn config here: https://stackoverflow.com/a/14636024/18706
before_fork do |server, worker|
if defined?(Resque)
Resque.redis.quit
Rails.logger.info("Disconnected from Redis")
end
end
after_fork do |server, worker|
if defined?(Resque)
Resque.redis = REDIS_WORKER
Rails.logger.info("Connected to Redis")
end
end
I think the issue was with Resque-web. Its config file, they fixed it now. In version 0.0.11, they mention it in a comment as well : https://github.com/resque/resque-web/blob/master/config/initializers/resque_config.rb#L3
Earlier, their file looked like this : https://github.com/resque/resque-web/blob/v0.0.9/config/initializers/resque_config.rb
And, if due to any reasons, you cannot upgrade, then rather try to set the env variable RAILS_RESQUE_REDIS=<host>:<port> instead, as the Initializers are loading after the it tries connect redis(and fails).

Rails gem uses the development db instead of the testing one when executing "rake test"

I'm using a gem with my rails 3 project, "rails-settings-cached", and when I'm in development mode the gem can access the database without any problem.
However, when I run "rake test", a lot of tests fails because "rails-settings-cached" keeps using the development db instead of the testing one.
The other parts of my application works fine. What should I do to connect the gem to the right database?
development:
adapter: mysql2
encoding: utf8
reconnect: false
database: mmdb_development
pool: 5
username: ***
password: ***
socket: /var/run/mysqld/mysqld.sock
test:
adapter: mysql2
encoding: utf8
reconnect: false
database: mmdb_test
pool: 5
username: ***
password: ***
socket: /var/run/mysqld/mysqld.sock
The problem is that rails-settings-cached... well... caches the settings.
So, when you run your tests, it is actually using the old cached values from the "development" database.
A possible workaround can be running rake tmp:cache:clear before and after the tests.
It works, but to automate it you can put these methods inside test_helper.rb:
def setup
Rails.cache.clear
end
def teardown
Rails.cache.clear
end
The problem with the caching in rails-settings-cached is that the default cache in Rails 3.2.8 (and probably in Rails 3 on) is ActiveSupport::Cache::FileStore. This caches to a file that is in a shared location and so is shared between development, test, and production. This can cause all sorts of issues!
The Caching with Rails Guide claims that the default is ActiveSupport::Cache::MemoryStore, but it appears that the documentation is incorrect. I have submitted an issue against rails regarding the apparent documentation inaccuracy.
One solution is to switch test and development to using ActiveSupport::Cache::MemoryStore. If the default of 32 megabytes is enough, you can simply add the following line to both development.rb and test.rb in config/environments (inside the .configure do block, of course):
config.cache_store = :memory_store
Try explicitly set your rals env to test in test/test_helper.rb on the very top of the test_helper.rb file
ENV["RAILS_ENV"] = "test"

Resources