Class: MongoMutex::Mutex

Inherits:
Object
  • Object
show all
Defined in:
lib/mongo_mutex/mutex.rb

Defined Under Namespace

Classes: MongoOperations

Instance Method Summary collapse

Constructor Details

#initialize(collection, lock_id, locker_id, options = {}) ⇒ Mutex

Returns a new instance of Mutex.

Raises:

  • (ArgumentError)


7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/mongo_mutex/mutex.rb', line 7

def initialize(collection, lock_id, locker_id, options = {})
  raise ArgumentError, "String lock id required" unless lock_id.is_a?(String)
  raise ArgumentError, "String locker id required" unless locker_id.is_a?(String)
  @collection = collection
  @lock_id = lock_id
  @locker_id = locker_id
  options = options.dup
  @lock_check_period = options.delete(:lock_check_period) || 5
  @lock_retention_timeout = options.delete(:lock_retention_timeout) || 600
  @clock = options.delete(:clock) || Time
  @logger = options.delete(:logger)
  @lock_operations = options.delete(:lock_operations) || MongoOperations.new
  raise ArgumentError, "Unsupported options #{options.keys}" unless options.empty?
end

Instance Method Details

#lockObject



45
46
47
48
49
50
# File 'lib/mongo_mutex/mutex.rb', line 45

def lock
  until try_lock
    sleep @lock_check_period
  end
  self
end

#locked?Boolean

Returns:

  • (Boolean)


40
41
42
43
# File 'lib/mongo_mutex/mutex.rb', line 40

def locked?
  lock_info = @lock_operations.lock_info(@collection, @lock_id)
  lock_info && lock_info[LOCKED_BY] && !expired?(lock_info[LOCKED_AT])
end

#synchronize(&block) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/mongo_mutex/mutex.rb', line 59

def synchronize(&block)
  lock
  begin
    yield
  ensure
    unlock
  end
end

#try_lockObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/mongo_mutex/mutex.rb', line 22

def try_lock
  previous = @lock_operations.try_lock(@collection, @lock_id, @locker_id, @clock.now, @lock_retention_timeout)
  if previous && (locked_by = previous[LOCKED_BY])
    if expired?(previous[LOCKED_AT])
      @logger.warn "Ignoring old #{@lock_id} lock by #{locked_by} since #{previous[LOCKED_AT]} was too long ago" if @logger
    else
      raise ThreadError, "mutex already locked by #{locked_by} at #{previous[LOCKED_AT]}"
    end
  end
  true
rescue Mongo::Error::OperationFailure => error
  if error.message.include?(DUPLICATE_KEY_ERROR)
    return false
  else
    raise
  end
end

#unlockObject



52
53
54
55
56
57
# File 'lib/mongo_mutex/mutex.rb', line 52

def unlock
  unless @lock_operations.unlock(@collection, @lock_id, @locker_id, @clock.now, @lock_retention_timeout)
    raise ThreadError, 'lock is either not locked or locked by someone else'
  end
  self
end