0
votes

Sidekiq worker's parameter should be simple data type according to this wiki by the author (https://github.com/mperham/sidekiq/wiki/Best-Practices)

ActiveJob's parameter can be complex object, thanks to Global ID (https://edgeguides.rubyonrails.org/active_job_basics.html#globalid)

ActiveJob backend can be configured to use Sidekiq.

So what happen behind the scene when I pass complex object to an ActiveJob worker with Sidekiq backend? I don't think Sidekiq will fail in processing it due to "will not survive the dump/load round trip correctly" this time.

1
What is your question?Mark Merritt
@MarkMerritt what is actually happening behind the scene when I pass complex object to ActiveJob with Sidekiq as its backend.Agung Setiawan
I'm not sure what a "complex object" means...It seems like you should just pass in the id to your jobMark Merritt
According to the wiki (link on the question) it's something other than string, integer, float, boolean, null(nil), array and hash. So any ActiveRecord object, Date, DateTime, etc considered "complex objects"Agung Setiawan
Yeah I think so too when we use Sidekiq to only pass an id. But ActiveJob clearly stated that it is possible to pass an actual object, not just its id. And my question arise when combining ActiveJob and SidekiqAgung Setiawan

1 Answers

1
votes

You can find the global id of a model with #to_global_id:

gid = MyModel.first.to_global_id

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

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

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

The code for GlobalID is here.

It creates a URI from the application name, model class, model id and optional params. This is done in GlobalID::URI::GID.

You can create you own GID as such:

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

The model passed must be ActiveRecord complaint, so passing a PORO (Plain Old Ruby Object) will not work:

class MyModel
end

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

Let's add an id attribute:

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)

And a class method #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">