Sylar Sylar - 3 months ago 24
Ruby Question

ActiveJob::SerializationError

I want to put a heavy lifting method into a background job. Rails 5 ActiveJob or the use of Redis. Not sure which one I should use.

Basically there will be an API that uses a gem and to stuff things from that API call to my local database.

Controller:

...

before_action :get_api

def do_later
GetApiJob.perform_later(foo)
# Call foo later
end

def foo
@apis.map do |api|
puts api.title
end
end

private
def get_api
@apis = ShopifyAPI::Product.find(:all)
end

...


GetApiJob:

...

queue_as :default

def perform(a)
a
# Expect to see a list, if any, of api's name
end

...


When I call
do_later
it will put
foo
into a background job. Doing that sample code, I get:


ActiveJob::SerializationError


Should I be using Sidekiq for this?

Answer

ActiveJob is just a common interface between Rails application and different background job runners. You cannot use ActiveJob alone, you still need to add sidekiq (and Redis) or delayed_job or something else.

ActiveJob does the serialization of passed arguments in your Rails application and then deseriales this on the background job side. But you cannot serialize anything, you can only serialize basic types like Fixnum, String, Float, arrays of those basic values, hashes or ActiveRecord objects. ActiveRecord objects are serialized using GlobalId.

In your case you are passing a collection returned from shopify api client, which is not an ActiveRecord collection and ActiveJob doesn't know how to serialize it.

It will be best if you move api call to the background job itself.

Controller

# No before_action

def do_later
  # No arguments, because we are fetching all products
  GetApiJob.perform_later
end

GetApiJob

queue_as :default

def perform
  # Fetch list of products
  products = ShopifyAPI::Product.find(:all)
  # Process list of products
end
Comments