redis_lock 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +19 -0
- data/lib/redis_lock.rb +23 -44
- data/lib/redis_lock/if_locked.rb +8 -0
- data/lib/redis_lock/if_open.rb +8 -0
- data/lib/redis_lock/multi_lock.rb +45 -0
- data/lib/redis_lock/semaphore.rb +32 -0
- data/lib/redis_lock/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03eb17313451ab7a8dfa1cffa18f79f7e87df368
|
4
|
+
data.tar.gz: 36611216461166a026bc525452720ccbc30be78c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b48fc19c007834779835bffab3abfa4cba58573f6963f87ae70affcef14b350f8a5ef06fb81e59360f04a4bf47ed56516cd28fa3b0291389c0248524543aabe5
|
7
|
+
data.tar.gz: 6b17f6e912c9f445a3243a1c4dff1b862a0371442a360ca68e3d9875d349529c120ca34e7b7c0e4ad6aeeabcbb6fe6fd6fa7ef3867266468e324a544fa0c7427
|
data/README.md
CHANGED
@@ -101,6 +101,25 @@ out #=> :hello
|
|
101
101
|
RedisLock.new('my_key').locked? #=> false
|
102
102
|
```
|
103
103
|
|
104
|
+
Very useful when you are changing multiple objects and want to protect them
|
105
|
+
in a distributed system
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
lock_1 = RedisLock.new('my_key')
|
109
|
+
lock_2 = RedisLock.new('another_key')
|
110
|
+
|
111
|
+
out = RedisLock.multi_semaphore('my_key', 'another_key') do |multi_lock|
|
112
|
+
multi_lock.locked? #=> true
|
113
|
+
lock_1.locked? #=> true
|
114
|
+
lock_2.locked? #=> true
|
115
|
+
sleep 3 # Do something
|
116
|
+
:hello
|
117
|
+
end
|
118
|
+
out #=> :hello
|
119
|
+
lock_1.locked? #=> false
|
120
|
+
lock_2.locked? #=> false
|
121
|
+
```
|
122
|
+
|
104
123
|
__if_open:__
|
105
124
|
|
106
125
|
**Use case:**
|
data/lib/redis_lock.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'redis'
|
2
2
|
require "redis_lock/version"
|
3
|
-
require "redis_lock/configuration"
|
4
3
|
|
5
4
|
class RedisLock
|
6
5
|
attr_reader :key
|
@@ -13,16 +12,19 @@ class RedisLock
|
|
13
12
|
yield config
|
14
13
|
end
|
15
14
|
|
16
|
-
def self.semaphore(
|
17
|
-
|
15
|
+
def self.semaphore(*args, &block)
|
16
|
+
opts = extract_options!(args)
|
17
|
+
Semaphore.new(MultiLock.new(*args, opts), opts).call(&block)
|
18
18
|
end
|
19
19
|
|
20
|
-
def self.if_open(
|
21
|
-
|
20
|
+
def self.if_open(*args, &block)
|
21
|
+
opts = extract_options!(args)
|
22
|
+
IfOpen.new(MultiLock.new(*args, opts), opts).call(&block)
|
22
23
|
end
|
23
24
|
|
24
|
-
def self.if_locked(
|
25
|
-
|
25
|
+
def self.if_locked(*args, &block)
|
26
|
+
opts = extract_options!(args)
|
27
|
+
IfLocked.new(MultiLock.new(*args, opts), opts).call(&block)
|
26
28
|
end
|
27
29
|
|
28
30
|
def config; self.class.config; end
|
@@ -51,25 +53,17 @@ class RedisLock
|
|
51
53
|
redis.set(key, value, args.merge(opts)) == "OK" ? true : false
|
52
54
|
end
|
53
55
|
|
54
|
-
def semaphore(
|
55
|
-
|
56
|
-
set_opts = args[:set_opts] || {}
|
57
|
-
while locked?
|
58
|
-
sleep (args[:wait] || 3)
|
59
|
-
end
|
60
|
-
set(ttl, set_opts)
|
61
|
-
_semaphore_perform(&block)
|
56
|
+
def semaphore(opts = {}, &block)
|
57
|
+
Semaphore.new(self, opts).call(&block)
|
62
58
|
end
|
63
59
|
|
64
|
-
def if_open(
|
65
|
-
|
66
|
-
_perform(&block)
|
60
|
+
def if_open(opts = {}, &block)
|
61
|
+
IfOpen.new(self, opts).call(&block)
|
67
62
|
end
|
68
63
|
alias_method :perform, :if_open
|
69
64
|
|
70
|
-
def if_locked(
|
71
|
-
|
72
|
-
_perform(&block)
|
65
|
+
def if_locked(opts = {}, &block)
|
66
|
+
IfLocked.new(self, opts).call(&block)
|
73
67
|
end
|
74
68
|
|
75
69
|
def locked?
|
@@ -98,28 +92,13 @@ class RedisLock
|
|
98
92
|
redis.get(key)
|
99
93
|
end
|
100
94
|
|
101
|
-
|
102
|
-
|
103
|
-
def self.setup_instance(key, args)
|
104
|
-
inst_opts = { redis: args.delete(:redis) }.reject{ |_, v| v.nil? }
|
105
|
-
new(key, inst_opts)
|
106
|
-
end
|
107
|
-
|
108
|
-
def _semaphore_perform(&block)
|
109
|
-
yield self
|
110
|
-
rescue => e
|
111
|
-
config.logger.error "[#{self.class}] key: `#{key}` error:"
|
112
|
-
config.logger.error e
|
113
|
-
raise e
|
114
|
-
ensure
|
115
|
-
unlock!
|
116
|
-
end
|
117
|
-
|
118
|
-
def _perform(&block)
|
119
|
-
yield self
|
120
|
-
rescue => e
|
121
|
-
config.logger.error "[#{self.class}] key: `#{key}` error:"
|
122
|
-
config.logger.error e
|
123
|
-
raise e
|
95
|
+
def self.extract_options!(args)
|
96
|
+
args.last.is_a?(::Hash) ? args.pop : {}
|
124
97
|
end
|
125
98
|
end
|
99
|
+
|
100
|
+
require "redis_lock/configuration"
|
101
|
+
require "redis_lock/semaphore"
|
102
|
+
require "redis_lock/if_open"
|
103
|
+
require "redis_lock/if_locked"
|
104
|
+
require "redis_lock/multi_lock"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class RedisLock
|
2
|
+
class MultiLock
|
3
|
+
extend Forwardable
|
4
|
+
attr_reader :keys, :locks, :opts
|
5
|
+
def_delegators :locks, :any?, :all?, :each, :map
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
@opts = extract_options!(args)
|
9
|
+
@keys = args
|
10
|
+
@locks = @keys.map do |k|
|
11
|
+
RedisLock.new(k, @opts)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def extract_options!(args)
|
16
|
+
args.last.is_a?(::Hash) ? args.pop : {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def set(ttl, opts = {})
|
20
|
+
map { |l| l.set(ttl, opts) }.all?{ |e| e === true }
|
21
|
+
end
|
22
|
+
|
23
|
+
def config
|
24
|
+
RedisLock.config
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete
|
28
|
+
map(&:delete).all?{ |e| e === true }
|
29
|
+
end
|
30
|
+
alias_method :unlock!, :delete
|
31
|
+
alias_method :open!, :delete
|
32
|
+
alias_method :remove, :delete
|
33
|
+
|
34
|
+
def open?
|
35
|
+
all?(&:open?)
|
36
|
+
end
|
37
|
+
alias_method :unlocked?, :open?
|
38
|
+
|
39
|
+
def locked?
|
40
|
+
any?(&:locked?)
|
41
|
+
end
|
42
|
+
alias_method :exists?, :locked?
|
43
|
+
alias_method :in_use?, :locked?
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class RedisLock
|
2
|
+
class Semaphore
|
3
|
+
attr_reader :lock, :args
|
4
|
+
|
5
|
+
def initialize(lock, args = {})
|
6
|
+
@lock = lock
|
7
|
+
@args = args
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(&block)
|
11
|
+
ttl = args[:ttl] || lock.config.default_ttl
|
12
|
+
set_opts = args[:set_opts] || {}
|
13
|
+
while lock.locked?
|
14
|
+
sleep (args[:wait] || 1)
|
15
|
+
end
|
16
|
+
lock.set(ttl, set_opts)
|
17
|
+
out = _perform(&block)
|
18
|
+
lock.unlock!
|
19
|
+
out
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def _perform(&block)
|
25
|
+
yield lock
|
26
|
+
rescue => e
|
27
|
+
config.logger.error "[#{self.class}] key: `#{key}` error:"
|
28
|
+
config.logger.error e
|
29
|
+
raise e
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/redis_lock/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_lock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artur Pañach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -96,6 +96,10 @@ files:
|
|
96
96
|
- bin/setup
|
97
97
|
- lib/redis_lock.rb
|
98
98
|
- lib/redis_lock/configuration.rb
|
99
|
+
- lib/redis_lock/if_locked.rb
|
100
|
+
- lib/redis_lock/if_open.rb
|
101
|
+
- lib/redis_lock/multi_lock.rb
|
102
|
+
- lib/redis_lock/semaphore.rb
|
99
103
|
- lib/redis_lock/version.rb
|
100
104
|
- redis_lock.gemspec
|
101
105
|
homepage: https://github.com/arturictus/redis_lock.git
|