Last active
March 21, 2017 15:42
-
-
Save TrumpClone/6826bb80fef2cd9f402328a774617a6e to your computer and use it in GitHub Desktop.
DB Locker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Synchronizable | |
DEFAULT_WAIT_TIME = 10.seconds | |
extend self | |
def synchronize(*args, &block) | |
Transaction.run { with_advisory_lock(*args, &block) } | |
end | |
private | |
def with_advisory_lock(object = self, wait_time: DEFAULT_WAIT_TIME, **params) | |
lock_name = lock_name_for(object, params) | |
ActiveRecord::Base.logger.debug "Locking with #{lock_name}" | |
wait_time = nil if Rails.env.in?(%w[development test]) | |
wrapped_block = proc do | |
ActiveRecord::Base.uncached do | |
ActiveRecord::Base._with_advisory_lock(lock_name) do | |
object.reload if object.is_a?(ActiveRecord::Base) | |
yield | |
end | |
end | |
end | |
if WithAdvisoryLock::Base.lock_stack.empty? | |
# We have to pass Timeout::Error explicitly so that transactions properly work | |
Timeout.timeout(wait_time, Timeout::Error, &wrapped_block) | |
else | |
wrapped_block.call | |
end | |
end | |
def lock_name_for(object, params) | |
name_parts = | |
case object | |
when String, Symbol | |
[object] | |
when Class | |
[object.name.underscore.dasherize] | |
else | |
[object.class.name.underscore.dasherize, object.try(:id)] | |
end | |
[name_parts, *params].flatten.compact.join("-") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment