【问题标题】:Initialize the Delayed Jobs gem by starting the workers on application start通过在应用程序启动时启动工作人员来初始化延迟作业 gem
【发布时间】:2014-05-12 14:02:14
【问题描述】:

我正在使用 Ruby on Rails 3.0.9 并尝试设置 delay_job gem。如果在重新启动 Apache2 服务器后,我在 Terminal\Console 中运行以下命令,则一切正常:

RAILS_ENV=development script/delayed_job stop
RAILS_ENV=development script/delayed_job -n 2 start

但是,由于我总是想在应用程序启动时启动工作程序,因此在我的 config/initializers/delayed_job.rb 中添加以下代码(同时处理开发和生产模式):

if Rails.env.development?
  system 'RAILS_ENV=development script/delayed_job stop'
  system 'RAILS_ENV=development script/delayed_job -n 2 start'
elsif Rails.env.production?
  system 'RAILS_ENV=production script/delayed_job stop'
  system 'RAILS_ENV=production script/delayed_job -n 2 start'
end

但是,通过使用上述代码并重新启动 Apache2 服务器后,DJ gem 不再按预期工作。也就是说,它不会像我在 Terminal\Console 中运行上述命令行时那样处理作业。

如何让 DJ 正常工作?有什么问题?

P.S.:我想这样做是为了使流程自动化。


config/initializers/delayed_job.rb 文件中的上述代码没有“创建”RAILS_ROOT/tmp/pids 目录中与 DJ 相关的“pids”文件。这些只能通过手动运行上述命令行来创建。为什么会这样?


@Devin M

更新

我的config/initializers/delayed_job.rb 包含:

# Options
Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.sleep_delay = 2
Delayed::Worker.max_attempts = 5
Delayed::Worker.max_run_time = 1.hour
Delayed::Worker.delay_jobs = !Rails.env.test?

if Rails.env.development?
  system "RAILS_ENV=development #{Rails.root.join('script','delayed_job')} stop"
  system "RAILS_ENV=development #{Rails.root.join('script','delayed_job')} -n 2 start"
elsif Rails.env.production?
  system "RAILS_ENV=production #{Rails.root.join('script','delayed_job')} stop"
  system "RAILS_ENV=production #{Rails.root.join('script','delayed_job')} -n 2 start"
