Offer dependent: :destroy_async for associations - #40157
Conversation
0622f67 to
26ce831
Compare
aee646b to
66c4747
Compare
ee96146 to
c112d8e
Compare
c112d8e to
f6d41ec
Compare
Sometimes cascading association deletions can cause timeouts due to an IO issue. Perhaps a model has associations that are destroyed on deletion which in turn trigger other deletions and this can continue down a complex tree. Along this tree you may also hit other IO operations. Such deep deletions can lead to server timeouts while awaiting completion and really the user may not notice all the changes on their side immediately making them wait unnecesarially or worse causing a timeout during the operation. We now allow associations supporting the `dependent:` key to take `:destroy_async`, which schedules a background job to destroy associations. Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com> Co-authored-by: Rafael Mendonça França <rafael@franca.dev> Co-authored-by: Cory Gwin @gwincr11 <gwincr11@github.com>
f6d41ec to
4cf7559
Compare
|
This is awesome 👍 But just curious: why not use That seems more consistent with other delayed methods: Is there something about the behavior that makes |
| valid = super + [:counter_cache, :join_table, :index_errors, :ensuring_owner_was] | ||
| valid += [:as, :foreign_type] if options[:as] | ||
| valid += [:through, :source, :source_type] if options[:through] | ||
| valid += [:ensuring_owner_was] if options[:dependent] == :destroy_async |
There was a problem hiding this comment.
isn't it a duplicate with the addition 3 lines above?
There was a problem hiding this comment.
Yes, good catch @vendethiel ! Feel free to open a PR ❤️
|
|
||
| def self.valid_options(options) | ||
| valid = super + [:counter_cache, :join_table, :index_errors] | ||
| valid = super + [:counter_cache, :join_table, :index_errors, :ensuring_owner_was] |
There was a problem hiding this comment.
As @vendethiel said, here the key is always included, which invalidates line 13, no?
There was a problem hiding this comment.
As @adrianna-chang-shopify said, feel free to open a PR 🙂
There was a problem hiding this comment.
Here @eugeneius , could you review? @adrianna-chang-shopify
|
@rafaelfranca @adrianna-chang-shopify I don't want to be a pest 😅 but I think it would be useful for the community to understand why this option is named |
|
The reason for the different name if because we wanted to keep the For the feature implemented here we don't care if the destroy happen in 1s or in 10 minutes. It just need to happen async, without blocking the current request. So the behavior of |
Motivation:
- Now that destroy_async is an option on association, a natural next
step seems to be adding this method to standard objects for a more
consistent offering.
Related Issues:
- rails#40157
- rails#36912
Changes:
- Add a destroy_async method to persistence.
- Add a rail tie to setup the active job configs.
- Add a default destroy async job.
- Test
|
Would a PR to add |
|
@tomrossi7 👍 on And also thanks for this |

Revised version of #36912, #39149
Summary
Allows associations taking the
dependentkey to specifydependent: :destroy_async, which will enqueue a job to destroy associations asynchronously.cc @rafaelfranca - I've removed
ActiveRecord::Base.destroy_laterfrom this PR, so it only contains the implementation of the asynchronous association deletion. Will rebase + squash if it looks okay to you.