redstruct 0.2.1 → 0.2.2

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: 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