Refactor how Redis locks are created (#18400)
* Refactor how Redis locks are created * Fix autorelease duration on account deletion lock
This commit is contained in:
parent
12535568f7
commit
6cf57c6765
16 changed files with 112 additions and 179 deletions
|
@ -15,6 +15,7 @@
|
|||
|
||||
class AccountMigration < ApplicationRecord
|
||||
include Redisable
|
||||
include Lockable
|
||||
|
||||
COOLDOWN_PERIOD = 30.days.freeze
|
||||
|
||||
|
@ -41,12 +42,8 @@ class AccountMigration < ApplicationRecord
|
|||
|
||||
return false unless errors.empty?
|
||||
|
||||
RedisLock.acquire(lock_options) do |lock|
|
||||
if lock.acquired?
|
||||
save
|
||||
else
|
||||
raise Mastodon::RaceConditionError
|
||||
end
|
||||
with_lock("account_migration:#{account.id}") do
|
||||
save
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -83,8 +80,4 @@ class AccountMigration < ApplicationRecord
|
|||
def validate_migration_cooldown
|
||||
errors.add(:base, I18n.t('migrations.errors.on_cooldown')) if account.migrations.within_cooldown.exists?
|
||||
end
|
||||
|
||||
def lock_options
|
||||
{ redis: redis, key: "account_migration:#{account.id}" }
|
||||
end
|
||||
end
|
||||
|
|
19
app/models/concerns/lockable.rb
Normal file
19
app/models/concerns/lockable.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Lockable
|
||||
# @param [String] lock_name
|
||||
# @param [ActiveSupport::Duration] autorelease Automatically release the lock after this time
|
||||
# @param [Boolean] raise_on_failure Raise an error if a lock cannot be acquired, or fail silently
|
||||
# @raise [Mastodon::RaceConditionError]
|
||||
def with_lock(lock_name, autorelease: 15.minutes, raise_on_failure: true)
|
||||
with_redis do |redis|
|
||||
RedisLock.acquire(redis: redis, key: "lock:#{lock_name}", autorelease: autorelease.seconds) do |lock|
|
||||
if lock.acquired?
|
||||
yield
|
||||
elsif raise_on_failure
|
||||
raise Mastodon::RaceConditionError, "Could not acquire lock for #{lock_name}, try again later"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Redisable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
private
|
||||
|
||||
def redis
|
||||
Thread.current[:redis] ||= RedisConfiguration.pool.checkout
|
||||
end
|
||||
|
||||
def with_redis(&block)
|
||||
RedisConfiguration.with(&block)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue