rails/actionmailbox

Replace custom Incineratable concern with generic Active Record DestroyLater concern

Opened this issue · 1 comments

dhh commented

I'd like to see a generic way to manage record lifetimes in Active Record, which we could both use for Action Mailbox, but also directly in applications. Here's what I have in mind:

module ActiveRecord::DestroyLater
  extend ActiveSupport::Concern

  class_methoods do
    def destroy_later(after:, ensuring: nil, **options)
      after_commit -> { destroy_later after: after, ensuring: ensuring },
       on: options[:if] ? %i[ create update ] : :create, 
       if: options[:if]
    end
  end

  def destroy_later(after:, ensuring: nil)
    ActiveRecord::DestroyLaterJob.set(wait: after).perform_later(self, ensuring)
  end
end

class ActiveRecord::DestroyLaterJob < ActiveJob::Base
  queue_as :active_record_destroy_later

  discard_on ActiveRecord::RecordNotFound

  def perform(record, ensuring = nil)
    record.destroy! if eligible?(record, ensuring)
  end

  private
    def eligible?(record, ensuring)
      !ensuring || (ensuring && record.public_send(ensuring))
    end
end

Then we could replace all of the Incineratable gear with:

class ActionMailbox:InboundEmail
  # Will be destroyed 30.days after the status changed to processed?
  # (and we'll ensure that the record is still processed? after those 30 days, before destroying)
  destroy_later after: 30.days, if: -> { status_changed? && processed? }, ensuring: :processed?
end

And would also allow TTL usage like this:

class Session
  # Will simply be destroyed 30 days after it was created
  destroy_later after: 30.days
end

@georgeclaghorn, is this something you want to take a look at?

Yes! I’ll take a look soon.