Sylar
Sylar

Reputation: 12092

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?

Upvotes: 0

Views: 5357

Answers (1)

Michał Młoźniak
Michał Młoźniak

Reputation: 5556

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

Upvotes: 3

Related Questions