【问题标题】:ActiveJob with Sidekiq backend passing complex object as parameter带有 Sidekiq 后端的 ActiveJob 将复杂对象作为参数传递
【发布时间】:2020-01-25 05:26:17
【问题描述】:

Sidekiq worker 的参数应该是作者根据这个 wiki 的简单数据类型 (https://github.com/mperham/sidekiq/wiki/Best-Practices)

ActiveJob 的参数可以是复杂对象,这要归功于 Global ID (https://edgeguides.rubyonrails.org/active_job_basics.html#globalid)

ActiveJob 后端可以配置为使用 Sidekiq。

那么,当我将复杂对象传递给具有 Sidekiq 后端的 ActiveJob 工作者时,幕后会发生什么?我认为 Sidekiq 这次不会因为“无法正确地在转储/加载往返中幸存”而无法处理它。

【问题讨论】:

  • 你有什么问题?
  • @MarkMerritt 当我将复杂对象传递给以 Sidekiq 作为其后端的 ActiveJob 时,幕后实际发生了什么。
  • 我不确定“复杂对象”是什么意思...看来您应该将 id 传递给您的工作
  • 根据 wiki(问题上的链接),它不是字符串、整数、浮点数、布尔值、null(nil)、数组和散列。所以任何 ActiveRecord 对象、日期、日期时间等都被视为“复杂对象”
  • 是的,当我们使用 Sidekiq 只传递一个 ID 时,我也这么认为。但是 ActiveJob 明确表示可以传递一个实际的对象,而不仅仅是它的 id。结合 ActiveJob 和 Sidekiq 时,我的问题就出现了

标签: ruby-on-rails ruby sidekiq rails-activejob


【解决方案1】:

你可以通过#to_global_id找到模型的全局id:

gid = MyModel.first.to_global_id

gid.uri # => #<URI ...

gid.to_s # => "gid://..."

GlobalID::Locator.locate(gid) # => #<MyModel

GlobalID 的代码是here

它根据应用程序名称、模型类、模型 ID 和可选参数创建一个 URI。这是在GlobalID::URI::GID 中完成的。

您可以这样创建自己的 GID:

URI::GID.create('myapp', MyModel.first, database: 'my_app_development')
# => #<URI::GID gid://myapp/MyModel/1?database=my_app_development>

传递的模型必须是 ActiveRecord 投诉,因此传递 PORO(Plain Old Ruby Object)将不起作用:

class MyModel
end

URI::GID.create('myapp', MyModel.new)
# => NoMethodError (undefined method `id'

让我们添加一个 id 属性:

MyModel = Struct.new(:id)

gid = URI::GID.create('myapp', MyModel.new(1))
# => #<URI::GID gid://myapp/MyModel/1>

GlobalID::Locator.locate(gid)
# => NoMethodError (undefined method `find' for MyModel:Class)

还有一个类方法#find

MyModel = Struct.new(:id) do
  def self.find(id)
    new(id)
  end
end

gid = URI::GID.create('myapp', MyModel.new(1))

GlobalID::Locator.locate(gid)
# => #<struct MyModel id="1">

【讨论】:

    猜你喜欢
    • 2016-08-28
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多