【问题标题】:is there a way to run a job at a set time later, without cron, say a scheduled queue?有没有办法在没有 cron 的情况下稍后在设定的时间运行作业,比如预定队列?
【发布时间】:2013-06-12 05:24:48
【问题描述】:

我有一个 Rails 应用程序,我想在后台运行作业,但我需要在原始事件 2 小时后运行该作业。

用例可能是这样的:

用户发布产品列表。 后台作业排队以联合列表到第 3 方 api,但即使在原始请求之后,响应也可能需要一段时间,第 3 方的解决方案是每 2 小时轮询一次,看看我们是否可以获得成功确认。

那么有没有办法将作业排队,以便工作守护进程知道忽略它或只在预定时间收听它?

我不想使用 cron,因为它会加载整个应用程序堆栈,并且可能会在重叠的长时间运行的作业上执行两次。

可以为此使用优先级队列吗?有什么解决方案来实现这一点?

【问题讨论】:

    标签: ruby-on-rails cron queue scheduled-tasks background-process


    【解决方案1】:

    尝试延迟工作 - https://github.com/collectiveidea/delayed_job

    类似的东西?

    class ProductCheckSyndicateResponseJob < Struct.new(:product_id)
      def perform
        product = Product.find(product_id)
    
        if product.still_needs_syndicate_response
          # do it ...
    
          # still no response, check again in two hours
          Delayed::Job.enqueue(ProductCheckSyndicateResponseJob.new(product.id), :run_at => 2.hours.from_now)
        else
          # nothing to do ...
        end
      end
    end
    

    首次在控制器中初始化作业,或者在模型上初始化 before_create 回调?

    Delayed::Job.enqueue(ProductCheckSyndicateResponseJob.new(@product.id), :run_at => 2.hours.from_now)
    

    【讨论】:

    • 我听说过延迟工作,但我认为他们总是立即执行。我不知道 :run_at
    【解决方案2】:

    使用Rufus Scheduler gem。它作为后台线程运行,因此您不必再次加载整个应用程序堆栈。把它添加到你的 Gemfile 中,然后你的代码就这么简单:

    # in an initializer,
    SCHEDULER = Rufus::Scheduler.start_new
    
    # then wherever you want in your Rails app,
    SCHEDULER.in('2h') do
      # whatever code you want to run in 2 hours
    end
    

    github page 有大量示例。

    【讨论】:

      猜你喜欢
      • 2017-01-23
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-09
      • 2016-03-01
      • 1970-01-01
      • 2019-08-12
      相关资源
      最近更新 更多