semian 0.3.0 → 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 +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
|