summaryrefslogtreecommitdiffstats
path: root/app/lib
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2022-05-13 00:02:35 +0200
committerGitHub <noreply@github.com>2022-05-13 00:02:35 +0200
commit6cf57c676550068a59149ca82d63fcb5b5431158 (patch)
tree4832da7de8828519c72a205d9878ccd5a606377a /app/lib
parent12535568f7435ed627c37312782f8ca07e83eca9 (diff)
Refactor how Redis locks are created (#18400)
* Refactor how Redis locks are created * Fix autorelease duration on account deletion lock
Diffstat (limited to 'app/lib')
-rw-r--r--app/lib/activitypub/activity.rb17
-rw-r--r--app/lib/activitypub/activity/announce.rb2
-rw-r--r--app/lib/activitypub/activity/create.rb4
-rw-r--r--app/lib/activitypub/activity/delete.rb6
4 files changed, 7 insertions, 22 deletions
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index 3c51a7a51df..7ff06ea390c 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -3,6 +3,7 @@
class ActivityPub::Activity
include JsonLdHelper
include Redisable
+ include Lockable
SUPPORTED_TYPES = %w(Note Question).freeze
CONVERTED_TYPES = %w(Image Audio Video Article Page Event).freeze
@@ -157,22 +158,6 @@ class ActivityPub::Activity
end
end
- def lock_or_return(key, expire_after = 2.hours.seconds)
- yield if redis.set(key, true, nx: true, ex: expire_after)
- ensure
- redis.del(key)
- end
-
- def lock_or_fail(key, expire_after = 15.minutes.seconds)
- RedisLock.acquire({ redis: redis, key: key, autorelease: expire_after }) do |lock|
- if lock.acquired?
- yield
- else
- raise Mastodon::RaceConditionError
- end
- end
- end
-
def fetch?
!@options[:delivery]
end
diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb
index 0674b108337..0032f13e623 100644
--- a/app/lib/activitypub/activity/announce.rb
+++ b/app/lib/activitypub/activity/announce.rb
@@ -4,7 +4,7 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
def perform
return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity?
- lock_or_fail("announce:#{@object['id']}") do
+ with_lock("announce:#{@object['id']}") do
original_status = status_from_object
return reject_payload! if original_status.nil? || !announceable?(original_status)
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 1f32d8cce84..73882e1348f 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -47,7 +47,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def create_status
return reject_payload! if unsupported_object_type? || invalid_origin?(object_uri) || tombstone_exists? || !related_to_local_activity?
- lock_or_fail("create:#{object_uri}") do
+ with_lock("create:#{object_uri}") do
return if delete_arrived_first?(object_uri) || poll_vote?
@status = find_existing_status
@@ -315,7 +315,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
poll = replied_to_status.preloadable_poll
already_voted = true
- lock_or_fail("vote:#{replied_to_status.poll_id}:#{@account.id}") do
+ with_lock("vote:#{replied_to_status.poll_id}:#{@account.id}") do
already_voted = poll.votes.where(account: @account).exists?
poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: object_uri)
end
diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb
index f5ef863f37f..871eb39667a 100644
--- a/app/lib/activitypub/activity/delete.rb
+++ b/app/lib/activitypub/activity/delete.rb
@@ -12,7 +12,7 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
private
def delete_person
- lock_or_return("delete_in_progress:#{@account.id}") do
+ with_lock("delete_in_progress:#{@account.id}", autorelease: 2.hours, raise_on_failure: false) do
DeleteAccountService.new.call(@account, reserve_username: false, skip_activitypub: true)
end
end
@@ -20,14 +20,14 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
def delete_note
return if object_uri.nil?
- lock_or_return("delete_status_in_progress:#{object_uri}", 5.minutes.seconds) do
+ with_lock("delete_status_in_progress:#{object_uri}", raise_on_failure: false) do
unless invalid_origin?(object_uri)
# This lock ensures a concurrent `ActivityPub::Activity::Create` either
# does not create a status at all, or has finished saving it to the
# database before we try to load it.
# Without the lock, `delete_later!` could be called after `delete_arrived_first?`
# and `Status.find` before `Status.create!`
- lock_or_fail("create:#{object_uri}") { delete_later!(object_uri) }
+ with_lock("create:#{object_uri}") { delete_later!(object_uri) }
Tombstone.find_or_create_by(uri: object_uri, account: @account)
end