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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: be7ac8c0aec7de8f0d4d6a86b4a1455a6f9aef61
4
- data.tar.gz: 9861b4a0a873da471fac752e00ff426821f03715
3
+ metadata.gz: 03eb17313451ab7a8dfa1cffa18f79f7e87df368
4
+ data.tar.gz: 36611216461166a026bc525452720ccbc30be78c
5
5
  SHA512:
6
- metadata.gz: 499d274f428e55d2db225f5cd92caab91b79533aaf090217b38dbc5d4dd515ff254fc9227ee6bef79ecb366e37758d476c685d41040c52e14970559418c3aa68
7
- data.tar.gz: 6c239f00a424665dc5e075779685f3206faf9cf0b199dcd025e9c6ec3a76df22c42cd1cc66fdb5430fabeaff581eef3a593e090acab61c8a2d19daccfc9f1c2f
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:**
@@ -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(key, args = {}, &block)
17
- setup_instance(key, args).semaphore(args, &block)
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(key, args = {}, &block)
21
- setup_instance(key, args).if_open(args, &block)
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(key, args = {}, &block)
25
- setup_instance(key, args).if_locked(args, &block)
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(args = {}, &block)
55
- ttl = args[:ttl] || config.default_ttl
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(args = {}, &block)
65
- return if locked?
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(args = {}, &block)
71
- return if open?
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
- private
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,8 @@
1
+ class RedisLock
2
+ class IfLocked < Semaphore
3
+ def call(&block)
4
+ return :open if lock.open?
5
+ _perform(&block)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class RedisLock
2
+ class IfOpen < Semaphore
3
+ def call(&block)
4
+ return :locked if lock.locked?
5
+ _perform(&block)
6
+ end
7
+ end
8
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  class RedisLock
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
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.3.1
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-25 00:00:00.000000000 Z
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