redstruct 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 134acc649952b4163693f10342277431de4934fa
4
- data.tar.gz: 19ab242fd3c80366c0904dd4f9ef774bbebe77e7
3
+ metadata.gz: 2af38a102227eedaa6ed3d2f8efd91b02dcae8a0
4
+ data.tar.gz: 49041b97b9b1074aaac1986b792ea2ba72b7e3cc
5
5
  SHA512:
6
- metadata.gz: d7750e77d99eed37f6e8f40d2b7125309b706b53b1a21034bf79211c5c50e8cb130bd392cf4d5694c8faadd51e72c0346eb89dc9276a4d30724d229987e6ea42
7
- data.tar.gz: 724d70a31f5b50a59bbf7b899f3bcffc0d9204ad76b3ee2141a99e2bb6ab1dafcee2ca82d0f974f7dd702716bb41e26e3b2ed5d382e5d13e59ed7a53d5d63857
6
+ metadata.gz: 9f1b9391762f28ec0686ce2f5b54b756b31e6640d63c51448b26d6d8948564a55916ff78f419edcba8310bdb3b79f91ad680fe5d17ad842e14fdda2528139823
7
+ data.tar.gz: 0abdd88f1387ea57ef1546ef35bae91fc783c631287c412705867ebbc148c093f9d5293aa208aec6b5f1fb964f8b0feedb2f3364c9f7338a6fef3f6f26d29fa0
@@ -4,6 +4,7 @@ require 'securerandom'
4
4
  require 'redstruct/factory/object'
5
5
  require 'redstruct/utils/scriptable'
6
6
  require 'redstruct/utils/coercion'
7
+ require 'redstruct/utils/atomic_counter'
7
8
 
8
9
  module Redstruct
9
10
  # Implementation of a simple binary lock (locked/not locked), with option to block and wait for the lock.
@@ -39,6 +40,8 @@ module Redstruct
39
40
  @resource = resource
40
41
  @token = nil
41
42
  @expiry = expiry
43
+ @acquired = Redstruct::Utils::AtomicCounter.new
44
+
42
45
  @timeout = case timeout
43
46
  when nil then nil
44
47
  when Float::INFINITY then 0
@@ -96,6 +99,8 @@ module Redstruct
96
99
  unless token.nil?
97
100
  @lease.expire(@expiry)
98
101
  @token = token
102
+ @acquired.increment
103
+
99
104
  acquired = true
100
105
  end
101
106
 
@@ -108,20 +113,24 @@ module Redstruct
108
113
  def release
109
114
  return false if @token.nil?
110
115
 
111
- keys = [@lease.key, @tokens.key]
112
- argv = [@token, generate_token, (@expiry.to_f * 1000).floor]
116
+ released = true
113
117
 
114
- released = release_script(keys: keys, argv: argv)
115
- @token = nil
118
+ if @acquired.decrement.zero?
119
+ keys = [@lease.key, @tokens.key]
120
+ argv = [@token, generate_token, (@expiry.to_f * 1000).floor]
121
+
122
+ released = coerce_bool(release_script(keys: keys, argv: argv))
123
+ @token = nil
124
+ end
116
125
 
117
- return coerce_bool(released)
126
+ return released
118
127
  end
119
128
 
120
129
  private
121
130
 
122
131
  def non_blocking_acquire
123
132
  keys = [@lease.key, @tokens.key]
124
- argv = [generate_token]
133
+ argv = [@token || generate_token]
125
134
 
126
135
  return acquire_script(keys: keys, argv: argv)
