Class: Mongo::Lock

Inherits:
Object
  • Object
show all
Extended by:
ClassConvenienceMethods
Includes:
SendWithRaiseMethods
Defined in:
lib/mongo-lock.rb,
lib/mongo-lock/version.rb,
lib/mongo-lock/drivers/base.rb,
lib/mongo-lock/configuration.rb,
lib/mongo-lock/drivers/mongo.rb,
lib/mongo-lock/drivers/moped.rb,
lib/mongo-lock/send_with_raise_methods.rb,
lib/mongo-lock/class_convenience_methods.rb

Defined Under Namespace

Modules: ClassConvenienceMethods, Drivers, SendWithRaiseMethods Classes: Configuration, InvalidCollectionError, MixedCollectionsError, NotAcquiredError, NotExtendedError, NotReleasedError

Constant Summary collapse

VERSION =
"1.2.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ClassConvenienceMethods

acquire!, init_and_send, release!

Methods included from SendWithRaiseMethods

#acquire!, #extend!, #extend_by!, #release!, #send_with_raise

Constructor Details

#initialize(key, options = {}) ⇒ Lock

Returns a new instance of Lock.



73
74
75
76
77
# File 'lib/mongo-lock.rb', line 73

def initialize key, options = {}
  self.configuration = Configuration.new self.class.configuration.to_hash, options
  self.key = retrieve_lock_key key
  acquire_if_acquired
end

Instance Attribute Details

#acquiredObject

Returns the value of attribute acquired.



25
26
27
# File 'lib/mongo-lock.rb', line 25

def acquired
  @acquired
end

#configurationObject

Returns the value of attribute configuration.



23
24
25
# File 'lib/mongo-lock.rb', line 23

def configuration
  @configuration
end

#expires_atObject

Returns the value of attribute expires_at.



26
27
28
# File 'lib/mongo-lock.rb', line 26

def expires_at
  @expires_at
end

#keyObject

Returns the value of attribute key.



24
25
26
# File 'lib/mongo-lock.rb', line 24

def key
  @key
end

#releasedObject

Returns the value of attribute released.



27
28
29
# File 'lib/mongo-lock.rb', line 27

def released
  @released
end

Class Method Details

.clear_expired(options = {}) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/mongo-lock.rb', line 57

def self.clear_expired options = {}
  options = configuration.process_collection_options options

  options[:collections].each do |collection|
    configuration.driver.clear_expired collection
  end
end

.configurationObject



43
44
45
46
47
48
49
# File 'lib/mongo-lock.rb', line 43

def self.configuration
  if defined? @@default_configuration
    @@default_configuration
  else
    @@default_configuration = configure
  end
end

.configure(options = {}, &block) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/mongo-lock.rb', line 29

def self.configure options = {}, &block
  defaults = {
    timeout_in: false,
    limit: 100,
    frequency: 1,
    expire_in: 10,
    should_raise: false,
    driver: options[:driver] || (require('mongo-lock/drivers/mongo') && ::Mongo::Lock::Drivers::Mongo),
    owner: Proc.new { "#{`hostname`.strip}:#{Process.pid}:#{Thread.object_id}" }
  }
  defaults = defaults.merge(@@default_configuration) if defined?(@@default_configuration) && @@default_configuration
  @@default_configuration = Configuration.new(defaults, options, &block)
end

.ensure_indexesObject



51
52
53
54
55
# File 'lib/mongo-lock.rb', line 51

def self.ensure_indexes
  configuration.collections.each_pair do |key, collection|
    configuration.driver.ensure_indexes collection
  end
end

.release_all(options = {}) ⇒ Object



65
66
67
68
69
70
71
# File 'lib/mongo-lock.rb', line 65

def self.release_all options = {}
  options = configuration.process_collection_options options

  options[:collections].each do |collection|
    configuration.driver.release_collection collection, options[:owner]
  end
end

Instance Method Details

#acquire(options = {}, &block) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/mongo-lock.rb', line 86

def acquire options = {}, &block
  options = inherit_options options
  i = 1
  time_spent = 0

  loop do
    result = try_acquire options, i, time_spent, &block
    return result unless result.nil?

    frequency = call_if_proc options[:frequency], i
    sleep frequency
    time_spent += frequency
    i += 1
  end
end

#acquire_if_acquiredObject



