diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/exceptions.rb | 1 | ||||
-rw-r--r-- | lib/mastodon/maintenance_cli.rb | 28 | ||||
-rw-r--r-- | lib/tasks/mastodon.rake | 35 |
3 files changed, 57 insertions, 7 deletions
diff --git a/lib/exceptions.rb b/lib/exceptions.rb index 3c5ba226b..d3b92f4a0 100644 --- a/lib/exceptions.rb +++ b/lib/exceptions.rb @@ -11,6 +11,7 @@ module Mastodon class RaceConditionError < Error; end class RateLimitExceededError < Error; end class SyntaxError < Error; end + class InvalidParameterError < Error; end class UnexpectedResponseError < Error attr_reader :response diff --git a/lib/mastodon/maintenance_cli.rb b/lib/mastodon/maintenance_cli.rb index 6e5242bff..85937da81 100644 --- a/lib/mastodon/maintenance_cli.rb +++ b/lib/mastodon/maintenance_cli.rb @@ -14,7 +14,7 @@ module Mastodon end MIN_SUPPORTED_VERSION = 2019_10_01_213028 # rubocop:disable Style/NumericLiterals - MAX_SUPPORTED_VERSION = 2022_03_16_233212 # rubocop:disable Style/NumericLiterals + MAX_SUPPORTED_VERSION = 2022_11_04_133904 # rubocop:disable Style/NumericLiterals # Stubs to enjoy ActiveRecord queries while not depending on a particular # version of the code/database @@ -45,6 +45,7 @@ module Mastodon class FollowRecommendationSuppression < ApplicationRecord; end class CanonicalEmailBlock < ApplicationRecord; end class Appeal < ApplicationRecord; end + class Webhook < ApplicationRecord; end class PreviewCard < ApplicationRecord self.inheritance_column = false @@ -182,6 +183,7 @@ module Mastodon deduplicate_accounts! deduplicate_tags! deduplicate_webauthn_credentials! + deduplicate_webhooks! Scenic.database.refresh_materialized_view('instances', concurrently: true, cascade: false) if ActiveRecord::Migrator.current_version >= 2020_12_06_004238 Rails.cache.clear @@ -497,6 +499,7 @@ module Mastodon def deduplicate_tags! remove_index_if_exists!(:tags, 'index_tags_on_name_lower') + remove_index_if_exists!(:tags, 'index_tags_on_name_lower_btree') @prompt.say 'Deduplicating tags…' ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM tags GROUP BY lower((name)::text) HAVING count(*) > 1").each do |row| @@ -509,11 +512,10 @@ module Mastodon end @prompt.say 'Restoring tags indexes…' - ActiveRecord::Base.connection.add_index :tags, 'lower((name)::text)', name: 'index_tags_on_name_lower', unique: true - - if ActiveRecord::Base.connection.indexes(:tags).any? { |i| i.name == 'index_tags_on_name_lower_btree' } - @prompt.say 'Reindexing textual indexes on tags…' - ActiveRecord::Base.connection.execute('REINDEX INDEX index_tags_on_name_lower_btree;') + if ActiveRecord::Migrator.current_version < 20210421121431 + ActiveRecord::Base.connection.add_index :tags, 'lower((name)::text)', name: 'index_tags_on_name_lower', unique: true + else + ActiveRecord::Base.connection.execute 'CREATE UNIQUE INDEX CONCURRENTLY index_tags_on_name_lower_btree ON tags (lower(name) text_pattern_ops)' end end @@ -531,6 +533,20 @@ module Mastodon ActiveRecord::Base.connection.add_index :webauthn_credentials, ['external_id'], name: 'index_webauthn_credentials_on_external_id', unique: true end + def deduplicate_webhooks! + return unless ActiveRecord::Base.connection.table_exists?(:webhooks) + + remove_index_if_exists!(:webhooks, 'index_webhooks_on_url') + + @prompt.say 'Deduplicating webhooks…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM webhooks GROUP BY url HAVING count(*) > 1").each do |row| + Webhooks.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring webhooks indexes…' + ActiveRecord::Base.connection.add_index :webhooks, ['url'], name: 'index_webhooks_on_url', unique: true + end + def deduplicate_local_accounts!(accounts) accounts = accounts.sort_by(&:id).reverse diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 3ec685c74..c1e5bd2b4 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -142,7 +142,40 @@ namespace :mastodon do prompt.say "\n" if prompt.yes?('Do you want to store uploaded files on the cloud?', default: false) - case prompt.select('Provider', ['Amazon S3', 'Wasabi', 'Minio', 'Google Cloud Storage']) + case prompt.select('Provider', ['DigitalOcean Spaces', 'Amazon S3', 'Wasabi', 'Minio', 'Google Cloud Storage']) + when 'DigitalOcean Spaces' + env['S3_ENABLED'] = 'true' + env['S3_PROTOCOL'] = 'https' + + env['S3_BUCKET'] = prompt.ask('Space name:') do |q| + q.required true + q.default "files.#{env['LOCAL_DOMAIN']}" + q.modify :strip + end + + env['S3_REGION'] = prompt.ask('Space region:') do |q| + q.required true + q.default 'nyc3' + q.modify :strip + end + + env['S3_HOSTNAME'] = prompt.ask('Space endpoint:') do |q| + q.required true + q.default 'nyc3.digitaloceanspaces.com' + q.modify :strip + end + + env['S3_ENDPOINT'] = "https://#{env['S3_HOSTNAME']}" + + env['AWS_ACCESS_KEY_ID'] = prompt.ask('Space access key:') do |q| + q.required true + q.modify :strip + end + + env['AWS_SECRET_ACCESS_KEY'] = prompt.ask('Space secret key:') do |q| + q.required true + q.modify :strip + end when 'Amazon S3' env['S3_ENABLED'] = 'true' env['S3_PROTOCOL'] = 'https' |