aboutsummaryrefslogtreecommitdiff
path: root/app/workers
diff options
context:
space:
mode:
Diffstat (limited to 'app/workers')
-rw-r--r--app/workers/account_deletion_worker.rb15
-rw-r--r--app/workers/account_merging_worker.rb18
-rw-r--r--app/workers/activitypub/delivery_worker.rb10
-rw-r--r--app/workers/activitypub/distribution_worker.rb2
-rw-r--r--app/workers/activitypub/followers_synchronization_worker.rb14
-rw-r--r--app/workers/admin/account_deletion_worker.rb13
-rw-r--r--app/workers/admin/suspension_worker.rb6
-rw-r--r--app/workers/admin/unsuspension_worker.rb13
-rw-r--r--app/workers/authorize_follow_worker.rb2
-rw-r--r--app/workers/cache_buster_worker.rb18
-rw-r--r--app/workers/delete_mute_worker.rb10
-rw-r--r--app/workers/feed_insert_worker.rb24
-rw-r--r--app/workers/import/relationship_worker.rb6
-rw-r--r--app/workers/local_notification_worker.rb4
-rw-r--r--app/workers/merge_worker.rb4
-rw-r--r--app/workers/mute_worker.rb7
-rw-r--r--app/workers/poll_expiration_notify_worker.rb6
-rw-r--r--app/workers/refollow_worker.rb3
-rw-r--r--app/workers/scheduler/feed_cleanup_scheduler.rb30
-rw-r--r--app/workers/scheduler/instance_refresh_scheduler.rb11
-rw-r--r--app/workers/scheduler/ip_cleanup_scheduler.rb18
-rw-r--r--app/workers/scheduler/user_cleanup_scheduler.rb13
-rw-r--r--app/workers/unfollow_follow_worker.rb5
-rw-r--r--app/workers/unmerge_worker.rb4
24 files changed, 201 insertions, 55 deletions
diff --git a/app/workers/account_deletion_worker.rb b/app/workers/account_deletion_worker.rb
new file mode 100644
index 000000000..fdf013e01
--- /dev/null
+++ b/app/workers/account_deletion_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AccountDeletionWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: 'pull', lock: :until_executed
+
+ def perform(account_id, options = {})
+ reserve_username = options.with_indifferent_access.fetch(:reserve_username, true)
+ skip_activitypub = options.with_indifferent_access.fetch(:skip_activitypub, false)
+ DeleteAccountService.new.call(Account.find(account_id), reserve_username: reserve_username, skip_activitypub: skip_activitypub, reserve_email: false)
+ rescue ActiveRecord::RecordNotFound
+ true
+ end
+end
diff --git a/app/workers/account_merging_worker.rb b/app/workers/account_merging_worker.rb
new file mode 100644
index 000000000..8c234e7ac
--- /dev/null
+++ b/app/workers/account_merging_worker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AccountMergingWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: 'pull'
+
+ def perform(account_id)
+ account = Account.find(account_id)
+
+ return true if account.nil? || account.local?
+
+ Account.where(uri: account.uri).where.not(id: account.id).find_each do |duplicate|
+ account.merge_with!(duplicate)
+ duplicate.destroy
+ end
+ end
+end
diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb
index 60775787a..6c5a576a7 100644
--- a/app/workers/activitypub/delivery_worker.rb
+++ b/app/workers/activitypub/delivery_worker.rb
@@ -2,6 +2,7 @@
class ActivityPub::DeliveryWorker
include Sidekiq::Worker
+ include RoutingHelper
include JsonLdHelper
STOPLIGHT_FAILURE_THRESHOLD = 10
@@ -38,9 +39,18 @@ class ActivityPub::DeliveryWorker
Request.new(:post, @inbox_url, body: @json, http_client: http_client).tap do |request|
request.on_behalf_of(@source_account, :uri, sign_with: @options[:sign_with])
request.add_headers(HEADERS)
+ request.add_headers({ 'Collection-Synchronization' => synchronization_header }) if ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] != 'true' && @options[:synchronize_followers]
end
end
+ def synchronization_header
+ "collectionId=\"#{account_followers_url(@source_account)}\", digest=\"#{@source_account.remote_followers_hash(inbox_url_prefix)}\", url=\"#{account_followers_synchronization_url(@source_account)}\""
+ end
+
+ def inbox_url_prefix
+ @inbox_url[/http(s?):\/\/[^\/]+\//]
+ end
+
def perform_request
light = Stoplight(@inbox_url) do
request_pool.with(@host) do |http_client|
diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb
index 3f6d7408a..4aca443b2 100644
--- a/app/workers/activitypub/distribution_worker.rb
+++ b/app/workers/activitypub/distribution_worker.rb
@@ -45,7 +45,7 @@ class ActivityPub::DistributionWorker
def deliver_to_inboxes!
ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
- [payload, @account.id, inbox_url]
+ [payload, @account.id, inbox_url, { synchronize_followers: !@status.distributable? }]
end
end
diff --git a/app/workers/activitypub/followers_synchronization_worker.rb b/app/workers/activitypub/followers_synchronization_worker.rb
new file mode 100644
index 000000000..35a3ef0b9
--- /dev/null
+++ b/app/workers/activitypub/followers_synchronization_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class ActivityPub::FollowersSynchronizationWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: 'push', lock: :until_executed
+
+ def perform(account_id, url)
+ @account = Account.find_by(id: account_id)
+ return true if @account.nil?
+
+ ActivityPub::SynchronizeFollowersService.new.call(@account, url)
+ end
+end
diff --git a/app/workers/admin/account_deletion_worker.rb b/app/workers/admin/account_deletion_worker.rb
new file mode 100644
index 000000000..82f269ad6
--- /dev/null
+++ b/app/workers/admin/account_deletion_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class Admin::AccountDeletionWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: 'pull'
+
+ def perform(account_id)
+ DeleteAccountService.new.call(Account.find(account_id), reserve_username: true, reserve_email: true)
+ rescue ActiveRecord::RecordNotFound
+ true
+ end
+end
diff --git a/app/workers/admin/suspension_worker.rb b/app/workers/admin/suspension_worker.rb
index 83c815efd..35c570336 100644
--- a/app/workers/admin/suspension_worker.rb
+++ b/app/workers/admin/suspension_worker.rb
@@ -5,7 +5,9 @@ class Admin::SuspensionWorker
sidekiq_options queue: 'pull'
- def perform(account_id, remove_user = false)
- SuspendAccountService.new.call(Account.find(account_id), reserve_username: true, reserve_email: !remove_user)
+ def perform(account_id)
+ SuspendAccountService.new.call(Account.find(account_id))
+ rescue ActiveRecord::RecordNotFound
+ true
end
end
diff --git a/app/workers/admin/unsuspension_worker.rb b/app/workers/admin/unsuspension_worker.rb
new file mode 100644
index 000000000..7cb2349b1
--- /dev/null
+++ b/app/workers/admin/unsuspension_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class Admin::UnsuspensionWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: 'pull'
+
+ def perform(account_id)
+ UnsuspendAccountService.new.call(Account.find(account_id))
+ rescue ActiveRecord::RecordNotFound
+ true
+ end
+end
diff --git a/app/workers/authorize_follow_worker.rb b/app/workers/authorize_follow_worker.rb
index 0d5014624..f57900fa5 100644
--- a/app/workers/authorize_follow_worker.rb
+++ b/app/workers/authorize_follow_worker.rb
@@ -7,7 +7,7 @@ class AuthorizeFollowWorker
source_account = Account.find(source_account_id)
target_account = Account.find(target_account_id)
- AuthorizeFollowService.new.call(source_account, target_account)
+ AuthorizeFollowService.new.call(source_account, target_account, bypass_limit: true)
rescue ActiveRecord::RecordNotFound
true
end
diff --git a/app/workers/cache_buster_worker.rb b/app/workers/cache_buster_worker.rb
new file mode 100644
index 000000000..5ad0a44cb
--- /dev/null
+++ b/app/workers/cache_buster_worker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CacheBusterWorker
+ include Sidekiq::Worker
+ include RoutingHelper
+
+ sidekiq_options queue: 'pull'
+
+ def perform(path)
+ cache_buster.bust(full_asset_url(path))
+ end
+
+ private
+
+ def cache_buster
+ CacheBuster.new(Rails.configuration.x.cache_buster)
+ end
+end
diff --git a/app/workers/delete_mute_worker.rb b/app/workers/delete_mute_worker.rb
new file mode 100644
index 000000000..eb031020e
--- /dev/null
+++ b/app/workers/delete_mute_worker.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class DeleteMuteWorker
+ include Sidekiq::Worker
+
+ def perform(mute_id)
+ mute = Mute.find_by(id: mute_id)
+ UnmuteService.new.call(mute.account, mute.target_account) if mute&.expired?
+ end
+end
diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb
index 1ae3c877b..b70c7e389 100644
--- a/app/workers/feed_insert_worker.rb
+++ b/app/workers/feed_insert_worker.rb
@@ -23,13 +23,25 @@ class FeedInsertWorker
private
def check_and_insert
- perform_push unless feed_filtered?
+ return if feed_filtered?
+
+ perform_push
+ perform_notify if notify?
end
def feed_filtered?
- # Note: Lists are a variation of home, so the filtering rules
- # of home apply to both
- FeedManager.instance.filter?(:home, @status, @follower.id)
+ case @type
+ when :home
+ FeedManager.instance.filter?(:home, @status, @follower)
+ when :list
+ FeedManager.instance.filter?(:list, @status, @list)
+ end
+ end
+
+ def notify?
+ return false if @type != :home || @status.reblog? || (@status.reply? && @status.in_reply_to_account_id != @status.account_id)
+
+ Follow.find_by(account: @follower, target_account: @status.account)&.notify?
end
def perform_push
@@ -40,4 +52,8 @@ class FeedInsertWorker
FeedManager.instance.push_to_list(@list, @status)
end
end
+
+ def perform_notify
+ NotifyService.new.call(@follower, :status, @status)
+ end
end
diff --git a/app/workers/import/relationship_worker.rb b/app/workers/import/relationship_worker.rb
index 4a455f3ae..4a7100435 100644
--- a/app/workers/import/relationship_worker.rb
+++ b/app/workers/import/relationship_worker.rb
@@ -15,7 +15,11 @@ class Import::RelationshipWorker
case relationship
when 'follow'
- FollowService.new.call(from_account, target_account, options)
+ begin
+ FollowService.new.call(from_account, target_account, options)
+ rescue ActiveRecord::RecordInvalid
+ raise if FollowLimitValidator.limit_for_account(from_account) < from_account.following_count
+ end
when 'unfollow'
UnfollowService.new.call(from_account, target_account)
when 'block'
diff --git a/app/workers/local_notification_worker.rb b/app/workers/local_notification_worker.rb
index 48635e498..6b08ca6fc 100644
--- a/app/workers/local_notification_worker.rb
+++ b/app/workers/local_notification_worker.rb
@@ -3,7 +3,7 @@
class LocalNotificationWorker
include Sidekiq::Worker
- def perform(receiver_account_id, activity_id = nil, activity_class_name = nil)
+ def perform(receiver_account_id, activity_id = nil, activity_class_name = nil, type = nil)
if activity_id.nil? && activity_class_name.nil?
activity = Mention.find(receiver_account_id)
receiver = activity.account
@@ -12,7 +12,7 @@ class LocalNotificationWorker
activity = activity_class_name.constantize.find(activity_id)
end
- NotifyService.new.call(receiver, activity)
+ NotifyService.new.call(receiver, type || activity_class_name.underscore, activity)
rescue ActiveRecord::RecordNotFound
true
end
diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb
index d745cb99c..74ef7d4da 100644
--- a/app/workers/merge_worker.rb
+++ b/app/workers/merge_worker.rb
@@ -6,6 +6,8 @@ class MergeWorker
sidekiq_options queue: 'pull'
def perform(from_account_id, into_account_id)
- FeedManager.instance.merge_into_timeline(Account.find(from_account_id), Account.find(into_account_id))
+ FeedManager.instance.merge_into_home(Account.find(from_account_id), Account.find(into_account_id))
+ rescue ActiveRecord::RecordNotFound
+ true
end
end
diff --git a/app/workers/mute_worker.rb b/app/workers/mute_worker.rb
index 7bf0923a5..c74f657cb 100644
--- a/app/workers/mute_worker.rb
+++ b/app/workers/mute_worker.rb
@@ -4,9 +4,8 @@ class MuteWorker
include Sidekiq::Worker
def perform(account_id, target_account_id)
- FeedManager.instance.clear_from_timeline(
- Account.find(account_id),
- Account.find(target_account_id)
- )
+ FeedManager.instance.clear_from_home(Account.find(account_id), Account.find(target_account_id))
+ rescue ActiveRecord::RecordNotFound
+ true
end
end
diff --git a/app/workers/poll_expiration_notify_worker.rb b/app/workers/poll_expiration_notify_worker.rb
index 64b4cbd7e..f0191d479 100644
--- a/app/workers/poll_expiration_notify_worker.rb
+++ b/app/workers/poll_expiration_notify_worker.rb
@@ -11,12 +11,12 @@ class PollExpirationNotifyWorker
# Notify poll owner and remote voters
if poll.local?
ActivityPub::DistributePollUpdateWorker.perform_async(poll.status.id)
- NotifyService.new.call(poll.account, poll)
+ NotifyService.new.call(poll.account, :poll, poll)
end
# Notify local voters
- poll.votes.includes(:account).map(&:account).select(&:local?).each do |account|
- NotifyService.new.call(account, poll)
+ poll.votes.includes(:account).group(:account_id).select(:account_id).map(&:account).select(&:local?).each do |account|
+ NotifyService.new.call(account, :poll, poll)
end
rescue ActiveRecord::RecordNotFound
true
diff --git a/app/workers/refollow_worker.rb b/app/workers/refollow_worker.rb
index 9b07ce1b5..319b00109 100644
--- a/app/workers/refollow_worker.rb
+++ b/app/workers/refollow_worker.rb
@@ -11,6 +11,7 @@ class RefollowWorker
target_account.passive_relationships.where(account: Account.where(domain: nil)).includes(:account).reorder(nil).find_each do |follow|
reblogs = follow.show_reblogs?
+ notify = follow.notify?
# Locally unfollow remote account
follower = follow.account
@@ -18,7 +19,7 @@ class RefollowWorker
# Schedule re-follow
begin
- FollowService.new.call(follower, target_account, reblogs: reblogs)
+ FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, bypass_limit: true)
rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError
next
end
diff --git a/app/workers/scheduler/feed_cleanup_scheduler.rb b/app/workers/scheduler/feed_cleanup_scheduler.rb
index 458fe6193..42b29f4ec 100644
--- a/app/workers/scheduler/feed_cleanup_scheduler.rb
+++ b/app/workers/scheduler/feed_cleanup_scheduler.rb
@@ -14,37 +14,11 @@ class Scheduler::FeedCleanupScheduler
private
def clean_home_feeds!
- clean_feeds!(inactive_account_ids, :home)
+ feed_manager.clean_feeds!(:home, inactive_account_ids)
end
def clean_list_feeds!
- clean_feeds!(inactive_list_ids, :list)
- end
-
- def clean_feeds!(ids, type)
- reblogged_id_sets = {}
-
- redis.pipelined do
- ids.each do |feed_id|
- redis.del(feed_manager.key(type, feed_id))
- reblog_key = feed_manager.key(type, feed_id, 'reblogs')
- # We collect a future for this: we don't block while getting
- # it, but we can iterate over it later.
- reblogged_id_sets[feed_id] = redis.zrange(reblog_key, 0, -1)
- redis.del(reblog_key)
- end
- end
-
- # Remove all of the reblog tracking keys we just removed the
- # references to.
- redis.pipelined do
- reblogged_id_sets.each do |feed_id, future|
- future.value.each do |reblogged_id|
- reblog_set_key = feed_manager.key(type, feed_id, "reblogs:#{reblogged_id}")
- redis.del(reblog_set_key)
- end
- end
- end
+ feed_manager.clean_feeds!(:list, inactive_list_ids)
end
def inactive_account_ids
diff --git a/app/workers/scheduler/instance_refresh_scheduler.rb b/app/workers/scheduler/instance_refresh_scheduler.rb
new file mode 100644
index 000000000..917404bec
--- /dev/null
+++ b/app/workers/scheduler/instance_refresh_scheduler.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class Scheduler::InstanceRefreshScheduler
+ include Sidekiq::Worker
+
+ sidekiq_options lock: :until_executed, retry: 0
+
+ def perform
+ Instance.refresh
+ end
+end
diff --git a/app/workers/scheduler/ip_cleanup_scheduler.rb b/app/workers/scheduler/ip_cleanup_scheduler.rb
index 6d38b52a2..853f20e25 100644
--- a/app/workers/scheduler/ip_cleanup_scheduler.rb
+++ b/app/workers/scheduler/ip_cleanup_scheduler.rb
@@ -3,13 +3,23 @@
class Scheduler::IpCleanupScheduler
include Sidekiq::Worker
- RETENTION_PERIOD = 1.year
+ IP_RETENTION_PERIOD = 1.year.freeze
sidekiq_options lock: :until_executed, retry: 0
def perform
- time_ago = RETENTION_PERIOD.ago
- SessionActivation.where('updated_at < ?', time_ago).in_batches.destroy_all
- User.where('last_sign_in_at < ?', time_ago).where.not(last_sign_in_ip: nil).in_batches.update_all(last_sign_in_ip: nil)
+ clean_ip_columns!
+ clean_expired_ip_blocks!
+ end
+
+ private
+
+ def clean_ip_columns!
+ SessionActivation.where('updated_at < ?', IP_RETENTION_PERIOD.ago).in_batches.destroy_all
+ User.where('current_sign_in_at < ?', IP_RETENTION_PERIOD.ago).in_batches.update_all(last_sign_in_ip: nil, current_sign_in_ip: nil, sign_up_ip: nil)
+ end
+
+ def clean_expired_ip_blocks!
+ IpBlock.expired.in_batches.destroy_all
end
end
diff --git a/app/workers/scheduler/user_cleanup_scheduler.rb b/app/workers/scheduler/user_cleanup_scheduler.rb
index 6113edde1..8571b59e1 100644
--- a/app/workers/scheduler/user_cleanup_scheduler.rb
+++ b/app/workers/scheduler/user_cleanup_scheduler.rb
@@ -6,9 +6,22 @@ class Scheduler::UserCleanupScheduler
sidekiq_options lock: :until_executed, retry: 0
def perform
+ clean_unconfirmed_accounts!
+ clean_suspended_accounts!
+ end
+
+ private
+
+ def clean_unconfirmed_accounts!
User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch|
Account.where(id: batch.map(&:account_id)).delete_all
User.where(id: batch.map(&:id)).delete_all
end
end
+
+ def clean_suspended_accounts!
+ AccountDeletionRequest.where('created_at <= ?', AccountDeletionRequest::DELAY_TO_DELETION.ago).reorder(nil).find_each do |deletion_request|
+ Admin::AccountDeletionWorker.perform_async(deletion_request.account_id)
+ end
+ end
end
diff --git a/app/workers/unfollow_follow_worker.rb b/app/workers/unfollow_follow_worker.rb
index b6e665a41..0bd5ff472 100644
--- a/app/workers/unfollow_follow_worker.rb
+++ b/app/workers/unfollow_follow_worker.rb
@@ -10,10 +10,11 @@ class UnfollowFollowWorker
old_target_account = Account.find(old_target_account_id)
new_target_account = Account.find(new_target_account_id)
- follow = follower_account.active_relationships.find_by(target_account: old_target_account)
+ follow = follower_account.active_relationships.find_by(target_account: old_target_account)
reblogs = follow&.show_reblogs?
+ notify = follow&.notify?
- FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, bypass_locked: bypass_locked)
+ FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, notify: notify, bypass_locked: bypass_locked, bypass_limit: true)
UnfollowService.new.call(follower_account, old_target_account, skip_unmerge: true)
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
true
diff --git a/app/workers/unmerge_worker.rb b/app/workers/unmerge_worker.rb
index ea6aacebf..1a23faae5 100644
--- a/app/workers/unmerge_worker.rb
+++ b/app/workers/unmerge_worker.rb
@@ -6,6 +6,8 @@ class UnmergeWorker
sidekiq_options queue: 'pull'
def perform(from_account_id, into_account_id)
- FeedManager.instance.unmerge_from_timeline(Account.find(from_account_id), Account.find(into_account_id))
+ FeedManager.instance.unmerge_from_home(Account.find(from_account_id), Account.find(into_account_id))
+ rescue ActiveRecord::RecordNotFound
+ true
end
end