Class: ActiveRecord::DatabaseMutex::Implementation

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/database_mutex/implementation.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Implementation

Creates a mutex with the name given with the option :name.



25
26
27
28
# File 'lib/active_record/database_mutex/implementation.rb', line 25

def initialize(opts = {})
  @name = opts[:name] or raise ArgumentError, "mutex requires a :name argument"
  counter or raise ArgumentError, 'argument :name is too long'
end

Instance Attribute Details

#nameObject (readonly)

Returns the name of this mutex as given as a constructor argument.



31
32
33
# File 'lib/active_record/database_mutex/implementation.rb', line 31

def name
  @name
end

Class Method Details

.check_size?Boolean

Returns:

  • (Boolean)


13
14
15
16
17
18
19
20
21
# File 'lib/active_record/database_mutex/implementation.rb', line 13

def check_size?
  if defined? @check_size
    @check_size
  else
    version = db.execute("SHOW VARIABLES LIKE 'version'").first.last.
      delete('^0-9.').version
    @check_size = version >= '5.7'.version
  end
end

.dbObject



9
10
11
# File 'lib/active_record/database_mutex/implementation.rb', line 9

def db
  ActiveRecord::Base.connection
end

Instance Method Details

#aquired_lock?Boolean

Returns true if this mutex is locked by this database connection.

Returns:

  • (Boolean)


117
118
119
# File 'lib/active_record/database_mutex/implementation.rb', line 117

def aquired_lock?
  query("SELECT CONNECTION_ID() = IS_USED_LOCK(#{quote(name)})") == 1
end

#lock(opts = {}) ⇒ Object

Locks the mutex and returns true if successful. If the mutex is already locked and the timeout in seconds is given as the :timeout option, this method raises a MutexLocked exception after that many seconds. If the :timeout option wasn’t given, this method blocks until the lock could be aquired.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/active_record/database_mutex/implementation.rb', line 61

def lock(opts = {})
  if opts[:nonblock] # XXX document
    begin
      lock_with_timeout :timeout => 0
    rescue MutexLocked
    end
  elsif opts[:timeout]
    lock_with_timeout opts
  else
    spin_timeout = opts[:spin_timeout] || 1 # XXX document
    begin
      lock_with_timeout :timeout => spin_timeout
    rescue MutexLocked
      retry
    end
  end
end

#locked?Boolean

Returns true if this mutex is locked at the moment.

Returns:

  • (Boolean)


112
113
114
# File 'lib/active_record/database_mutex/implementation.rb', line 112

def locked?
  not unlocked?
end

#not_aquired_lock?Boolean

Returns true if this mutex is not locked by this database connection.

Returns:

  • (Boolean)


122
123
124
# File 'lib/active_record/database_mutex/implementation.rb', line 122

def not_aquired_lock?
  not aquired_lock?
end

#synchronize(opts = {}) ⇒ Object

Locks the mutex if it isn’t already locked via another database connection and yields to the given block. After executing the block’s content the mutex is unlocked (only if it was locked by this synchronize method before).

If the mutex was already locked by another database connection the method blocks until it could aquire the lock and only then the block’s content is executed. If the mutex was already locked by the current database connection then the block’s content is run and the the mutex isn’t unlocked afterwards.

If a value in seconds is passed to the :timeout option the blocking ends after that many seconds and the method returns immediately if the lock couldn’t be aquired during that time.



47
48
49
50
51
52
53
54
# File 'lib/active_record/database_mutex/implementation.rb', line 47

def synchronize(opts = {})
  locked = lock(opts) or return
  yield
rescue ActiveRecord::DatabaseMutex::MutexLocked
  return nil
ensure
  locked and unlock
end

#to_sObject Also known as: inspect

Returns a string representation of this DatabaseMutex instance.



127
128
129
# File 'lib/active_record/database_mutex/implementation.rb', line 127

def to_s
  "#<#{self.class} #{name}>"
end

#unlockObject

Unlocks the mutex and returns true if successful. Otherwise this method raises a MutexLocked exception.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/active_record/database_mutex/implementation.rb', line 81

def unlock(*)
  if aquired_lock?
    decrease_counter
    if counter_zero?
      case query("SELECT RELEASE_LOCK(#{quote(name)})")
      when 1
        true
      when 0, nil
        raise MutexUnlockFailed, "unlocking of mutex '#{name}' failed"
      end
    end
  else
    raise MutexUnlockFailed, "unlocking of mutex '#{name}' failed"
  end
end

#unlock?(*a) ⇒ Boolean

Unlock this mutex and return self if successful, otherwise (the mutex was not locked) nil is returned.

Returns:

  • (Boolean)


99
100
101
102
103
104
# File 'lib/active_record/database_mutex/implementation.rb', line 99

def unlock?(*a)
  unlock(*a)
  self
rescue MutexUnlockFailed
  nil
end

#unlocked?Boolean

Returns true if this mutex is unlocked at the moment.

Returns:

  • (Boolean)


107
108
109
# File 'lib/active_record/database_mutex/implementation.rb', line 107

def unlocked?
  query("SELECT IS_FREE_LOCK(#{quote(name)})") == 1
end