Add SELF_DESTRUCT env variable to process self-destructions in the background (#26439)
This commit is contained in:
parent
26d2a2a0cc
commit
379115e601
22 changed files with 193 additions and 57 deletions
|
@ -65,7 +65,6 @@ module Mastodon::CLI
|
|||
desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities'
|
||||
subcommand 'maintenance', Maintenance
|
||||
|
||||
option :dry_run, type: :boolean
|
||||
desc 'self-destruct', 'Erase the server from the federation'
|
||||
long_desc <<~LONG_DESC
|
||||
Erase the server from the federation by broadcasting account delete
|
||||
|
@ -92,55 +91,37 @@ module Mastodon::CLI
|
|||
|
||||
prompt = TTY::Prompt.new
|
||||
|
||||
exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain
|
||||
if SelfDestructHelper.self_destruct?
|
||||
prompt.ok('Self-destruct mode is already enabled for this Mastodon server')
|
||||
|
||||
unless dry_run?
|
||||
prompt.warn('This operation WILL NOT be reversible. It can also take a long time.')
|
||||
prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.')
|
||||
prompt.warn('A running Sidekiq process is required. Do not shut it down until queues clear.')
|
||||
pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count
|
||||
sidekiq_stats = Sidekiq::Stats.new
|
||||
|
||||
exit(1) if prompt.no?('Are you sure you want to proceed?')
|
||||
end
|
||||
|
||||
inboxes = Account.inboxes
|
||||
processed = 0
|
||||
|
||||
Setting.registrations_mode = 'none' unless dry_run?
|
||||
|
||||
if inboxes.empty?
|
||||
Account.local.without_suspended.in_batches.update_all(suspended_at: Time.now.utc, suspension_origin: :local) unless dry_run?
|
||||
prompt.ok('It seems like your server has not federated with anything')
|
||||
prompt.ok('You can shut it down and delete it any time')
|
||||
return
|
||||
end
|
||||
|
||||
prompt.warn('Do NOT interrupt this process...')
|
||||
|
||||
delete_account = lambda do |account|
|
||||
payload = ActiveModelSerializers::SerializableResource.new(
|
||||
account,
|
||||
serializer: ActivityPub::DeleteActorSerializer,
|
||||
adapter: ActivityPub::Adapter
|
||||
).as_json
|
||||
|
||||
json = Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(account))
|
||||
|
||||
unless dry_run?
|
||||
ActivityPub::DeliveryWorker.push_bulk(inboxes, limit: 1_000) do |inbox_url|
|
||||
[json, account.id, inbox_url]
|
||||
end
|
||||
|
||||
account.suspend!(block_email: false)
|
||||
if pending_accounts.positive?
|
||||
prompt.warn("#{pending_accounts} accounts are still pending deletion.")
|
||||
elsif sidekiq_stats.enqueued.positive?
|
||||
prompt.warn('Deletion notices are still being processed')
|
||||
elsif sidekiq_stats.retry_size.positive?
|
||||
prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry')
|
||||
else
|
||||
prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!')
|
||||
end
|
||||
|
||||
processed += 1
|
||||
exit(0)
|
||||
end
|
||||
|
||||
Account.local.without_suspended.find_each { |account| delete_account.call(account) }
|
||||
Account.local.suspended.joins(:deletion_request).find_each { |account| delete_account.call(account) }
|
||||
exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain
|
||||
|
||||
prompt.ok("Queued #{inboxes.size * processed} items into Sidekiq for #{processed} accounts#{dry_run_mode_suffix}")
|
||||
prompt.ok('Wait until Sidekiq processes all items, then you can shut everything down and delete the data')
|
||||
prompt.warn('This operation WILL NOT be reversible.')
|
||||
prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.')
|
||||
prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).')
|
||||
|
||||
exit(1) if prompt.no?('Are you sure you want to proceed?')
|
||||
|
||||
self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain)
|
||||
prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:')
|
||||
prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}")
|
||||
prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.")
|
||||
rescue TTY::Reader::InputInterrupt
|
||||
exit(1)
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue