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.



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

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



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

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



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

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

Instance Method Details

#keep_lockedObject



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

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



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

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

#lock!Object



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

def lock!
  try_lock

  if wait
    until locked
      sleep 0.1
      try_lock
    end
  end

  locked
end

#redis_clientObject



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

def redis_client
  LockManager.redis_client
end

#redis_set(options) ⇒ Object



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

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

#try_lockObject



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

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

#unlock!Object



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

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