5

I have a couple models with many children. Dependent destroy has gotten really heavy. Anyone know of a way to tie dependent destroy into active jobs? Or, is my only option to remove dependent destroy and role my own jobs via callbacks on the parent model?

hellion
  • 4,602
  • 6
  • 38
  • 77
  • have you considered marking your models as destroyed and actually delete them from the database async? – phoet Mar 21 '15 at 10:56
  • You mean queuing children for destroy in a job? That's what I'm working on. ActiveJob is fairly new...maybe someday there will be a rails way to handle dependent: :destroy async with a simple association option. For now, I am queuing each child model for destroy and using the orphaned parent_id as the tag. – hellion Mar 21 '15 at 15:34
  • 2
    i usually don't delete records from the database as delete operations don't scale well. most of the time it's cheaper to just mark records deleted and leave them there. – phoet Mar 21 '15 at 15:36

3 Answers3

5

You can create a worker to destroy the models async and enqueue it's deletion. Something like:

class ComplexModelDeletion < ActiveJob::Base
  def perform(model)
    model.destroy!
  end
end

And the model could be something like:

class Model < ActiveRecord::Base
  def destroy_later
    ComplexModelDeletion.enqueue(self)
  end
end

Then, whenever you need to kill an instance of this model, you could call Model#destroy_later to enqueue it. You could even mark the object as deleted before enqueuing it just to prevent it from being retrieve from DB before it is actually killed.

Not sure if this would work as is, but just to give you an idea of what you could do.

lsdr
  • 1,245
  • 1
  • 15
  • 28
2

Rails does not do this natively. However, this gem does a good job of fixing N+1s related to dependent: :destroy. It actually uses dependent: :delete_all, but uses it in such a way that all sub classes are deleted too. And, it does it using only 2 hits to the DB per class. I can't believe functionality like this isn't wrapped into rails core. https://github.com/jisaacks/recurse-delete

hellion
  • 4,602
  • 6
  • 38
  • 77
1

With v6.1.0, Rails now has native support. You can add a dependent: :destroy_async to the relation and rails will handle deletion in the background. See weblog here - https://weblog.rubyonrails.org/2020/10/3/this-week-in-rails-destroying-associations-asynchronously-interval-datatype-and-more/

justcode
  • 399
  • 1
  • 4
  • 16