217
218
219
# File 'lib/mongo-lock.rb', line 217

def acquire_if_acquired
  self.acquired = true if driver.is_acquired?
end

#acquired?Boolean

Current state

Returns:

  • (Boolean)


191
192
193
# File 'lib/mongo-lock.rb', line 191

def acquired?
  !!acquired && !expired?
end

#available?(options = {}) ⇒ Boolean

Returns:

  • (Boolean)


183
184
185
186
187
# File 'lib/mongo-lock.rb', line 183

def available? options = {}
  options = inherit_options options
  existing_lock = driver.find_existing
  !existing_lock || existing_lock['owner'] == options[:owner]
end

#call_block(options, &block) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/mongo-lock.rb', line 128

def call_block options, &block
  if block_given?
    yield self
    release(options)
  end
  true
end

#call_if_proc(proc, *args) ⇒ Object



230
231
232
233
234
235
236
# File 'lib/mongo-lock.rb', line 230

def call_if_proc proc, *args
  if proc.is_a? Proc
    proc.call(*args)
  else
    proc
  end
end

#configure(options = {}) {|self.configuration| ... } ⇒ Object

API

Yields:



81
82
83
84
# File 'lib/mongo-lock.rb', line 81

def configure options = {}, &block
  self.configuration = Configuration.new self.configuration.to_hash, options
  yield self.configuration if block_given?
end

#driverObject

Utils



205
206
207
# File 'lib/mongo-lock.rb', line 205

def driver
  @driver ||= configuration.driver.new self
end

#expired?Boolean

Returns:

  • (Boolean)


195
196
197
# File 'lib/mongo-lock.rb', line 195

def expired?
  !!(expires_at && expires_at < Time.now)
end

#extend(options = {}) ⇒ Object



178
179
180
181
# File 'lib/mongo-lock.rb', line 178

def extend options = {}
  time = configuration.to_hash.merge(options)[:expire_in]
  extend_by time, options
end

#extend_by(time, options = {}) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/mongo-lock.rb', line 165

def extend_by time, options = {}
  options = inherit_options options

  # Can't extend a lock that hasn't been acquired or expired
  if !acquired? || expired?
    return raise_or_false options, NotExtendedError

  else
    driver.find_and_update time, options
    true
  end
end

#inherit_options(options) ⇒ Object



226
227
228
# File 'lib/mongo-lock.rb', line 226

def inherit_options options
  configuration.to_hash.merge options
end

#raise_or_false(options, error = NotAcquiredError) ⇒ Object



221
222
223
224
# File 'lib/mongo-lock.rb', line 221

def raise_or_false options, error = NotAcquiredError
  raise error if options[:should_raise]
  false
end

#release(options = {}) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/mongo-lock.rb', line 136

def release options = {}
  options = inherit_options options

  # If the lock has already been released
  if released?
    return true

  # If the lock has expired its as good as released
  elsif expired?
    self.released = true
    self.acquired = false
    return true

  # We must have acquired the lock to release it
  elsif !acquired?
    if acquire options.merge(should_raise: false)
      return release options
    else
      return raise_or_false options, NotReleasedError
    end

  else
    self.released = true
    self.acquired = false
    driver.remove options
    return true
  end
end

#released?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/mongo-lock.rb', line 199

def released?
  !!released
end

#retrieve_lock_key(key) ⇒ Object



209
210
211
212
213
214
215
# File 'lib/mongo-lock.rb', line 209

def retrieve_lock_key key
  case
  when key.respond_to?(:lock_key)  then key.lock_key
  when key.is_a?(Array)            then key.map { |element| retrieve_lock_key(element) }.to_param
  else                                  key.to_param
  end.to_s
end

#try_acquire(options, i, time_spent, &block) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/mongo-lock.rb', line 102

def try_acquire options, i, time_spent, &block

  # If timeout has expired
  if options[:timeout_in] && options[:timeout_in] < time_spent
    return raise_or_false options

  # If limit has expired
  elsif options[:limit] && options[:limit] < i
    return raise_or_false options

  # If there is an existing lock
  elsif existing_lock = driver.find_or_insert(options)
    # If the lock is owned by me
    if existing_lock['owner'] == options[:owner]
      self.acquired = true
      extend_by options[:expire_in]
      return true
    end

  # If the lock was acquired
  else
    self.acquired = true
    return call_block options, &block
  end
end