Account::Searchable#clear_search_records called
Search::Record.for(id).destroy_all which deleted every row in the
shard's table, wiping search records belonging to every other account
that happened to hash to the same shard.
ref: https://3.basecamp.com/2914079/buckets/27/card_tables/cards/9782824728
Account incineration could leave orphaned records due to missing cascade
declarations and async jobs failing when the account was already gone.
Cascade fixes:
- Add Account::Searchable concern to clean up Search::Query (delete_all)
and Search::Record (destroy_all, respects SQLite FTS dependent: :destroy)
- Add before_destroy in Account::Storage to delete storage entries
- Suppress storage entry recording during incineration so attachment
purge callbacks don't create entries or enqueue materialize jobs
- Guard Access#clean_inaccessible_data_later with unless user.destroyed?
to avoid enqueuing pointless jobs during user cascade
Job tenancy:
- Extract AccountTenanted concern from the global ActiveJob initializer
into ApplicationJob (include) with targeted prepends for
ActionMailer::MailDeliveryJob and Turbo broadcast jobs
- Defer account resolution from deserialize to perform so that missing
accounts raise DeserializationError inside the execution path where
discard_on can handle it
Tests:
- Comprehensive incineration test covering 35 model types with
before/after assertions and full enqueued job processing
- Mailer deliver_later test verifying account context survives job
serialization for multi-account users
- Turbo broadcast test verifying account-scoped URLs in rendered partials
* Add self-service account deletion
* Disable access to cancelled accounts & implement Stripe interactions
* Add tests
* Fix failing tests
* Remove cancelled accounts from lists
* Fix incorrect redirect
* Use _path instead of _url for consistency
* Don't track how far the inicieration job got
We still want the step tracking so that the job can be interrupted. But, since the scope is idempotent, we don't need to track how far it got.
* Specify the exact time when the data will be deleted
* Fix crash due to unadvancable cursor
* Rename up_for_incineration to due_for_incineration
* Regenrate the schema
* Fix incorrect path check
* Migrate the SQLite schema
* Only show the cancel button on cancellable accounts
* Check that a subscirption method exists before calling it
* Ignore job failures due to missing records when an account gets deleted
* Skip sending notifications on cancelled accounts
* Use collbacks to integrate
* Add a blank line between queue_as and discard_on
* Break checks into methods
* Inline methods
* Rename Account::IncinerateJob
* Run migrations
* Migrate SQLite