ruby-on-rails Rails异步活动作业不执行代码,而内联执行代码

ewm0tg9j  于 2023-10-21  发布在  Ruby
关注(0)|答案(3)|浏览(105)

..
:inline,这是Rails 4中的默认设置,处理用ActiveJob构建的作业,呃... inline,在当前执行线程中。不同步,不应该。它应该使用ConnectionPool,而不是在当前线程中运行它,这是理想情况下会发生的事情。它会在当前执行线程之外运行perform。
但没有什么能执行它。
我已经仔细阅读了文档,我唯一能理解的是:与:inline不同,:inline不执行任务,并希望您在本地构建一个围绕执行的系统。我必须在所有作业上手动执行perform,以便让它们在本地执行。当我将适配器设置为:inline时,它可以正常工作,而不必执行。
是否有一些配置问题,我错过了这是防止dspec正常工作(如dspec电缆?).
如果从rake任务(或控制台)执行,它是否不工作?).
它与:sidekiq/:resque一起工作得很好,但我不想一直在本地运行这些。
Rails by default comes with an "immediate runner" queuing implementation. That means that each job that has been enqueued will run immediately.
这是一种暗示我在那里是有问题的。我有一些作业在某个地方排队等待,但就是不运行。是什么阻止了这一切?

vh0rcniy

vh0rcniy1#

这就是我的发现。随着concurrent-ruby的出现,rake任务并没有设置来处理这个问题。
如果你读过文档,它说对于:async,当进程结束时,它会被清除出内存。
Rails本身只提供了一个进程内排队系统,它只将作业保存在RAM中。如果进程崩溃或机器被重置,那么所有未完成的作业都将丢失,默认的后台将丢失。
耙过程结束时,他们结束了。所以,如果你正在做任何类型的数据更改,rake任务将不会打开足够长的时间来运行作业,这就是为什么它们运行:inline很好,而不是:async
所以,我还没有想出一个解决方案来保持rake任务打开足够长的时间来运行:async(并保持应用程序:async的整个时间)。我必须将其切换到:inline来运行任务,然后在完成其余工作后再切换回:async。这就是为什么它可以很好地与:sidekiq:resque一起工作,因为这些应用程序将作业信息保存在内存中,并且在rake任务结束时不会释放。
为了让rake任务在本地与:async一起工作,如果你是本地的,除了以:inline的身份运行任务之外,你没有什么可以做的,直到rake(作为一个任务运行器)理解如何在异步任务启动(或不启动)时保持打开。作为一个仅用于开发的特性,这并不是真正的高优先级,但是,如果您不理解为什么:async默认情况下运行作业的任务实际上不会运行,这就是原因。

uqdfh47h

uqdfh47h2#

以下是您可以在rake任务结束时放置的内容,以等待AsyncAdapter完成处理,然后再退出rake任务:

if Rails.configuration.active_job.queue_adapter == :async
  executor =
    ActiveJob::Base._queue_adapter.instance_eval do
      @scheduler.instance_eval { @async_executor }
    end
  sleep(0.1) while executor.scheduled_task_count > executor.completed_task_count
end
vkc1a9a2

vkc1a9a23#

正如其他人所指出的,执行async时,作业在后台处理,任务没有等待。
其他人给出了一些复杂的方法,即使在测试中运行它们,也可以等待作业完成。
但是Rails实际上有一个内置的方法来做到这一点。使用perform_enqueued_jobs,您可以运行:jsp作业,但等待它们完成,而不必分配自己的自定义适配器。
https://api.rubyonrails.org/v7.0.0/classes/ActiveJob/TestHelper.html
执行所有排队作业。如果给定了一个块,则执行在该块持续期间排队的所有作业。如果未给出块,则执行测试中到此为止的所有排队作业。

def test_perform_enqueued_jobs
  perform_enqueued_jobs do
    MyJob.perform_later(1, 2, 3)
  end
  assert_performed_jobs 1
end

def test_perform_enqueued_jobs_without_block
  MyJob.perform_later(1, 2, 3)

  perform_enqueued_jobs

  assert_performed_jobs 1
end

对于rspec,只需在describe块中插入include ActiveJob::TestHelper即可。

相关问题