【问题标题】:How to perform Asynchrnous task in rails using delayed_jobs?如何使用延迟作业在 Rails 中执行异步任务?
【发布时间】:2015-06-30 11:19:00
【问题描述】:

任务: 以Async的方式删除一个项目[HomeWork]

我已经在我的 rails 应用程序中配置了 Active jobsdelayed_jobs,但我仍然对在 rails 项目中执行 Async 任务感到困惑。

我们举个例子: 我有一些项目要从数据库中删除,但我想以Async 的方式删除。我还在delayed_job 博客中读到了perform_laterperform_now 方法。这是我工作正常的代码:

控制器类

 def destroy
   PostJob.perform_now(params[:id])
   respond_to do |format|
    format.xml  { head :ok }
    format.js { render 'posts.js.erb' }
  end
 end

职位类别

class PostJob < ActiveJob::Base
 queue_as :default

 def perform(id)
  @post = Post.find(id)
  @post.destroy
 end
end

根据delayed_jobs的official doc,我可以在方法末尾添加handle_asynchronously,以async的方式运行。在这种情况下我该如何实施?

我的问题:

  1. 当我查看destroy 方法时,它不会以Async 方式删除元素。但是,用destroy 方法编写的每个步骤都在Synchronous 中。我错了吗?
  2. 如果不是,那么如何实现destroy 方法以异步方式删除post
  3. 后台任务和 cron 任务是一回事吗?

编辑-1

在 A Fader Darkly 提出建议后,我将 perform_now 更改为 perform_later,这对于 Async 进程非常有效,但它没有从表中删除条目(代码很好,因为它在我用户 @987654343 时有效@)。

当我通过以下命令手动运行作业时,一切正常:

rake jobs:work

有什么方法可以在queue 获得一些新数据后立即执行delay_job 任务?

【问题讨论】:

    标签: ruby-on-rails ruby asynchronous delayed-job rails-activejob


    【解决方案1】:

    如果您将销毁方法更改为调用:

    PostJob.perform_later(params[:id])
    

    它应该异步发生。如果没有,您需要进行更多设置。

    对于您的问题:

    1. 是的,你是对的,但你说的是同义反复。该方法中的所有内容都是同步的 - 由于perform_now,不使用作业队列。因此,destroy 不会以异步方式删除。
    2. 见上文。
    3. Cron 作业在操作系统级别工作,并定期安排在特定时间。例如,您可以让 cron 作业每分钟、每天或每周(在特定日期的特定时间)都在工作。它们从称为 crontab 的计划文件运行。

    “后台”任务只是阻止它接管终端会话的 IO。因此,您可以在进程在后台运行时继续使用终端。通常这是临时完成的,因此您不必等待繁重的操作完成后再继续执行不同的任务。

    编辑

    根据对问题的编辑,听起来需要启动延迟作业守护程序。根据说明:

    注意:对于 Rails 4,将 script/delayed_job 替换为 bin/delayed_job 在本地运行队列时,请省略命令的“RAILS_ENV=production”部分。

    运行作业 script/delayed_job 可用于管理将开始工作的后台进程。

    为此,请将 gem“守护进程”添加到您的 Gemfile 中,并确保您已运行 rails generate delayed_job。

    然后您可以执行以下操作:

    RAILS_ENV=生产脚本/delayed_job 开始 RAILS_ENV=生产脚本/delayed_job 停止

    在不同的进程中运行两个工人。

    RAILS_ENV=生产脚本/delayed_job -n 2 开始 RAILS_ENV=生产脚本/delayed_job 停止

    设置 --queue 或 --queues 选项以从特定队列工作。

    RAILS_ENV=生产脚本/delayed_job --queue=跟踪开始 RAILS_ENV=生产脚本/delayed_job --queues=mailers,tasks start

    使用 --pool 选项指定工作池。您可以多次使用此选项为不同的队列启动不同数量的工作人员。

    以下命令将为跟踪队列启动 1 个工作器,

    2 个工作人员用于邮件和任务队列,2 个工作人员用于任何工作:

    RAILS_ENV=生产脚本/delayed_job --pool=tracking --pool=mailers,tasks:2 --pool=*:2 start

    运行所有可用的作业,然后退出

    RAILS_ENV=生产脚本/delayed_job start --exit-on-complete

    或在前台运行

    RAILS_ENV=生产脚本/delayed_job 运行 --exit-on-complete

    【讨论】:

    • 感谢您的精彩解释!我从 destroy 方法中删除了其余代码,它工作正常。但正如你提到的,这个过程是sync 而不是Async。我可以做到async,但是如果我使用perform_later,它什么时候执行?我需要对delay_job_config 文件进行任何更改吗?
    • 如果您使用 'perform_later',那么它将在队列准备好处理作业时立即执行。除非您有 1000 多个小任务或一些非常繁重的任务,否则 perform_later 将接近即时。但是,您不会知道调用它的代码中的操作结果。如果这就是删除代码的意思,则无需删除“respond_to”块。
    • 好的,知道了但是当我使用perform_later 运行方法并刷新页面时,即使在 5 分钟后它也没有被删除。当我检查工作日志时。它创建了一个新条目,但该作业尚未运行。实际上我的作业是当我从 UI 中单击 Delete 时开始删除过程
    • @A Fader 请查看问题的编辑部分
    • 听起来队列没有运行。如果您使用的是“延迟作业”gem,您需要运行一个队列进程。把它想象成一个网络服务器——一个网络服务器需要运行来服务页面,队列需要运行来处理作业。看这里:github.com/collectiveidea/delayed_job 并找到关于“运行作业”的部分
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    相关资源
    最近更新 更多