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 +4 -4
- data/lib/redstruct/lock.rb +15 -6
- data/lib/redstruct/utils/atomic_counter.rb +30 -0
- data/lib/redstruct/version.rb +1 -1
- data/test/redstruct/lock_test.rb +16 -0
- data/test/redstruct/script_test.rb +1 -1
- data/test/test_helper.rb +3 -21
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2af38a102227eedaa6ed3d2f8efd91b02dcae8a0
|
4
|
+
data.tar.gz: 49041b97b9b1074aaac1986b792ea2ba72b7e3cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f1b9391762f28ec0686ce2f5b54b756b31e6640d63c51448b26d6d8948564a55916ff78f419edcba8310bdb3b79f91ad680fe5d17ad842e14fdda2528139823
|
7
|
+
data.tar.gz: 0abdd88f1387ea57ef1546ef35bae91fc783c631287c412705867ebbc148c093f9d5293aa208aec6b5f1fb964f8b0feedb2f3364c9f7338a6fef3f6f26d29fa0
|
data/lib/redstruct/lock.rb
CHANGED
@@ -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
|
-
|
112
|
-
argv = [@token, generate_token, (@expiry.to_f * 1000).floor]
|
116
|
+
released = true
|
113
117
|
|
114
|
-
|
115
|
-
|
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
|
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
|
data/lib/redstruct/version.rb
CHANGED
data/test/redstruct/lock_test.rb
CHANGED
@@ -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)
|
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 =
|
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.
|
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.
|
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-
|
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
|