@stream_entry = status.stream_entry
@options = options
- remove_from_self if status.account.local?
- remove_from_followers
- remove_from_lists
- remove_from_affected
- remove_reblogs
- remove_from_hashtags
- remove_from_public
- remove_from_media if status.media_attachments.any?
-
- @status.destroy!
+ RedisLock.acquire(lock_options) do |lock|
+ if lock.acquired?
+ remove_from_self if status.account.local?
+ remove_from_followers
+ remove_from_lists
+ remove_from_affected
+ remove_reblogs
+ remove_from_hashtags
+ remove_from_public
+ 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
# cause is that the original object has been removed, since
redis.publish('timeline:public:media', @payload)
redis.publish('timeline:public:local:media', @payload) if @status.local?
end
+
+ def lock_options
+ { redis: Redis.current, key: "distribute:#{@status.id}" }
+ end
end
include Sidekiq::Worker
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
true
end