about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2018-08-25 13:25:39 +0200
committerGitHub <noreply@github.com>2018-08-25 13:25:39 +0200
commit793eea29823a44fd4950f87898ecf0ff3b49351d (patch)
tree3b8f21b5d4fa500d50a3e014140166348c1c1e17
parentb4fc810bc34eb58e2c9e6c5abb2de2d6d9390a9b (diff)
Add improved CLI interface for removing remote media (#8411)
./bin/tootctl media remove --days 7 --background

Make the old rake task point to it
-rw-r--r--app/workers/maintenance/destroy_media_worker.rb2
-rw-r--r--app/workers/maintenance/redownload_account_media_worker.rb2
-rw-r--r--app/workers/maintenance/uncache_media_worker.rb2
-rwxr-xr-xbin/tootctl4
-rw-r--r--lib/cli.rb11
-rw-r--r--lib/mastodon/media_cli.rb47
-rw-r--r--lib/tasks/mastodon.rake11
7 files changed, 68 insertions, 11 deletions
diff --git a/app/workers/maintenance/destroy_media_worker.rb b/app/workers/maintenance/destroy_media_worker.rb
index 5f052983b..cde33d6d7 100644
--- a/app/workers/maintenance/destroy_media_worker.rb
+++ b/app/workers/maintenance/destroy_media_worker.rb
@@ -6,7 +6,7 @@ class Maintenance::DestroyMediaWorker
   sidekiq_options queue: 'pull'
 
   def perform(media_attachment_id)
-    media = MediaAttachment.find(media_attachment_id)
+    media = media_attachment_id.is_a?(MediaAttachment) ? media_attachment_id : MediaAttachment.find(media_attachment_id)
     media.destroy
   rescue ActiveRecord::RecordNotFound
     true
diff --git a/app/workers/maintenance/redownload_account_media_worker.rb b/app/workers/maintenance/redownload_account_media_worker.rb
index fc26815f2..6afbe6e19 100644
--- a/app/workers/maintenance/redownload_account_media_worker.rb
+++ b/app/workers/maintenance/redownload_account_media_worker.rb
@@ -6,7 +6,7 @@ class Maintenance::RedownloadAccountMediaWorker
   sidekiq_options queue: 'pull', retry: false
 
   def perform(account_id)
-    account = Account.find(account_id)
+    account = account_id.is_a?(Account) ? account_id : Account.find(account_id)
     account.reset_avatar!
     account.reset_header!
     account.save
diff --git a/app/workers/maintenance/uncache_media_worker.rb b/app/workers/maintenance/uncache_media_worker.rb
index 2d1a670a7..4bc62ef75 100644
--- a/app/workers/maintenance/uncache_media_worker.rb
+++ b/app/workers/maintenance/uncache_media_worker.rb
@@ -6,7 +6,7 @@ class Maintenance::UncacheMediaWorker
   sidekiq_options queue: 'pull'
 
   def perform(media_attachment_id)
-    media = MediaAttachment.find(media_attachment_id)
+    media = media_attachment_id.is_a?(MediaAttachment) ? media_attachment_id : MediaAttachment.find(media_attachment_id)
 
     return if media.file.blank?
 
diff --git a/bin/tootctl b/bin/tootctl
new file mode 100755
index 000000000..2fe02523a
--- /dev/null
+++ b/bin/tootctl
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+APP_PATH = File.expand_path('../config/application', __dir__)
+require_relative '../lib/cli'
+Mastodon::CLI.start(ARGV)
diff --git a/lib/cli.rb b/lib/cli.rb
new file mode 100644
index 000000000..7e82806b6
--- /dev/null
+++ b/lib/cli.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'thor'
+require_relative 'mastodon/media_cli'
+
+module Mastodon
+  class CLI < Thor
+    desc 'media SUBCOMMAND ...ARGS', 'manage media files'
+    subcommand 'media', Mastodon::MediaCLI
+  end
+end
diff --git a/lib/mastodon/media_cli.rb b/lib/mastodon/media_cli.rb
new file mode 100644
index 000000000..cc6ad07d9
--- /dev/null
+++ b/lib/mastodon/media_cli.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require_relative '../../config/boot'
+require_relative '../../config/environment'
+
+# rubocop:disable Rails/Output
+
+module Mastodon
+  class MediaCLI < Thor
+    option :days, type: :numeric, default: 7
+    option :background, type: :boolean, default: false
+    desc 'remove', 'remove remote media files'
+    long_desc <<-DESC
+      Removes locally cached copies of media attachments from other servers.
+
+      The --days option specifies how old media attachments have to be before
+      they are removed. It defaults to 7 days.
+
+      With the --background option, instead of deleting the files sequentially,
+      they will be queued into Sidekiq and the command will exit as soon as
+      possible. In Sidekiq they will be processed with higher concurrency, but
+      it may impact other operations of the Mastodon server, and it may overload
+      the underlying file storage.
+    DESC
+    def remove
+      time_ago = options[:days].days.ago
+      queued   = 0
+
+      MediaAttachment.where.not(remote_url: '').where.not(file_file_name: nil).where('created_at < ?', time_ago).select(:id).reorder(nil).find_in_batches do |media_attachments|
+        if options[:background]
+          queued += media_attachments.size
+          Maintenance::UncacheMediaWorker.push_bulk(media_attachments.map(&:id))
+        else
+          media_attachments.each do |m|
+            Maintenance::UncacheMediaWorker.new.perform(m)
+            print '.'
+          end
+        end
+      end
+
+      puts
+      puts "Scheduled the deletion of #{queued} media attachments" if options[:background]
+    end
+  end
+end
+
+# rubocop:enable Rails/Output
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index 191ce634c..9ce39335d 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -512,14 +512,9 @@ namespace :mastodon do
 
     desc 'Remove cached remote media attachments that are older than NUM_DAYS. By default 7 (week)'
     task remove_remote: :environment do
-      time_ago = ENV.fetch('NUM_DAYS') { 7 }.to_i.days.ago
-      nb_media_attachments = 0
-
-      MediaAttachment.where.not(remote_url: '').where.not(file_file_name: nil).where('created_at < ?', time_ago).select(:id).reorder(nil).find_in_batches do |media_attachments|
-        nb_media_attachments += media_attachments.length
-        Maintenance::UncacheMediaWorker.push_bulk(media_attachments.map(&:id))
-      end
-      puts "Scheduled the deletion of #{nb_media_attachments} media attachments"
+      require_relative '../mastodon/media_cli'
+      cli = Mastodon::MediaCLI.new([], days: ENV['NUM_DAYS'] || 7)
+      cli.invoke(:remove)
     end
 
     desc 'Set unknown attachment type for remote-only attachments'