semian 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/.rubocop.yml +113 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +5 -0
- data/LICENSE.md +1 -1
- data/README.md +488 -39
- data/Rakefile +15 -8
- data/ext/semian/extconf.rb +2 -2
- data/lib/semian.rb +16 -6
- data/lib/semian/adapter.rb +1 -1
- data/lib/semian/circuit_breaker.rb +38 -37
- data/lib/semian/mysql2.rb +21 -1
- data/lib/semian/net_http.rb +95 -0
- data/lib/semian/protected_resource.rb +7 -2
- data/lib/semian/resource.rb +1 -1
- data/lib/semian/simple_integer.rb +23 -0
- data/lib/semian/simple_sliding_window.rb +43 -0
- data/lib/semian/simple_state.rb +43 -0
- data/lib/semian/unprotected_resource.rb +4 -1
- data/lib/semian/version.rb +1 -1
- data/repodb.yml +1 -0
- data/scripts/install_toxiproxy.sh +3 -3
- data/semian.gemspec +4 -3
- data/test/circuit_breaker_test.rb +6 -2
- data/test/helpers/background_helper.rb +1 -1
- data/test/instrumentation_test.rb +1 -1
- data/test/mysql2_test.rb +57 -1
- data/test/net_http_test.rb +481 -0
- data/test/redis_test.rb +3 -3
- data/test/resource_test.rb +33 -31
- data/test/semian_test.rb +3 -2
- data/test/simple_integer_test.rb +49 -0
- data/test/simple_sliding_window_test.rb +65 -0
- data/test/simple_state_test.rb +45 -0
- data/test/test_helper.rb +5 -0
- data/test/unprotected_resource_test.rb +1 -1
- metadata +30 -27
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -1
- metadata.gz.sig +0 -0
data/test/redis_test.rb
CHANGED
@@ -79,7 +79,7 @@ class TestRedis < MiniTest::Unit::TestCase
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def test_resource_acquisition_for_connect
|
82
|
-
|
82
|
+
connect_to_redis!
|
83
83
|
|
84
84
|
Semian[:redis_testing].acquire do
|
85
85
|
error = assert_raises Redis::ResourceBusyError do
|
@@ -213,11 +213,11 @@ class TestRedis < MiniTest::Unit::TestCase
|
|
213
213
|
def connect_to_redis!(semian_options = {})
|
214
214
|
redis = Redis.new(
|
215
215
|
host: '127.0.0.1',
|
216
|
-
port:
|
216
|
+
port: 16_379,
|
217
217
|
reconnect_attempts: 0,
|
218
218
|
db: 1,
|
219
219
|
timeout: 0.5,
|
220
|
-
semian: SEMIAN_OPTIONS.merge(semian_options)
|
220
|
+
semian: SEMIAN_OPTIONS.merge(semian_options),
|
221
221
|
)
|
222
222
|
redis.client.connect
|
223
223
|
redis
|
data/test/resource_test.rb
CHANGED
@@ -2,7 +2,9 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestResource < MiniTest::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
Semian.destroy(:testing)
|
5
|
+
Semian.destroy(:testing)
|
6
|
+
rescue
|
7
|
+
nil
|
6
8
|
end
|
7
9
|
|
8
10
|
def teardown
|
@@ -109,10 +111,10 @@ class TestResource < MiniTest::Unit::TestCase
|
|
109
111
|
resource = create_resource :testing, tickets: 2, timeout: 0.5
|
110
112
|
|
111
113
|
resource.acquire do
|
112
|
-
|
114
|
+
fork do
|
113
115
|
resource.acquire do
|
114
116
|
assert_raises Semian::TimeoutError do
|
115
|
-
resource.acquire {
|
117
|
+
resource.acquire {}
|
116
118
|
end
|
117
119
|
end
|
118
120
|
end
|
@@ -122,35 +124,33 @@ class TestResource < MiniTest::Unit::TestCase
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def test_acquire_releases_on_kill
|
125
|
-
|
126
|
-
|
127
|
-
acquired = false
|
127
|
+
resource = create_resource :testing, tickets: 1, timeout: 0.1
|
128
|
+
acquired = false
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
# Ghetto process synchronization
|
131
|
+
file = Tempfile.new('semian')
|
132
|
+
path = file.path
|
133
|
+
file.close!
|
133
134
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
135
|
+
pid = fork do
|
136
|
+
resource.acquire do
|
137
|
+
FileUtils.touch(path)
|
138
|
+
sleep 1000
|
139
139
|
end
|
140
|
+
end
|
140
141
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
142
|
+
sleep 0.1 until File.exist?(path)
|
143
|
+
assert_raises Semian::TimeoutError do
|
144
|
+
resource.acquire {}
|
145
|
+
end
|
145
146
|
|
146
|
-
|
147
|
-
|
148
|
-
|
147
|
+
Process.kill("KILL", pid)
|
148
|
+
resource.acquire { acquired = true }
|
149
|
+
assert acquired
|
149
150
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
151
|
+
Process.wait
|
152
|
+
ensure
|
153
|
+
FileUtils.rm_f(path) if path
|
154
154
|
end
|
155
155
|
|
156
156
|
def test_count
|
@@ -184,7 +184,7 @@ class TestResource < MiniTest::Unit::TestCase
|
|
184
184
|
resource = create_resource :testing, tickets: 1
|
185
185
|
resource.destroy
|
186
186
|
assert_raises Semian::SyscallError do
|
187
|
-
resource.acquire {
|
187
|
+
resource.acquire {}
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
@@ -287,9 +287,7 @@ class TestResource < MiniTest::Unit::TestCase
|
|
287
287
|
|
288
288
|
f.flock(File::LOCK_UN)
|
289
289
|
|
290
|
-
while children.any?
|
291
|
-
children.delete(Process.wait)
|
292
|
-
end
|
290
|
+
children.delete(Process.wait) while children.any?
|
293
291
|
|
294
292
|
assert_equal 5, create_resource(:testing, tickets: 0).count
|
295
293
|
ensure
|
@@ -307,7 +305,11 @@ class TestResource < MiniTest::Unit::TestCase
|
|
307
305
|
def destroy_resources
|
308
306
|
return unless @resources
|
309
307
|
@resources.each do |resource|
|
310
|
-
|
308
|
+
begin
|
309
|
+
resource.destroy
|
310
|
+
rescue
|
311
|
+
nil
|
312
|
+
end
|
311
313
|
end
|
312
314
|
@resources = []
|
313
315
|
end
|
data/test/semian_test.rb
CHANGED
@@ -2,7 +2,9 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestSemian < MiniTest::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
Semian.destroy(:testing)
|
5
|
+
Semian.destroy(:testing)
|
6
|
+
rescue
|
7
|
+
nil
|
6
8
|
end
|
7
9
|
|
8
10
|
def test_unsupported_acquire_yields
|
@@ -27,5 +29,4 @@ class TestSemian < MiniTest::Unit::TestCase
|
|
27
29
|
ensure
|
28
30
|
ENV.delete('SEMIAN_SEMAPHORES_DISABLED')
|
29
31
|
end
|
30
|
-
|
31
32
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestSimpleInteger < MiniTest::Unit::TestCase
|
4
|
+
CLASS = ::Semian::Simple::Integer
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@integer = CLASS.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@integer.destroy
|
12
|
+
end
|
13
|
+
|
14
|
+
module IntegerTestCases
|
15
|
+
def test_access_value
|
16
|
+
assert_equal(0, @integer.value)
|
17
|
+
@integer.value = 99
|
18
|
+
assert_equal(99, @integer.value)
|
19
|
+
time_now = (Time.now).to_i
|
20
|
+
@integer.value = time_now
|
21
|
+
assert_equal(time_now, @integer.value)
|
22
|
+
@integer.value = 6
|
23
|
+
assert_equal(6, @integer.value)
|
24
|
+
@integer.value = 6
|
25
|
+
assert_equal(6, @integer.value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_increment
|
29
|
+
@integer.increment(4)
|
30
|
+
assert_equal(4, @integer.value)
|
31
|
+
@integer.increment
|
32
|
+
assert_equal(5, @integer.value)
|
33
|
+
@integer.increment(-2)
|
34
|
+
assert_equal(3, @integer.value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_reset_on_init
|
38
|
+
assert_equal(0, @integer.value)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_reset
|
42
|
+
@integer.increment(5)
|
43
|
+
@integer.reset
|
44
|
+
assert_equal(0, @integer.value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
include IntegerTestCases
|
49
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestSimpleSlidingWindow < MiniTest::Unit::TestCase
|
4
|
+
CLASS = ::Semian::Simple::SlidingWindow
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@sliding_window = CLASS.new(max_size: 6)
|
8
|
+
@sliding_window.clear
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@sliding_window.destroy
|
13
|
+
end
|
14
|
+
|
15
|
+
module SlidingWindowTestCases
|
16
|
+
def test_sliding_window_push
|
17
|
+
assert_equal(0, @sliding_window.size)
|
18
|
+
@sliding_window << 1
|
19
|
+
assert_sliding_window(@sliding_window, [1], 6)
|
20
|
+
@sliding_window << 5
|
21
|
+
assert_sliding_window(@sliding_window, [1, 5], 6)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_sliding_window_resize
|
25
|
+
assert_equal(0, @sliding_window.size)
|
26
|
+
@sliding_window << 1 << 2 << 3 << 4 << 5 << 6
|
27
|
+
assert_sliding_window(@sliding_window, [1, 2, 3, 4, 5, 6], 6)
|
28
|
+
@sliding_window.resize_to 6
|
29
|
+
assert_sliding_window(@sliding_window, [1, 2, 3, 4, 5, 6], 6)
|
30
|
+
@sliding_window.resize_to 5
|
31
|
+
assert_sliding_window(@sliding_window, [2, 3, 4, 5, 6], 5)
|
32
|
+
@sliding_window.resize_to 6
|
33
|
+
assert_sliding_window(@sliding_window, [2, 3, 4, 5, 6], 6)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_sliding_window_edge_falloff
|
37
|
+
assert_equal(0, @sliding_window.size)
|
38
|
+
@sliding_window << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7
|
39
|
+
assert_sliding_window(@sliding_window, [2, 3, 4, 5, 6, 7], 6)
|
40
|
+
@sliding_window.shift
|
41
|
+
assert_sliding_window(@sliding_window, [3, 4, 5, 6, 7], 6)
|
42
|
+
end
|
43
|
+
|
44
|
+
def resize_to_less_than_1_raises
|
45
|
+
assert_raises ArgumentError do
|
46
|
+
@sliding_window.resize_to 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module SlidingWindowUtilityMethods
|
52
|
+
def assert_sliding_window(sliding_window, array, max_size)
|
53
|
+
# Get private member, the sliding_window doesn't expose the entire array
|
54
|
+
data = sliding_window.instance_variable_get("@window")
|
55
|
+
assert_equal(array, data)
|
56
|
+
assert_equal(max_size, sliding_window.max_size)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
include SlidingWindowTestCases
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
include SlidingWindowUtilityMethods
|
65
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestSimpleEnum < MiniTest::Unit::TestCase
|
4
|
+
CLASS = ::Semian::Simple::State
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@state = CLASS.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@state.destroy
|
12
|
+
end
|
13
|
+
|
14
|
+
module StateTestCases
|
15
|
+
def test_start_closed?
|
16
|
+
assert @state.closed?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_open
|
20
|
+
@state.open
|
21
|
+
assert @state.open?
|
22
|
+
assert_equal @state.value, :open
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_close
|
26
|
+
@state.close
|
27
|
+
assert @state.closed?
|
28
|
+
assert_equal @state.value, :closed
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_half_open
|
32
|
+
@state.half_open
|
33
|
+
assert @state.half_open?
|
34
|
+
assert_equal @state.value, :half_open
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_reset
|
38
|
+
@state.reset
|
39
|
+
assert @state.closed?
|
40
|
+
assert_equal @state.value, :closed
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
include StateTestCases
|
45
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,37 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semian
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Francis
|
8
8
|
- Simon Eskildsen
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
|
-
cert_chain:
|
12
|
-
-
|
13
|
-
-----BEGIN CERTIFICATE-----
|
14
|
-
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ8wDQYDVQQDDAZhZG1p
|
15
|
-
bnMxFzAVBgoJkiaJk/IsZAEZFgdzaG9waWZ5MRMwEQYKCZImiZPyLGQBGRYDY29t
|
16
|
-
MB4XDTE0MDUxNTIwMzM0OFoXDTE1MDUxNTIwMzM0OFowPzEPMA0GA1UEAwwGYWRt
|
17
|
-
aW5zMRcwFQYKCZImiZPyLGQBGRYHc2hvcGlmeTETMBEGCgmSJomT8ixkARkWA2Nv
|
18
|
-
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0/81O3e1vh5smcwp2G
|
19
|
-
MpLQ6q0kejQLa65bPYPxdzWA1SYOKyGfw+yR9LdFzsuKpwWzKq6zX35lj1IckWS4
|
20
|
-
bNBEQzxmufUxU0XPM02haFB8fOfDJzdXsWte9Ge4IFwahwn68gpMqN+BvxL+KMYz
|
21
|
-
Iut9YmN44d4LZdsENEIO5vmybuG2vYDz7R56qB0PA+Q2P2CdhymsBad2DQs69FBo
|
22
|
-
uico9V6VMYYctL9lCYdzu9IXrOYNTt88suKIVzzAlHOKeN0Ng5qdztFoTR8sfxDr
|
23
|
-
Ydg3KHl5n47wlpgd8R0f/4b5gGxW+v9pyJCgQnLlRu7DedVSvv7+GMtj3g9r3nhJ
|
24
|
-
KqECAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFI/o
|
25
|
-
maf34HXbUOQsdoLHacEKQgunMB0GA1UdEQQWMBSBEmFkbWluc0BzaG9waWZ5LmNv
|
26
|
-
bTAdBgNVHRIEFjAUgRJhZG1pbnNAc2hvcGlmeS5jb20wDQYJKoZIhvcNAQEFBQAD
|
27
|
-
ggEBADkK9aj5T0HPExsov4EoMWFnO+G7RQ28C30VAfKxnL2UxG6i4XMHVs6Xi94h
|
28
|
-
qXFw1ec9Y2eDUqaolT3bviOk9BB197+A8Vz/k7MC6ci2NE+yDDB7HAC8zU6LAx8Y
|
29
|
-
Iqvw7B/PSZ/pz4bUVFlTATif4mi1vO3lidRkdHRtM7UePSn2rUpOi0gtXBP3bLu5
|
30
|
-
YjHJN7wx5cugMEyroKITG5gL0Nxtu21qtOlHX4Hc4KdE2JqzCPOsS4zsZGhgwhPs
|
31
|
-
fl3hbtVFTqbOlwL9vy1fudXcolIE/ZTcxQ+er07ZFZdKCXayR9PPs64heamfn0fp
|
32
|
-
TConQSX2BnZdhIEYW+cKzEC/bLc=
|
33
|
-
-----END CERTIFICATE-----
|
34
|
-
date: 2015-03-11 00:00:00.000000000 Z
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-11-26 00:00:00.000000000 Z
|
35
13
|
dependencies:
|
36
14
|
- !ruby/object:Gem::Dependency
|
37
15
|
name: rake-compiler
|
@@ -89,6 +67,20 @@ dependencies:
|
|
89
67
|
- - ">="
|
90
68
|
- !ruby/object:Gem::Version
|
91
69
|
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: thin
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
92
84
|
- !ruby/object:Gem::Dependency
|
93
85
|
name: toxiproxy
|
94
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,7 +105,9 @@ extensions:
|
|
113
105
|
extra_rdoc_files: []
|
114
106
|
files:
|
115
107
|
- ".gitignore"
|
108
|
+
- ".rubocop.yml"
|
116
109
|
- ".travis.yml"
|
110
|
+
- CHANGELOG.md
|
117
111
|
- Gemfile
|
118
112
|
- LICENSE.md
|
119
113
|
- README.md
|
@@ -125,24 +119,33 @@ files:
|
|
125
119
|
- lib/semian/circuit_breaker.rb
|
126
120
|
- lib/semian/instrumentable.rb
|
127
121
|
- lib/semian/mysql2.rb
|
122
|
+
- lib/semian/net_http.rb
|
128
123
|
- lib/semian/platform.rb
|
129
124
|
- lib/semian/protected_resource.rb
|
130
125
|
- lib/semian/redis.rb
|
131
126
|
- lib/semian/resource.rb
|
127
|
+
- lib/semian/simple_integer.rb
|
128
|
+
- lib/semian/simple_sliding_window.rb
|
129
|
+
- lib/semian/simple_state.rb
|
132
130
|
- lib/semian/unprotected_resource.rb
|
133
131
|
- lib/semian/version.rb
|
132
|
+
- repodb.yml
|
134
133
|
- scripts/install_toxiproxy.sh
|
135
134
|
- semian.gemspec
|
136
135
|
- test/circuit_breaker_test.rb
|
137
136
|
- test/helpers/background_helper.rb
|
138
137
|
- test/instrumentation_test.rb
|
139
138
|
- test/mysql2_test.rb
|
139
|
+
- test/net_http_test.rb
|
140
140
|
- test/redis_test.rb
|
141
141
|
- test/resource_test.rb
|
142
142
|
- test/semian_test.rb
|
143
|
+
- test/simple_integer_test.rb
|
144
|
+
- test/simple_sliding_window_test.rb
|
145
|
+
- test/simple_state_test.rb
|
143
146
|
- test/test_helper.rb
|
144
147
|
- test/unprotected_resource_test.rb
|
145
|
-
homepage: https://github.com/
|
148
|
+
homepage: https://github.com/shopify/semian
|
146
149
|
licenses:
|
147
150
|
- MIT
|
148
151
|
metadata: {}
|
@@ -162,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
165
|
version: '0'
|
163
166
|
requirements: []
|
164
167
|
rubyforge_project:
|
165
|
-
rubygems_version: 2.2.
|
168
|
+
rubygems_version: 2.2.3
|
166
169
|
signing_key:
|
167
170
|
specification_version: 4
|
168
171
|
summary: Bulkheading for Ruby with SysV semaphores
|