Skip to content
Extraits de code Groupes Projets
Valider 6b0eda14 rédigé par ThibG's avatar ThibG Validation de Eugen Rochko
Parcourir les fichiers

Avoid race condition when streaming deleted statuses (#10280)

* Avoid race condition when streaming deleted statuses

* Move redis lock to DistributionWorker to avoid extra Redis value
parent db06b253
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -14,16 +14,22 @@ class RemoveStatusService < BaseService ...@@ -14,16 +14,22 @@ class RemoveStatusService < BaseService
@stream_entry = status.stream_entry @stream_entry = status.stream_entry
@options = options @options = options
remove_from_self if status.account.local? RedisLock.acquire(lock_options) do |lock|
remove_from_followers if lock.acquired?
remove_from_lists remove_from_self if status.account.local?
remove_from_affected remove_from_followers
remove_reblogs remove_from_lists
remove_from_hashtags remove_from_affected
remove_from_public remove_reblogs
remove_from_media if status.media_attachments.any? remove_from_hashtags
remove_from_public
@status.destroy! remove_from_media if status.media_attachments.any?
@status.destroy!
else
raise Mastodon::RaceConditionError
end
end
# There is no reason to send out Undo activities when the # There is no reason to send out Undo activities when the
# cause is that the original object has been removed, since # cause is that the original object has been removed, since
...@@ -156,4 +162,8 @@ class RemoveStatusService < BaseService ...@@ -156,4 +162,8 @@ class RemoveStatusService < BaseService
redis.publish('timeline:public:media', @payload) redis.publish('timeline:public:media', @payload)
redis.publish('timeline:public:local:media', @payload) if @status.local? redis.publish('timeline:public:local:media', @payload) if @status.local?
end end
def lock_options
{ redis: Redis.current, key: "distribute:#{@status.id}" }
end
end end
...@@ -4,7 +4,13 @@ class DistributionWorker ...@@ -4,7 +4,13 @@ class DistributionWorker
include Sidekiq::Worker include Sidekiq::Worker
def perform(status_id) def perform(status_id)
FanOutOnWriteService.new.call(Status.find(status_id)) RedisLock.acquire(redis: Redis.current, key: "distribute:#{status_id}") do |lock|
if lock.acquired?
FanOutOnWriteService.new.call(Status.find(status_id))
else
raise Mastodon::RaceConditionError
end
end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
true true
end end
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter