1

我正在开发一个 Rails 应用程序,目前我们正在迁移到 jruby。我们目前在我们的一个模型上有超过 10 个后回调,这会长时间阻止响应。

after_update :sync
after_update :send
after_create :add
after_create :add
after_create :send
after_update :track!
after_create :track!
after_create :send_welcome_email
after_create :track
after_update :send
after_update :set_is_active!
after_update :set_
after_create :apply
after_update :apply
after_update :clear
after_create :mark

我需要包装/覆盖activerecord的后回调(after_save,after_update)以使用concurrent-ruby异步运行它们而不阻塞响应,但我不知道如何以正确的方式做到这一点。

我想做的是这样的

require 'concurrent'
class ApplicationRecord < ActiveRecord::Base
  def after_update
    Concurrent::Promise.new { super }.exec
  end
end

我只需要知道正确的语法以及这是否是此类事情的正确方法。将不胜感激任何建议。

4

1 回答 1

0

这里没有一般性建议 - 需要对应用程序有所了解。

需要注意的几件事:

  • 听起来你正处于回调地狱中,也许重新考虑一下架构 - 缩小这些模型和/或使用观察者(以简化)

  • 您当然可以将执行移至另一个线程,但操作后最好不要依赖于彼此的状态

  • 如果那些在零件之后进行数据库操作的人也要注意在“主要”事务之外运行它们

  • 最后但并非最不重要的一点是不要忘记进行清理 - AR 连接应该放回池中,因为 Rails 不会为您执行此操作(与请求线程一样),除非您明确告诉它

一般情况下,如果您需要等待完成并且您的回调需要按顺序运行,则将它们移动到另一个线程不会产生太大影响。如果不是这种情况 - 尝试一下,也许考虑一下您是否希望所有 Promise 都在同一个(默认)执行器上运行,或者想要显式定义不同的 Promise(例如,对于 CPU 密集型任务与 IO 绑定的任务)。

于 2018-12-04T18:05:07.237 回答