Resque-Scheduler在Rails 4.2中无法与ActiveJob一起使用

9

有人能够在Rails 4.2中成功使用定时任务吗?

我正在使用resque,并尝试使用resque-scheduler来安排任务。我已经加载了一个计划表,调度程序运行起来了,看起来也在运行任务,但它并没有做任何事情。

resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Starting
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Loading Schedule
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Scheduling friends 
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Schedules Loaded
resque-scheduler: [INFO] 2014-09-16T01:54:55-07:00: queueing FriendsJob (friends)

我可以像这样排队工作,然后它们会被处理。
TestJob.enqueue(params[:id])

并且我在工作日志中获得了这个输出。
got: (Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])
** [01:24:01 2014-09-16] 54841: resque-1.25.2: Processing default since 1410855841  [ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper]
** [01:24:01 2014-09-16] 54841: Running before_fork hooks with [(Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])]
** [01:24:01 2014-09-16] 54841: resque-1.25.2: Forked 54882 at 1410855841
** [01:24:01 2014-09-16] 54882: Running after_fork hooks with [(Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])]
Hello World!!
** [01:24:01 2014-09-16] 54882: done: (Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])

但是当我尝试安排一项任务时,它们似乎已经被加入队列,但却没有执行任何操作。
以下是schedule.yml的内容:
friends:
  every: "30s"
  queue: "friends"
  class: "FriendsJob"
  args: 8
  description: "Friends jobs scheduler"

以下是预定任务的输出结果。

** [01:23:36 2014-09-16] 54841: got: (Job{friends} | FriendsJob | [8])
** [01:23:36 2014-09-16] 54841: resque-1.25.2: Processing friends since 1410855816 [FriendsJob]
** [01:23:36 2014-09-16] 54841: Running before_fork hooks with [(Job{friends} | FriendsJob | [8])]
** [01:23:36 2014-09-16] 54841: resque-1.25.2: Forked 54880 at 1410855816
** [01:23:36 2014-09-16] 54880: Running after_fork hooks with [(Job{friends} | FriendsJob | [8])]
** [01:23:36 2014-09-16] 54880: done: (Job{friends} | FriendsJob | [8])

阅读完这篇文章http://dev.mikamai.com/post/96343027199/rails-4-2-new-gems-active-job-and-global-id后,我怀疑它与ActiveJob和GlobalId有关。

看一下排队的不同之处。

** [01:24:01 2014-09-16] 54841: Running before_fork hooks with [(Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])]

vs scheduled

** [01:23:36 2014-09-16] 54841: Running before_fork hooks with [(Job{friends} | FriendsJob | [8])]

这些工作是通过生成器创建的。
 rails g job <JobName>

它们长这样:
class TestJob < ActiveJob::Base
  queue_as :default
  def perform(friend_id)
    friend = Friend.find(friend_id)
    name = friend.name.swapcase
    puts "Hello World!!"
  end
end


class FriendsJob < ActiveJob::Base
  queue_as :friends
  def perform(friend_id)
    friend = Friend.find(friend_id)
    name = friend.name.swapcase
    puts "Hello World!!"
  end
end

非常感谢你的帮助,提前表示感谢。
****** 更新 *********
我已经移除了action_job railtie,现在只使用Resque和Resque-Scheduler,预定的作业正在工作。因此,这似乎与ActionJob/GlobalId有关。我在rails项目中开了一个问题。希望他们能尽快解决。
****** 第二次更新 *********
我得到了一个更新。在ActiveJob代码库中工作的Cristianbica说过这样一句话。 “我们迄今为止还没有考虑过重复作业,而且没有支持它,因为没有任何适配器能够支持它,除非使用外部gem。然而,这是一个非常好的功能,但我认为我们无法及时将其纳入4.2版本。此外,我不确定它是否适合包含在Rails中。”

如果有人对上述问题感兴趣,请查看此链接:https://github.com/rails/rails/issues/16933。 - Juanito Fatas
我也想利用activejob,但是我被拖住了,因为我需要有每15分钟和每1分钟运行的定期工作。 - omencat
3个回答

5

1
这很有潜力!我要试一试。谢谢! - luis.madrigal
1
非常感谢您的工作,Justin。它运行得非常好。 - trans1t

3

看起来Rails 4.2中的ActiveJob并不被resque-scheduler支持,因此作业没有被正确调度,这就解释了使用ActiveJob API和resque-scheduler入队作业时日志差异的原因。

为了解决这个问题,我们应该找到一种在ActiveJob包装器中调度作业的方法:

ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper

Resque-scheduler提供了一种支持默认未支持的扩展的方式。为此,我们应该扩展自定义作业类以支持#scheduled方法。这样,我们就可以使用ActiveJob API手动排队作业。

最简单的方法是在基础作业中编写通用代码方法,然后从中扩展所有作业:

# custom base job
class Job < ActiveJob::Base

    # method called by resque-scheduler to enqueue job in a queue
    def self.scheduled(queue, klass, *args)

        # create the job instance and pass the arguments
        job = self.job_or_instantiate(*args)

        # set correct queue
        job.queue_name = queue

        # enqueue job using ActiveJob API
        job.enqueue
    end
end

Reque-scheduler会调用此方法来调度从Job类扩展的每个单独的作业。这样,作业将在ActiveJob包装器中排队等待。结果与调用MyJob.perform_later(*args)相同。


1
这是自述文件中提到的相关部分:https://github.com/resque/resque-scheduler#support-for-resque-status-and-other-custom-jobs - thisismydesign
1
一个需要注意的是,命名参数无法正常工作(否则应该使用ActiveJob)。 - thisismydesign

2

更新:4/4/16 - 虽然下面的答案在当前版本的Rails中仍然正确,但我现在使用了Justin创建的active_scheduler gem,如上面的答案所提到的:https://dev59.com/WIPba4cB1Zd3GeqPsG4Z#29155372

原始答案: 如果需要安排定期工作,请避免使用ActiveJob。

来自Luis提出的问题

由于我们目前不支持使用ActiveJob进行定期工作,因此我们将关闭此操作。如果可以支持定期工作,我将其视为单独的gem或在rails 5中。功能请求和相关讨论通常在邮件列表中讨论(https://groups.google.com/forum/#!forum/rubyonrails-core)。 作为@luismadrigal问题的解决方案,我建议您使用resque-scheduler方式执行定期工作。

https://github.com/rails/rails/issues/16933#issuecomment-58945932

曾经有讨论要创建一个gem 在邮件列表中,但我找不到更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接