Rake 任务和 Rails 初始化程序

发布于 2024-11-25 21:25:34 字数 1031 浏览 2 评论 0原文

对 Rails 有点陌生,所以请配合我。我现在正在做的是使用 Resque 后台处理一些 Ruby 代码。为了启动 Rescque rake 任务,我一直在使用(在 heroku 上),我有一个 resque.rake 文件,其中包含推荐的代码以附加到 heroku 的神奇(或奇怪)线程架构中:

require "resque/tasks"
require 'resque_scheduler/tasks'

task "resque:setup" => :environment do
  ENV['QUEUE'] = '*'
end


desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "resque:work"

因为我需要访问 Rails 代码,我参考:环境。如果我在 Heroku 的后台设置至少 1 个 Worker dyno,我的 Resque 会表现出色,被清除,一切都很愉快。直到我尝试自动化操作......

所以我想改进代码并每分钟左右自动用相关任务填充队列。这样做(不使用 cron,因为 heroku 不足以使用 cron),我声明一个名为 task_scheduler.rb 的初始化程序,它使用 Rufus 调度程序来运行任务:

scheduler = Rufus::Scheduler.start_new

scheduler.in '5s' do
  autoprocessor_method
end

scheduler.every '1m' do
  autoprocessor_method
end

事情似乎在一段时间内工作得很好......然后 rake 进程就停止了莫名其妙地从队列中拿起。队列变得越来越大。即使我有多个工作测功机在运行,它们最终都会感到疲倦并停止处理队列。我不确定我做错了什么,但我怀疑在我的 rake 任务中引用 Rails 环境导致 task_scheduler.rb 代码再次运行,从而导致重复调度。我想知道如果有人知道如何解决这个问题,而且我也很好奇这是否是 rake 任务停止工作的原因。

谢谢

Kinda new to Rails, so please cope with me. What i'm doing now is background processing some Ruby code use Resque. To get the Rescque rake task started, I've been using (on heroku), I have a resque.rake file with that recommended code to attach into heroku's magical(or strange) threading architecture:

require "resque/tasks"
require 'resque_scheduler/tasks'

task "resque:setup" => :environment do
  ENV['QUEUE'] = '*'
end


desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "resque:work"

Since I need access to the Rails code, I reference :environment. If I set at least 1 worker dyno in the background on heroku, my Resque does great, gets cleared, everything is happy. Until i try to automate stuff...

So I wanted to evolve the code and automatically fill the queue with relevant tasks every minute or so. Do that (without using cron, because heroku is not adequate with cron), I declare an initializer named task_scheduler.rb that uses Rufus scheduler to run tasks:

scheduler = Rufus::Scheduler.start_new

scheduler.in '5s' do
  autoprocessor_method
end

scheduler.every '1m' do
  autoprocessor_method
end

Things appear to work awesome for a while....then the rake process just stops picking up from the queue unexplainably. The queue just gets larger and larger. Even if i have multiple worker dynos running, they all eventually get tired and stop processing the queue. I'm not sure what I am doing wrong, but I suspect the referencing of the Rails environment in my rake task is causing the task_scheduler.rb code to run again, causing duplicate scheduling. I'm wondering how to solve that problem if someone knows, and I'm also curious if that is the reason for the rake task to stop working.

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

单身狗的梦 2024-12-02 21:25:34

您不应该在初始化程序中启动调度程序,您应该有一个守护进程运行调度程序并填充队列。它会是这样的(“脚本/调度程序”):

#!/usr/bin/env ruby

root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
Dir.chdir(root)

require 'rubygems'
gem 'daemons'
require 'daemons'

options = {
    :dir_mode   => :normal,
    :dir        => File.join(root, 'log'),
    :log_output => true,
    :backtrace  => true,
    :multiple   => false
}

Daemons.run_proc("scheduler", options) do

  Dir.chdir(root)
  require(File.join(root, 'config', 'environment'))

  scheduler = Rufus::Scheduler.start_new

  scheduler.in '5s' do
    autoprocessor_method
  end

  scheduler.every '1m' do
    autoprocessor_method
  end

end

您可以从您的应用程序中将此脚本作为常用守护进程调用:

script/scheduler start

这将确保您只有一个进程为该应用程序发送工作resque 工作人员,而不是为您运行的每个杂种工作人员分配一个工作人员。

You should not be booting the scheduler in an initializer, you should have a daemon process running the scheduler and filling up your queue. It would be something like this ("script/scheduler"):

#!/usr/bin/env ruby

root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
Dir.chdir(root)

require 'rubygems'
gem 'daemons'
require 'daemons'

options = {
    :dir_mode   => :normal,
    :dir        => File.join(root, 'log'),
    :log_output => true,
    :backtrace  => true,
    :multiple   => false
}

Daemons.run_proc("scheduler", options) do

  Dir.chdir(root)
  require(File.join(root, 'config', 'environment'))

  scheduler = Rufus::Scheduler.start_new

  scheduler.in '5s' do
    autoprocessor_method
  end

  scheduler.every '1m' do
    autoprocessor_method
  end

end

And you can call this script as a usual daemon from your app:

script/scheduler start

This is going to make sure you have only one process sending work for the resque workers instead of one for each mongrel that you're running.

相权↑美人 2024-12-02 21:25:34

首先,如果你不是在 Heroku 上运行,我不会推荐这种方法。我会看看 Mauricio 的答案,或者考虑使用经典的 cron 作业或使用 Everytime 来安排 cron 作业。

但如果你在 Heroku 上运行并尝试这样做时感到痛苦,那么我是如何让它发挥作用的。

我保留了相同的原始 Resque.rake 代码,就像我粘贴在原始问题中一样。此外,我创建了另一个附加到 jobs:work rake 进程的 rake 任务,就像第一种情况一样:

desc "Scheduler processor"
  task :scheduler => :environment do
  autoprocess_method
  scheduler = Rufus::Scheduler.start_new
  scheduler.every '1m' do
     twitter_autoprocess
  end
end

desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "scheduler"

注意事项:

  1. 一旦您使用多个工作 dyno,这将是不完美的,因为调度程序将在多个工作中运行点。您可以通过在某处保存状态来解决这个问题,但它并不像我想要的那么干净。
  2. 我找到了进程挂起的原始原因。就是这行代码:

    scheduler.in '5s' 执行
     自动处理器方法
    结尾
    

    我不知道为什么,但是当我删除它时,它再也没有挂起。

First of all, if you are not running on Heroku, i would not recommend this approach. I'd look at Mauricio's answer, or consider using a classic cron job or using Whenever to schedule the cron job.

But if you are in the pain of running on heroku and trying to do this, here is how i got this to work.

I kept the same original Resque.rake code in place, as i pasted in the original question. In addition, i created another rake task that i attached to the jobs:work rake process, just like the first case:

desc "Scheduler processor"
  task :scheduler => :environment do
  autoprocess_method
  scheduler = Rufus::Scheduler.start_new
  scheduler.every '1m' do
     twitter_autoprocess
  end
end

desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "scheduler"

Couple of notes:

  1. This will be imperfect once you use more than one worker dyno because the scheduler will run in more than one spot. you can solve that by saving state somewhere, but its not as clean as I would like.
  2. I found the original reason why the process would hang. It was this line of code:

    scheduler.in '5s' do
     autoprocessor_method
    end
    

    I'm not sure why, but when I removed that, it never hung again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文