Async callbacks as a first class citizen

Summary

We often create callbacks that only trigger a background job. It would be simpler if we could inline the logic for the background job in the model and just mark the callback as async. This would “collapse” the perceived complexity of the implementation, since we won’t need an additional background job class.

I’m not sure how do people feel about this? Would you consider this an anti pattern or a way to reduce boilerplate.

Example

In our codebase we have something along these lines:

class Recording < ApplicationRecord
  after_create_commit :process

  def process
    ProcessImportedRecordingJob.set(wait: 5.seconds).perform_later(self)
  end
end

It would be good if we could do something like this instead and have the same functionality:

class Recording < ApplicationRecord
  after_create_commit :process, async: true

  def process
    # Processing logic
  end
end

Potential Problems

The implementation might be tricky, since we’d need to either:

  1. Find a way to pass a proc or a block to a background job.
    • FWIW I don’t think this is easily solvable.
  2. Dynamically create a background job class and use that to execute the callback
    • This seems like the most viable solution
1 Like

While I understand the motivation, I’m a bit skeptical. It’s too abstract about what’s going on under the hood.

The implementation might be tricky

That implies it does too much under the hood. If we do that by ourselves:

class RecordingProcessJob < ApplicationJob
  def perform(recording_id)
    recording = Recording.find(recording_id)
    # Processing logic
  end
end

class RecordingController < ApplicationController
  def create
    recording = Recording.create!(recording_params)
    RecordingProcessJob.perform_later(recording.id)
  end
end

And essentially that’s it. The best thing about this is we know processing will be done in background because we have RecordingProcessJob class.

Check out Delayed Extensions of Sidekiq.

It was not specific for callbacks, but the idea is similar.

1 Like