在 Rails 中安排一个 ActiveJob

Posted

技术标签:

【中文标题】在 Rails 中安排一个 ActiveJob【英文标题】:Schedule an ActiveJob in Rails 【发布时间】:2017-09-16 07:50:31 【问题描述】:

我正在做一个天气 API,它将从另一个 API 获取、处理和保存数据。为了获得每日更新(请求 URL 信息、获取 JSON/XML 数据、构建我的数据并将其保存到我的数据库中),我认为最合适的方法是使用 ActiveJob。

我想安排作业定期运行。我想要类似 UNIX cron 或 Java 的 Spring @Scheduled 注解。

我在 Stack Overflow(this one) 上看到了另一个关于调度作业的问题,但他们像任何时候一样使用外部 gem。我一直在寻找允许在 Rails API (Backends) 中执行作业的后端,但似乎没有一个可用的后端允许调度作业。

Rails 框架(第 5 版)上有什么可以让我做我想做的事吗?或者我必须使用外部宝石?

非常感谢。

编辑 如果对任何人有用,这里是工作的架构:

class ImportDailyDataJob < ApplicationJob
  queue_as :default

  def perform(*args)
    # Do something later
  end

  private

  def prepare_request
    # return the request object
  end

  def request_data
    # Get the data from external API.
  end

  def process_data
    # Process the data
  end

  def save_processed_data
    # Saves the data to the database
  end
end

【问题讨论】:

投了赞成票,因为只有 Rails 的方法可以做到这一点。我个人使用 cron 作业来运行 rails 脚本。 只是为了澄清一些关于外部 gem 与 A​​ctiveJob 的关系:AJ 为各种队列适配器提供了一个通用接口,因此可以轻松切换使用 Resque 等相同的代码说完,Sidekiq。但是,如果不使用 Rails 核心之外的一些工具,您并不会真正从 AJ 中获得太多好处。 有人试过active_job 吗? 【参考方案1】:

这不是真正的调度,但如果您不需要完全准确的调度,您可以在某些情况下伪造它,即在您的情况下,每天运行一次作业:

class WeatherJob < ApplicationJob
  def perform
    reschedule_job

    do_work
  end

  def do_work
    # ...
  end

  def reschedule_job
    self.class.set(wait: 24.hours).perform_later
  end
end

使用 ActiveJob 将作业排队以在将来运行应该与 DelayedJob 或 Sidekiq 一起使用,可能并非所有活动作业后端都支持?

【讨论】:

不错的方法!您的方法将允许我每天执行一次作业,而无需使用外部 gem,但最初如何运行它? 第一次从 Rails 控制台入队 bundle exec rails console - WeatherJob.perform_later 将导致它立即运行,这将在 24 小时后将记录入队以再次运行【参考方案2】:

我认为你应该去 sidekiq 使用 redis 编写一个任务来安排一个工作,这样做只需安装这两个 gem 并可以去他们的文档:

gem 'redis-rails'

然后安装sidekiq

gem 'sidekiq'

【讨论】:

感谢您的回答。正如两个答案都证实的那样,Rails 上没有内置调度程序。 不,不是 ActiveJob 为您提供 redis 和 sidekiq 的所有功能,但它是 rails 的核心,您必须先阅读文档,然后才能处理,但是 redis并且 sidekiq 也会通过 ui 让您更好地理解这一点。【参考方案3】:

大多数主要的 AJ 适配器都具有一些用于调度作业的功能,但有些则将该功能分离到单独的 gem 中。例如,对于 Resque,有一个单独的 resque-scheduler gem 与 vanilla Resque gem 一起工作。

还有here's 关于经常性工作的一点。完成一些基本设置后,您创建一个 schedule.yml 文件,定义您希望作业运行的方式/时间,例如

# config/initializers/resque_scheduler.rb
Resque.schedule = YAML.load_file('../calendar.yml')

# config/calendar.yml
your_recurring_job:
  cron: "0 0 * * *" # Every day at midnight
  class: "YourJobClass"
  queue: your_queue
  args:
  description: "This job does a thing, daily"

我不了解每个适配器,但主要的适配器通常有类似的姐妹 gem 提供此功能。

【讨论】:

要明确一点,虽然这使用了cron语法,但它并没有经过cron。它完全在 Redis/Resque 中工作。 感谢您的解释和链接。我需要调查 Redis 在作业调度程序过程中的作用,因为两个答案都建议使用外部 gem + Redis。但这将是另一个问题的好话题。无论如何,我可能会使用 Resque。

以上是关于在 Rails 中安排一个 ActiveJob的主要内容,如果未能解决你的问题,请参考以下文章

在 NodeJS 中安排一个异步函数

如何在 BigQuery 中安排脚本?

通过 R 运行 .vbs 脚本,在任务计划程序中安排

在 ReactJS 中安排 API 调用

如何在 SQL Developer 中安排作业

如何在詹金斯中安排多个配置文件?