Class: LockManager

Inherits:
Object
  • Object
show all
Defined in:
app/services/lock_manager.rb

Constant Summary collapse

KEY_PREFIX =
"lockmanager"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type:, id:, expire:, wait: true) ⇒ LockManager

Returns a new instance of LockManager.



7
8
9
10
11
# File 'app/services/lock_manager.rb', line 7

def initialize(type:, id:, expire:, wait: true)
  @key = "#{KEY_PREFIX}-#{type}-#{id}"
  @expire = expire
  @wait = wait
end

Instance Attribute Details

#expireObject (readonly)

Returns the value of attribute expire.



4
5
6
# File 'app/services/lock_manager.rb', line 4

def expire
  @expire
end

#keyObject (readonly)

Returns the value of attribute key.



4
5
6
# File 'app/services/lock_manager.rb', line 4

def key
  @key
end

#lockedObject (readonly)

Returns the value of attribute locked.



4
5
6
# File 'app/services/lock_manager.rb', line 4

def locked
  @locked
end

#waitObject (readonly)

Returns the value of attribute wait.



4
5
6
# File 'app/services/lock_manager.rb', line 4

def wait
  @wait
end

Class Method Details

.active_locksObject



53
54
55
56
57
# File 'app/services/lock_manager.rb', line 53

def self.active_locks
  redis_client.keys("#{KEY_PREFIX}*").each_with_object({}) do |key, result|
    result[key] = redis_client.ttl(key)
  end
end

.redis_clientObject



71
72
73
# File 'app/services/lock_manager.rb', line 71

def self.redis_client
  Redis.new(RedisUrlParser.call(Settings.redis_url))
end

Instance Method Details

#keep_lockedObject



43
44
45
46
47
48
49
50
51
# File 'app/services/lock_manager.rb', line 43

def keep_locked
  raise "Lock not acquired" unless locked

  if redis_set(xx: true)
    puts "[LockManager] lock extended by #{expire}"
  else
    raise "[LockManager] Lock expired"
  end
end

#lockObject



13
14
15
16
17
18
19
20
21
22
23
# File 'app/services/lock_manager.rb', line 13

def lock
  if lock!
    begin
      yield(self)
    ensure
      unlock!
    end
  else
    false
  end
end

#lock!Object



25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/services/lock_manager.rb', line 25

def lock!
  try_lock

  if wait
    until locked
      sleep 0.1
      try_lock
    end
  end

  locked
end

#redis_clientObject



67
68
69
# File 'app/services/lock_manager.rb', line 67

def redis_client
  LockManager.redis_client
end

#redis_set(options) ⇒ Object



63
64
65
# File 'app/services/lock_manager.rb', line 63

def redis_set(options)
  redis_client.set(key, 1, **options.merge(ex: expire))
end

#try_lockObject



59
60
61
# File 'app/services/lock_manager.rb', line 59

def try_lock
  @locked = redis_set(nx: true)
end

#unlock!Object



38
39
40
41
# File 'app/services/lock_manager.rb', line 38

def unlock!
  redis_client.del(key)
  @locked = false
end