diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2022-05-13 00:02:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-13 00:02:35 +0200 |
commit | 6cf57c676550068a59149ca82d63fcb5b5431158 (patch) | |
tree | 4832da7de8828519c72a205d9878ccd5a606377a /app/models | |
parent | 12535568f7435ed627c37312782f8ca07e83eca9 (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/models')
-rw-r--r-- | app/models/account_migration.rb | 13 | ||||
-rw-r--r-- | app/models/concerns/lockable.rb | 19 | ||||
-rw-r--r-- | app/models/concerns/redisable.rb | 8 |
3 files changed, 26 insertions, 14 deletions
diff --git a/app/models/account_migration.rb b/app/models/account_migration.rb index ded32c9c6..06291c9f3 100644 --- a/app/models/account_migration.rb +++ b/app/models/account_migration.rb @@ -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 diff --git a/app/models/concerns/lockable.rb b/app/models/concerns/lockable.rb new file mode 100644 index 000000000..55a9714ca --- /dev/null +++ b/app/models/concerns/lockable.rb @@ -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 diff --git a/app/models/concerns/redisable.rb b/app/models/concerns/redisable.rb index 8d76b6b82..0dad3abb2 100644 --- a/app/models/concerns/redisable.rb +++ b/app/models/concerns/redisable.rb @@ -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 |