127
136
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Redstruct
4
+ module Utils
5
+ # Very basic utility class to have thread-safe counters
6
+ class AtomicCounter
7
+ # @param [Integer] initial the initial value of the counter
8
+ def initialize(initial = 0)
9
+ @lock = Mutex.new
10
+ @current = initial
11
+ end
12
+
13
+ # Increments the counter by the given delta
14
+ # @param [Integer] by the delta to increment by
15
+ # @return [Integer] the new, incremented value
16
+ def increment(by: 1)
17
+ return @lock.synchronize do
18
+ @current += by.to_i
19
+ end
20
+ end
21
+
22
+ # Decrements the counter by the given delta
23
+ # @param [Integer] by the delta to decrement by
24
+ # @return [Integer] the new, decremented value
25
+ def decrement(by: 1)
26
+ return increment(by: -by.to_i)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Redstruct
4
4
  # Current version
5
- VERSION = '0.2.1'
5
+ VERSION = '0.2.2'
6
6
  end
@@ -109,6 +109,22 @@ module Redstruct
109
109
  assert lock.acquire, 'should be to acquire the lock again since it was deleted'
110
110
  end
111
111
 
112
+ def test_nested
113
+ lock = create
114
+ nested = false
115
+
116
+ lock.locked do
117
+ lock.locked do
118
+ nested = true
119
+ end
120
+
121
+ refute_nil lock.token, 'should still own the lock'
122
+ assert lock.acquire, 'should still own the lock'
123
+ end
124
+
125
+ assert nested, 'should have turned on the nested flag'
126
+ end
127
+
112
128
  private
113
129
 
114
130
  def create(resource = nil, **options)
@@ -6,7 +6,7 @@ module Redstruct
6
6
  class ScriptTest < Redstruct::Test
7
7
  def setup
8
8
  super
9
- @value = @@counter.incr
9
+ @value = @@counter.increment
10
10
  @code = "return #{@value}"
11
11
  @factory = create_factory
12
12
  @script = @factory.script(@code)
data/test/test_helper.rb CHANGED
@@ -5,6 +5,7 @@ require 'securerandom'
5
5
  require 'bundler/setup'
6
6
  require 'minitest/autorun'
7
7
  require 'flexmock/minitest'
8
+ require 'redstruct/utils/atomic_counter'
8
9
 
9
10
  ci_build = ENV['CI_BUILD'].to_i.positive?
10
11
 
@@ -30,37 +31,18 @@ Minitest.after_run do
30
31
  end
31
32
  end
32
33
 
33
- # Small class used to generate thread-safe sequence when creating per-test
34
- # factories
35
- class AtomicInteger
36
- def initialize
37
- @lock = Mutex.new
38
- @current = 0
39
- end
40
-
41
- def incr
42
- value = nil
43
- @lock.synchronize do
44
- value = @current
45
- @current += 1
46
- end
47
-
48
- return value
49
- end
50
- end
51
-
52
34
  module Redstruct
53
35
  # Base class for all Redstruct tests. Configures the gem, provides a default factory, and makes sure to clean it up
54
36
  # at the end
55
37
  class Test < Minitest::Test
56
- @@counter = AtomicInteger.new # rubocop: disable Style/ClassVars
38
+ @@counter = Redstruct::Utils::AtomicCounter.new # rubocop: disable Style/ClassVars
57
39
 
58
40
  parallelize_me!
59
41
  make_my_diffs_pretty!
60
42
 
61
43
  # Use this helper to create a factory that the test class will keep track of and remove at the end
62
44
  def create_factory(namespace = nil)
63
- namespace ||= "#{Redstruct.config.default_namespace}:#{@@counter.incr}"
45
+ namespace ||= "#{Redstruct.config.default_namespace}:#{@@counter.increment}"
64
46
  return Redstruct::Factory.new(namespace: namespace)
65
47
  end
66
48
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redstruct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Pepin-Perreault
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-31 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -113,6 +113,7 @@ files:
113
113
  - lib/redstruct/sorted_set/slice.rb
114
114
  - lib/redstruct/string.rb
115
115
  - lib/redstruct/struct.rb
116
+ - lib/redstruct/utils/atomic_counter.rb
116
117
  - lib/redstruct/utils/coercion.rb
117
118
  - lib/redstruct/utils/inspectable.rb
118
119
  - lib/redstruct/utils/iterable.rb