0

I am splitting my redis and resque workers out to a new machine. Previously they all ran on one machine - successfully.

I us cap for deploying and after a successful deploy I get this in my rails log when I try to queue up a resque job:

==> shared/log/production.log <==
I, [2016-05-28T05:43:03.924222 #5769]  INFO -- : Started GET "/photos/24803/rotate/180" for 127.0.0.1 at 2016-05-28 05:43:03 +0000
I, [2016-05-28T05:43:04.080861 #5769]  INFO -- : Processing by PhotosController#rotate as HTML
I, [2016-05-28T05:43:04.081274 #5769]  INFO -- :   Parameters: {"id"=>"24803", "degrees"=>"180"}
D, [2016-05-28T05:43:04.183430 #5769] DEBUG -- :   Photo Load (1.4ms)  SELECT  `photos`.* FROM `photos` WHERE `photos`.`id` = 24803 LIMIT 1
I, [2016-05-28T05:43:04.250844 #5769]  INFO -- : Completed 500 Internal Server Error in 169ms (ActiveRecord: 22.1ms)
F, [2016-05-28T05:43:04.256268 #5769] FATAL -- : 
Redis::CannotConnectError (Error connecting to Redis on localhost:6379 (Errno::ECONNREFUSED)):
  app/models/photo.rb:109:in `rotate'
  app/controllers/photos_controller.rb:106:in `rotate'

So I'm thinking that my app server does not get that it should go to the "backend server" for this stuff.

My configuration:

I have the app server running op 192.168.2.102 - everything is installed there except for redis. Redis is installed on 192.168.2.103

config/deploy.rb:

server '192.168.2.102', port: 22, roles: [:web, :app], primary: true
server '192.168.2.103', port: 22, roles: [:db, :resque_worker, :resque_scheduler]


set :repo_url,        'xxx'
set :application,     'xxx'
set :user,            'deploy'
set :puma_threads,    [4, 16]
set :puma_workers,    0
set :workers, { "import" => 1, "utility" => 1 }
set :resque_environment_task, true

# Don't change these unless you know what you're doing
set :pty,             true
set :use_sudo,        false
set :stage,           :production
set :deploy_via,      :remote_cache
set :deploy_to,       "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind,       "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state,      "#{shared_path}/tmp/pids/puma.state"
set :puma_pid,        "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log,  "#{release_path}/log/puma.access.log"
set :ssh_options,     { forward_agent: true, user: fetch(:user) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true  # Change to false when not using ActiveRecord

## Defaults:
set :scm,           :git
set :branch,        :master
# set :format,        :pretty
# set :log_level,     :debug
# set :keep_releases, 5

## Linked Files & Directories (Default None):
#set :linked_files, %w{db/production.sqlite3}
set :linked_dirs,  %w{ log tmp/pids tmp/cache tmp/sockets public/system }
#set :bundle_binstubs, nil

namespace :puma do
  desc 'Create Directories for Puma Pids and Socket'
  task :make_dirs do
    on roles(:app) do
      execute "mkdir #{shared_path}/tmp/sockets -p"
      execute "mkdir #{shared_path}/tmp/pids -p"
    end
  end

  before :start, :make_dirs
end

namespace :deploy do
  desc "Make sure local git is in sync with remote."
  task :check_revision do
    on roles(:app) do
      unless `git rev-parse HEAD` == `git rev-parse origin/master`
        puts "WARNING: HEAD is not the same as origin/master"
        puts "Run `git push` to sync changes."
        exit
      end
    end
  end

  desc 'Initial Deploy'
  task :initial do
    on roles(:app) do
      before 'deploy:restart', 'puma:start'
      invoke 'deploy'
    end
  end

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      invoke 'puma:restart'
    end
  end

  before :starting,     :check_revision
  after  :finishing,    :compile_assets
  after  :finishing,    :cleanup
  after  :finishing,    :restart




end
after "deploy:restart", "resque:restart"
# ps aux | grep puma    # Get puma pid
# kill -s SIGUSR2 pid   # Restart puma
# kill -s SIGTERM pid   # Stop puma

config/resque.yml:

development: localhost:6379
test: localhost:6379
production: 192.168.2.103:6379

config/initializers/resque.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')
Resque.redis = resque_config[rails_env]

Resque.logger = MonoLogger.new(File.open("#{Rails.root}/log/resque.log", "w+"))
Resque.logger.formatter = Resque::QuietFormatter.new

config/initializers/redis.rb:

$redis = Redis.new(:host => ENV["REDIS_HOST"], :port => ENV["REDIS_PORT"])

I'not sure whether I need the last file...

If you're thinking that it's my connectio setup that's wrong then think no more (about that..). Firstly Resque is not even trying to connect to the right redis. secondly, when I do this:

...on 192.168.2.103:

deploy@raspberrypi:~/apps/phototank $ netstat -nlpt | grep 6379
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::6379                 :::*                    LISTEN      -  

...on 192.168.2.102:

deploy@raspberrypi:~/apps/phototank $ redis-cli -h 192.168.2.103 ping
PONG

____EDIT____

If I run

RAILS_ENV=development rails s

on my development machine everything works perfect...what the hell?!??

martin
  • 3,289
  • 5
  • 22
  • 27
  • Are you running Rails in production environment? Your problem is that Rails is using Resque's development path for Redis. – Abdo May 28 '16 at 06:33
  • Yes it is production... why would it use development... It try to change the development path temporarily and see what happens – martin May 28 '16 at 06:35
  • You might want to check for `ENV["REDIS_HOST"]` in `config/initializers/redis.rb` . I suspect this is returning `localhost` too. – Abdo May 28 '16 at 06:40
  • You are right...it is using the development setup. I chenged that from localhost to 192.168.2.103 and it worked. I'll try the above and report back - thanks – martin May 28 '16 at 06:42
  • You will also need http://stackoverflow.com/a/37463835/226255 – Abdo May 28 '16 at 06:53
  • Keeping resque.yml as above and commenting out the one line in config/initializers/redis.rb does not solve the problem. So the question remains...why would resque use my development. The rest of the app uses the production env. e.g. the database runs on 192.168.2.103 without problems – martin May 28 '16 at 06:58
  • @abdo I have that ;-) – martin May 28 '16 at 06:59
  • sidenote: Are you set for Resque? Have you considered `Sidekiq` ? – Abdo May 28 '16 at 07:39
  • I have checked out sidekiq after your comment - looks really nice, especially the performance...I'm deploying to raspberry pi's... – martin Jun 01 '16 at 18:36
  • great to hear! :-) – Abdo Jun 01 '16 at 19:21

1 Answers1

0

Problem located:

config/initializers/resque.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')
Resque.redis = resque_config[rails_env]

Resque.logger = MonoLogger.new(File.open("#{Rails.root}/log/resque.log", "w+"))
Resque.logger.formatter = Resque::QuietFormatter.new

The second line sets the env to development if nothing else is defined...the env gets set in the line after that...

I simply removed the first two lines

martin
  • 3,289
  • 5
  • 22
  • 27