0
0
Fork 0

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:
Eugen Rochko 2022-05-13 00:02:35 +02:00 committed by GitHub
parent 12535568f7
commit 6cf57c6765
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 112 additions and 179 deletions

View file

@ -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

View 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

View file

@ -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