Sig
Sig

Reputation: 5986

ActiveJob::DeserializationError in a after_create callback - Record Not Found

In a Rails 6 app, I have the following code.

class Reservation < ApplicationRecord
  after_create     :publish_creation

  def publish_creation
    Publishers::Reservations::CreateJob.perform_later(self)
  end
end

class Publishers::Reservations::CreateJob < ApplicationJob
  queue_as :default

  def perform(reservation)
    puts reservation.inspect #dummy code for testing
  end
end

The majority of times I create a Reservation (the record is always created in the DB), I get the error below

2020-02-14T09:54:03.707Z pid=81787 tid=1xmj WARN: ActiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn't find Reservation with 'id'= 35651cf7-35bc-4da0-bb0d-6285ac093d22

The first time Sidekiq retries to process the job, it always finds the Reservation and everything works fine.

Reservation id: "35651cf7-35bc-4da0-bb0d-6285ac093d22", analysis_id: "6b3b167b-1279-49c0-991a-b580c375fd0f", reservable_type: "User", reservable_id: "94f60c16-29d4-4372-983b-7544c393a7e6", reserved_between: 2020-02-10 08:00:00 UTC..2020-02-10 08:10:00 UTC, state: "scheduled", created_at: "2020-02-14 10:02:28", updated_at: "2020-02-14 10:02:28"

Am I missing anything here? Is this something related to the fact I'm running in development mode and it should disappear once I move to production?

Upvotes: 6

Views: 1497

Answers (2)

Roko
Roko

Reputation: 1335

At Rails 5+ you can use after_create_commit (docs)

It will run after the create transaction so the record will already be created, but unlike after_commit it will only run after create, not after update nor destroy.

It's an alias for: after_commit :your_callback, on: :create

Upvotes: 3

Gautam
Gautam

Reputation: 1812

You should use after_commit instead of after_create. This is because

after_create - Is called after Model.save on new objects that haven‘t been saved yet (no record exists). In the case of after_create, this will always be before the call to save (or create) returns. Rails wraps every save inside a transaction and the before/after create callbacks run inside that transaction.

after_commit - Is called after the database transaction is completed. With after_commit, your code doesn't run until after the outermost transaction was committed.

Upvotes: 16

Related Questions