end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 initialization delayed-job


    【解决方案1】:

    我认为你不能这样做,因为当你启动“/script/delayed_job”时,rails 环境将被加载,导致“config/initializers/delayed_job.rb”文件再次被执行。 您可以看到这会导致无限循环。 此外,每次调用 rake 时,例如:'rake db:migrate',它都会初始化 delay_jobs。

    你可以用这个来破解它:

    if Rails.env.production?
      if(!File.exists?(Rails.root.join('tmp','pids', 'delayed_job.pid')))
        system "echo \"Starting delayed_jobs...\""
        system "./script/delayed_job start &"
      else
        system "echo \"delayed_jobs is running\""
      end
    end
    

    使用“&”,delayed_job 脚本在后台运行,在与 rails 不同的进程上。 如果 delay_jobs 已经在运行,则后续调用 rake 将跳过它的启动。 如果由于某种原因在delayed_jobs 终止时没有删除该文件,您仍然会遇到一些问题。

    命令 /script/delayed_job 状态 会检测是否是这种情况,但你不能在这个 'config/initializers/delayed_job.rb' 文件中运行它,因为它会导致无限循环:(

    【讨论】:

    • 听这个家伙说“但是你不能在这个 'config/initializers/delayed_job.rb' 文件中运行它,因为它会导致无限循环”
    【解决方案2】:

    尝试使用此代码:

    system "RAILS_ENV=production #{Rails.root.join('script','delayed_job')} stop"
    system "RAILS_ENV=production #{Rails.root.join('script','delayed_job')} -n 2 start"
    

    在控制台中测试它产生了这个输出,表明它应该可以工作:

    Loading development environment (Rails 3.0.9)
    ruby-1.9.2-p290 :001 > Rails.root.join('script','delayed_job')
     => #<Pathname:/home/devin/testsoapp/script/delayed_job> 
    ruby-1.9.2-p290 :002 > "RAILS_ENV=production #{Rails.root.join('script','delayed_job')} -n 2 start"
     => "RAILS_ENV=production /home/devin/testsoapp/script/delayed_job -n 2 start" 
    ruby-1.9.2-p290 :003 > 
    

    【讨论】:

    • 通过使用您的代码,得到的测试输出与您的相同(当然我的应用程序的路径引用不同),但它仍然不起作用。也就是说,它仍然不会在RAILS_ROOT/tmp/pids 中创建“pid”文件。请注意,此时我正在本地计算机上以开发模式运行该应用程序。
    • 如果您在应用程序控制台中运行"RAILS_ENV=production #{Rails.root.join('script','delayed_job')} -n 2 start",然后在终端中将返回的字符串作为命令运行,它会起作用吗?
    • 不,它不起作用。请注意,此时我正在本地计算机上以开发模式运行该应用程序。
    • 在开发模式下,如果我在控制台中运行RAILS_ENV=development #{Rails.root.join('script','delayed_job')} -n 2 start",它会按预期工作。在开发模式下,如果我在 config/initializers/delayed_job.rb 文件中使用相同的代码(如问题中所述),它不起作用。此行为是否取决于某些用户对目录和文件的权限(我的本地计算机是运行 Snow Leopard 的 MAC OS)?
    • delayed_job.logdevelopment.log 文件中我没有错误。 (对我来说)很奇怪,将 RAILS_ENV=development #{Rails.root.join('script','delayed_job')} -n 2 start 放在初始化文件中不起作用,而通过运行命令行版本起作用。
    【解决方案3】:

    我遇到了一个问题,即在创建 pid 文件之前,初始化 delay_job 进程正在通过其初始化程序运行(即,对于单个工作人员,delayed_job.pid 和delayed_job.0.piddelayed_job.1.pid 等,如果有很多工人)

    所以我求助于创建自己的锁定文件:

    Delayed::Worker.destroy_failed_jobs = false
    Delayed::Worker.sleep_delay = 2
    Delayed::Worker.max_attempts = 5
    Delayed::Worker.max_run_time = 4.hour
    Delayed::Worker.delay_jobs = !Rails.env.test?
    
    workers = 2
    
    
    if Rails.env.production? || Rails.env.development?
      # Check if the delayed job process is already running
      # Since the process loads the rails env, this file will be called over and over
      # Unless this condition is set.
      pids = Dir.glob(Rails.root.join('tmp','pids','*'))
    
      system "echo \"delayed_jobs INIT check\""
      if pids.select{|pid| pid.start_with?(Rails.root.join('tmp','pids','delayed_job.init').to_s)}.empty?
    
        f = File.open(Rails.root.join('tmp','pids','delayed_job.init'), "w+") 
        f.write(".")
        f.close
        system "echo \"Restatring delayed_jobs...\""
        system "RAILS_ENV=#{Rails.env} #{Rails.root.join('bin','delayed_job')} stop"
        system "RAILS_ENV=#{Rails.env} #{Rails.root.join('bin','delayed_job')} -n #{workers} start"
        system "echo \"delayed_jobs Workers Initiated\""
        File.delete(Rails.root.join('tmp','pids','delayed_job.init')) if File.exist?(Rails.root.join('tmp','pids','delayed_job.init'))
    
      else
        system "echo \"delayed_jobs is running\""
      end
    end
    

    文件:config\initializers\delayed_job.rb

    注意:不适用于 windows!

    【讨论】:

      猜你喜欢
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      • 2011-02-04
      • 1970-01-01
      • 2013-10-22
      • 1970-01-01
      • 2012-03-21
      相关资源
      最近更新 更多