gpt4 book ai didi

ruby-on-rails - 事件作业 : how to do simple operations without a full blown job class?

转载 作者:数据小太阳 更新时间:2023-10-29 08:03:37 25 4
gpt4 key购买 nike

使用delayed_job,我可以像这样进行简单的操作:

@foo.delay.increment!(:myfield)

是否可以用 Rails 的新 ActiveJob 做同样的事情?(无需创建一大堆作业类来执行这些小操作)

最佳答案

ActiveJob 只是各种后台作业处理器之上的抽象,因此许多功能取决于您实际使用的提供商。但我会尽量不依赖任何后端。

通常,作业提供者由持久化机制运行器组成。卸载作业时,您以某种方式将其写入持久性机制,然后其中一个运行器检索并运行它。所以问题是:您能否以与您需要的任何操作兼容的格式来表达您的工作数据?

这会很棘手。

那么让我们来定义什么是工作定义。例如,它可以是单个方法调用。假设这个语法:

Model.find(42).delay.foo(1, 2)

我们可以使用以下格式:

{
class: 'Model',
id: '42', # whatever
method: 'foo',
args: [
1, 2
]
}

现在我们如何从给定的调用构建这样的哈希并将其排入作业队列?

首先,看起来,我们需要定义一个类,它有一个 method_missing 来捕获被调用的方法名:

class JobMacro
attr_accessor :data
def initialize(record = nil)
self.data = {}
if record.present?
self.data[:class] = record.class.to_s
self.data[:id] = record.id
end
end
def method_missing(action, *args)
self.data[:method] = action.to_s
self.data[:args] = args
GenericJob.perform_later(data)
end
end

作业本身必须像这样重建该表达式:

data[:class].constantize.find(data[:id]).public_send(data[:method], *data[:args])

当然,您必须在模型上定义delay 宏。最好将它分解到一个模块中,因为定义非常通用:

def delay
JobMacro.new(self)
end

它确实有一些限制:

  • 仅支持在持久化的 ActiveRecord 模型上运行作业。一项工作需要一种方法来重建被调用者以调用该方法,我选择了最可能的方法。如果需要,您也可以使用编码,但我认为这不可靠:在作业开始执行时,未编码的对象可能无效。 “GlobalID”也是如此。
  • 它使用 Ruby 的反射。对于许多问题来说,这是一个诱人的解决方案,但速度不快,而且在安全性方面有点冒险。因此,请谨慎使用此方法。
  • 只有一个方法调用。没有 procs(你可以用 ruby2ruby gem 做到这一点)。依靠作业提供者正确序列化参数,如果失败,请使用您自己的代码帮助它。例如,que 在内部使用 JSON,所以在 JSON 中有效的任何东西,在 que 中也有效。例如,符号不会。

一开始事情会以惊人的方式破裂。
因此,请务必在开始之前设置调试工具。


这方面的一个例子是 Sidekiq's backward (Delayed::Job) compatibility extension for ActiveRecord .

关于ruby-on-rails - 事件作业 : how to do simple operations without a full blown job class?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30962808/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com