service_skeleton 0.0.0.1.ENOTAG → 0.0.0.2.g46c1e0e
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 +5 -5
- data/.gitignore +0 -2
- data/.rubocop.yml +114 -9
- data/.travis.yml +11 -0
- data/README.md +153 -279
- data/lib/service_skeleton/background_worker.rb +80 -0
- data/lib/service_skeleton/config.rb +18 -78
- data/lib/service_skeleton/config_variable.rb +8 -29
- data/lib/service_skeleton/config_variables.rb +68 -54
- data/lib/service_skeleton/error.rb +3 -5
- data/lib/service_skeleton/filtering_logger.rb +0 -2
- data/lib/service_skeleton/logging_helpers.rb +3 -10
- data/lib/service_skeleton/metrics_methods.rb +13 -28
- data/lib/service_skeleton/signal_handler.rb +183 -0
- data/lib/service_skeleton.rb +145 -22
- data/service_skeleton.gemspec +9 -10
- metadata +19 -102
- data/.editorconfig +0 -7
- data/.git-blame-ignore-revs +0 -2
- data/.github/workflows/ci.yml +0 -50
- data/lib/service_skeleton/config_class.rb +0 -16
- data/lib/service_skeleton/config_variable/boolean.rb +0 -21
- data/lib/service_skeleton/config_variable/enum.rb +0 -27
- data/lib/service_skeleton/config_variable/float.rb +0 -25
- data/lib/service_skeleton/config_variable/integer.rb +0 -25
- data/lib/service_skeleton/config_variable/kv_list.rb +0 -26
- data/lib/service_skeleton/config_variable/path_list.rb +0 -13
- data/lib/service_skeleton/config_variable/string.rb +0 -18
- data/lib/service_skeleton/config_variable/url.rb +0 -36
- data/lib/service_skeleton/config_variable/yaml_file.rb +0 -42
- data/lib/service_skeleton/generator.rb +0 -165
- data/lib/service_skeleton/metric_method_name.rb +0 -9
- data/lib/service_skeleton/runner.rb +0 -46
- data/lib/service_skeleton/service_name.rb +0 -20
- data/lib/service_skeleton/signal_manager.rb +0 -202
- data/lib/service_skeleton/signals_methods.rb +0 -15
- data/lib/service_skeleton/ultravisor_children.rb +0 -20
- data/lib/service_skeleton/ultravisor_loggerstash.rb +0 -11
- data/ultravisor/.yardopts +0 -1
- data/ultravisor/Guardfile +0 -9
- data/ultravisor/README.md +0 -404
- data/ultravisor/lib/ultravisor/child/call.rb +0 -21
- data/ultravisor/lib/ultravisor/child/call_receiver.rb +0 -14
- data/ultravisor/lib/ultravisor/child/cast.rb +0 -16
- data/ultravisor/lib/ultravisor/child/cast_receiver.rb +0 -11
- data/ultravisor/lib/ultravisor/child/process_cast_call.rb +0 -39
- data/ultravisor/lib/ultravisor/child.rb +0 -481
- data/ultravisor/lib/ultravisor/error.rb +0 -25
- data/ultravisor/lib/ultravisor/logging_helpers.rb +0 -32
- data/ultravisor/lib/ultravisor.rb +0 -216
- data/ultravisor/spec/example_group_methods.rb +0 -19
- data/ultravisor/spec/example_methods.rb +0 -8
- data/ultravisor/spec/spec_helper.rb +0 -52
- data/ultravisor/spec/ultravisor/add_child_spec.rb +0 -79
- data/ultravisor/spec/ultravisor/child/call_spec.rb +0 -121
- data/ultravisor/spec/ultravisor/child/cast_spec.rb +0 -111
- data/ultravisor/spec/ultravisor/child/id_spec.rb +0 -21
- data/ultravisor/spec/ultravisor/child/new_spec.rb +0 -152
- data/ultravisor/spec/ultravisor/child/restart_delay_spec.rb +0 -40
- data/ultravisor/spec/ultravisor/child/restart_spec.rb +0 -70
- data/ultravisor/spec/ultravisor/child/run_spec.rb +0 -95
- data/ultravisor/spec/ultravisor/child/shutdown_spec.rb +0 -124
- data/ultravisor/spec/ultravisor/child/spawn_spec.rb +0 -107
- data/ultravisor/spec/ultravisor/child/unsafe_instance_spec.rb +0 -55
- data/ultravisor/spec/ultravisor/child/wait_spec.rb +0 -32
- data/ultravisor/spec/ultravisor/new_spec.rb +0 -71
- data/ultravisor/spec/ultravisor/remove_child_spec.rb +0 -49
- data/ultravisor/spec/ultravisor/run_spec.rb +0 -334
- data/ultravisor/spec/ultravisor/shutdown_spec.rb +0 -106
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative "../spec_helper"
|
3
|
-
|
4
|
-
require_relative "../../lib/ultravisor"
|
5
|
-
|
6
|
-
describe Ultravisor do
|
7
|
-
describe ".new" do
|
8
|
-
context "without arguments" do
|
9
|
-
it "does not explode" do
|
10
|
-
expect { Ultravisor.new }.to_not raise_error
|
11
|
-
end
|
12
|
-
|
13
|
-
it "gives us an Ultravisor instance" do
|
14
|
-
expect(Ultravisor.new).to be_a(Ultravisor)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context "with empty children" do
|
19
|
-
it "does not explode" do
|
20
|
-
expect { Ultravisor.new children: [] }.to_not raise_error
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "with children that isn't an array" do
|
25
|
-
it "raises an error" do
|
26
|
-
[{}, "ohai!", nil, 42].each do |v|
|
27
|
-
expect { Ultravisor.new children: v }.to raise_error(ArgumentError)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "with valid children" do
|
33
|
-
let(:ultravisor) { Ultravisor.new(children: [{ id: :testy, klass: Object, method: :to_s }]) }
|
34
|
-
|
35
|
-
it "registers the child by its ID" do
|
36
|
-
expect(ultravisor[:testy]).to be_a(Ultravisor::Child)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context "with two children with the same ID" do
|
41
|
-
it "explodes" do
|
42
|
-
expect do
|
43
|
-
Ultravisor.new(
|
44
|
-
children: [
|
45
|
-
{ id: :testy, klass: Object, method: :to_s },
|
46
|
-
{ id: :testy, klass: Class, method: :to_s },
|
47
|
-
]
|
48
|
-
)
|
49
|
-
end.to raise_error(Ultravisor::DuplicateChildError)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context "with a valid strategy" do
|
54
|
-
it "does not explode" do
|
55
|
-
expect { Ultravisor.new strategy: :all_for_one }.to_not raise_error
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
[
|
60
|
-
{ strategy: :bob },
|
61
|
-
{ strategy: "all_for_one" },
|
62
|
-
{ strategy: ["games"] },
|
63
|
-
].each do |s|
|
64
|
-
context "with invalid strategy #{s.inspect}" do
|
65
|
-
it "explodes" do
|
66
|
-
expect { Ultravisor.new **s }.to raise_error(ArgumentError)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative "../spec_helper"
|
3
|
-
|
4
|
-
require_relative "../../lib/ultravisor"
|
5
|
-
|
6
|
-
describe Ultravisor do
|
7
|
-
let(:args) { {} }
|
8
|
-
let(:ultravisor) { Ultravisor.new(**args) }
|
9
|
-
let(:mock_child) { instance_double(Ultravisor::Child) }
|
10
|
-
|
11
|
-
describe "#remove_child" do
|
12
|
-
before(:each) do
|
13
|
-
ultravisor.instance_variable_set(:@children, [[:lamb, mock_child]])
|
14
|
-
end
|
15
|
-
|
16
|
-
context "when the ultravisor isn't running" do
|
17
|
-
it "removes the child from the list of children" do
|
18
|
-
ultravisor.remove_child(:lamb)
|
19
|
-
|
20
|
-
expect(ultravisor[:lamb]).to be(nil)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "doesn't explode if asked to remove a child that doesn't exist" do
|
24
|
-
expect { ultravisor.remove_child(:no_such_child) }.to_not raise_error
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "while the ultravisor is running" do
|
29
|
-
let(:mock_thread) { instance_double(Thread) }
|
30
|
-
|
31
|
-
before(:each) do
|
32
|
-
allow(mock_child).to receive(:shutdown)
|
33
|
-
ultravisor.instance_variable_set(:@running_thread, mock_thread)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "shuts down the child" do
|
37
|
-
expect(mock_child).to receive(:shutdown)
|
38
|
-
|
39
|
-
ultravisor.remove_child(:lamb)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "removes the child from the list of children" do
|
43
|
-
ultravisor.remove_child(:lamb)
|
44
|
-
|
45
|
-
expect(ultravisor[:lamb]).to be(nil)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,334 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative "../spec_helper"
|
3
|
-
|
4
|
-
require_relative "../../lib/ultravisor"
|
5
|
-
|
6
|
-
describe Ultravisor do
|
7
|
-
uses_logger
|
8
|
-
|
9
|
-
describe "#run" do
|
10
|
-
let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end } } }
|
11
|
-
let(:args) { { children: [{ id: :testy, klass: mock_class, method: :run }] } }
|
12
|
-
let(:ultravisor) { Ultravisor.new(**args) }
|
13
|
-
let(:mock_thread) { instance_double(Thread) }
|
14
|
-
|
15
|
-
before(:each) do
|
16
|
-
allow(ultravisor.instance_variable_get(:@queue)).to receive(:pop).and_return(:shutdown)
|
17
|
-
end
|
18
|
-
|
19
|
-
context "with no children" do
|
20
|
-
let(:args) { {} }
|
21
|
-
|
22
|
-
it "doesn't start anything" do
|
23
|
-
expect(Thread).to_not receive(:new)
|
24
|
-
|
25
|
-
expect { ultravisor.run }.to_not raise_error
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "when already running" do
|
30
|
-
before(:each) do
|
31
|
-
ultravisor.instance_variable_set(:@running_thread, mock_thread)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "raises an exception" do
|
35
|
-
expect { ultravisor.run }.to raise_error(Ultravisor::AlreadyRunningError)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context "when the event handler gets an unknown event" do
|
40
|
-
before(:each) do
|
41
|
-
allow(ultravisor.instance_variable_get(:@queue)).to receive(:pop).and_return("wassamatta", :shutdown)
|
42
|
-
allow(logger).to receive(:error)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "logs an error" do
|
46
|
-
expect(logger).to receive(:error).with(match(/^Ultravisor#.*process_events/))
|
47
|
-
|
48
|
-
ultravisor.run
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "with a single child" do
|
53
|
-
let(:child) { Ultravisor::Child.new(id: :testy, klass: Object, method: :to_s) }
|
54
|
-
|
55
|
-
before(:each) do
|
56
|
-
allow(child).to receive(:spawn)
|
57
|
-
ultravisor.instance_variable_set(:@children, [[child.id, child]])
|
58
|
-
end
|
59
|
-
|
60
|
-
it "spawns a child worker" do
|
61
|
-
expect(child).to receive(:spawn)
|
62
|
-
|
63
|
-
ultravisor.run
|
64
|
-
end
|
65
|
-
|
66
|
-
it "shuts down the child on termination" do
|
67
|
-
expect(ultravisor.instance_variable_get(:@children).first.last).to receive(:shutdown)
|
68
|
-
|
69
|
-
ultravisor.run
|
70
|
-
end
|
71
|
-
|
72
|
-
context "that terminates" do
|
73
|
-
before(:each) do
|
74
|
-
allow(ultravisor.instance_variable_get(:@queue)).to receive(:pop).and_return(child, :shutdown)
|
75
|
-
allow(ultravisor).to receive(:sleep)
|
76
|
-
end
|
77
|
-
|
78
|
-
context "within the limits of its restart policy" do
|
79
|
-
it "spawns the child again" do
|
80
|
-
expect(child).to receive(:spawn).exactly(:twice)
|
81
|
-
|
82
|
-
ultravisor.run
|
83
|
-
end
|
84
|
-
|
85
|
-
it "sleeps between restart" do
|
86
|
-
expect(ultravisor).to receive(:sleep).with(1)
|
87
|
-
|
88
|
-
ultravisor.run
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context "too often for its restart policy" do
|
93
|
-
before(:each) do
|
94
|
-
allow(child).to receive(:restart?).and_raise(Ultravisor::BlownRestartPolicyError)
|
95
|
-
allow(logger).to receive(:error)
|
96
|
-
end
|
97
|
-
|
98
|
-
it "terminates the ultravisor" do
|
99
|
-
expect(ultravisor.instance_variable_get(:@queue)).to receive(:<<).with(:shutdown)
|
100
|
-
|
101
|
-
ultravisor.run
|
102
|
-
end
|
103
|
-
|
104
|
-
it "logs an error" do
|
105
|
-
expect(logger).to receive(:error)
|
106
|
-
|
107
|
-
ultravisor.run
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
context "with a restart_policy delay range" do
|
112
|
-
let(:child) { Ultravisor::Child.new(id: :testy, klass: mock_class, method: :run, restart_policy: { delay: 7..12 }) }
|
113
|
-
|
114
|
-
it "sleeps for a period within the range" do
|
115
|
-
expect(ultravisor).to receive(:sleep).with(be_between(7, 12))
|
116
|
-
|
117
|
-
ultravisor.run
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context "while we're in the process of shutting down" do
|
122
|
-
before(:each) do
|
123
|
-
allow(ultravisor.instance_variable_get(:@queue)).to receive(:pop) do
|
124
|
-
if ultravisor.instance_variable_get(:@running_thread)
|
125
|
-
ultravisor.instance_variable_set(:@running_thread, nil)
|
126
|
-
child
|
127
|
-
else
|
128
|
-
:shutdown
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
it "doesn't respawn the child" do
|
134
|
-
expect(child).to receive(:spawn).exactly(:once)
|
135
|
-
|
136
|
-
ultravisor.run
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
context "with restart: :never" do
|
141
|
-
let(:child) { Ultravisor::Child.new(id: :once, klass: mock_class, restart: :never, method: :run) }
|
142
|
-
|
143
|
-
it "doesn't respawn the child" do
|
144
|
-
expect(child).to receive(:spawn).exactly(:once)
|
145
|
-
|
146
|
-
ultravisor.run
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context "with restart: :on_failure" do
|
151
|
-
let(:child) { Ultravisor::Child.new(id: :once, klass: mock_class, restart: :on_failure, method: :run) }
|
152
|
-
|
153
|
-
it "doesn't respawn the child" do
|
154
|
-
expect(child).to receive(:spawn).exactly(:once)
|
155
|
-
|
156
|
-
ultravisor.run
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
context "with an error" do
|
161
|
-
before(:each) do
|
162
|
-
allow(logger).to receive(:error)
|
163
|
-
ex = Errno::ENOENT.new("I stiiiiiiiill haven't found, what I'm lookin' for")
|
164
|
-
ex.set_backtrace(caller)
|
165
|
-
allow(child).to receive(:termination_exception).and_return(ex)
|
166
|
-
end
|
167
|
-
|
168
|
-
it "logs the error" do
|
169
|
-
expect(logger).to receive(:error).with(match(/:testy/))
|
170
|
-
|
171
|
-
ultravisor.run
|
172
|
-
end
|
173
|
-
|
174
|
-
it "respawns the child" do
|
175
|
-
expect(child).to receive(:spawn).exactly(:twice)
|
176
|
-
|
177
|
-
ultravisor.run
|
178
|
-
end
|
179
|
-
|
180
|
-
context "with restart: :on_failure" do
|
181
|
-
let(:child) { Ultravisor::Child.new(id: :once, klass: mock_class, restart: :on_failure, method: :run) }
|
182
|
-
|
183
|
-
it "respawns the child" do
|
184
|
-
expect(child).to receive(:spawn).exactly(:twice)
|
185
|
-
|
186
|
-
ultravisor.run
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
context "with two children" do
|
194
|
-
let(:args) do
|
195
|
-
{
|
196
|
-
children: [
|
197
|
-
{
|
198
|
-
id: :one,
|
199
|
-
klass: Object,
|
200
|
-
method: :to_s,
|
201
|
-
},
|
202
|
-
{
|
203
|
-
id: :two,
|
204
|
-
klass: Object,
|
205
|
-
method: :to_s,
|
206
|
-
}
|
207
|
-
]
|
208
|
-
}
|
209
|
-
end
|
210
|
-
|
211
|
-
it "starts the children in order of their definition" do
|
212
|
-
expect(ultravisor[:one]).to receive(:spawn).ordered
|
213
|
-
expect(ultravisor[:two]).to receive(:spawn).ordered
|
214
|
-
|
215
|
-
ultravisor.run
|
216
|
-
end
|
217
|
-
|
218
|
-
it "shuts the children down in the opposite order" do
|
219
|
-
expect(ultravisor[:two]).to receive(:shutdown).ordered
|
220
|
-
expect(ultravisor[:one]).to receive(:shutdown).ordered
|
221
|
-
|
222
|
-
ultravisor.run
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
context "with an all_for_one strategy" do
|
227
|
-
let(:args) do
|
228
|
-
{
|
229
|
-
strategy: :all_for_one,
|
230
|
-
children: [
|
231
|
-
{
|
232
|
-
id: :one,
|
233
|
-
klass: Object,
|
234
|
-
method: :to_s,
|
235
|
-
},
|
236
|
-
{
|
237
|
-
id: :two,
|
238
|
-
klass: Object,
|
239
|
-
method: :to_s,
|
240
|
-
},
|
241
|
-
{
|
242
|
-
id: :three,
|
243
|
-
klass: Object,
|
244
|
-
method: :to_s,
|
245
|
-
},
|
246
|
-
]
|
247
|
-
}
|
248
|
-
end
|
249
|
-
|
250
|
-
let(:child1) { Ultravisor::Child.new(id: :one, klass: Object, method: :to_s) }
|
251
|
-
let(:child2) { Ultravisor::Child.new(id: :two, klass: Object, method: :to_s) }
|
252
|
-
let(:child3) { Ultravisor::Child.new(id: :three, klass: Object, method: :to_s) }
|
253
|
-
|
254
|
-
before(:each) do
|
255
|
-
ultravisor.instance_variable_set(:@children, [[:one, child1], [:two, child2], [:three, child3]])
|
256
|
-
allow(ultravisor.instance_variable_get(:@queue)).to receive(:pop).and_return(child2, :shutdown)
|
257
|
-
allow(ultravisor).to receive(:sleep)
|
258
|
-
ultravisor.instance_variable_set(:@running_thread, mock_thread)
|
259
|
-
end
|
260
|
-
|
261
|
-
it "shuts down all the other children in reverse order" do
|
262
|
-
expect(child3).to receive(:shutdown).ordered
|
263
|
-
expect(child1).to receive(:shutdown).ordered
|
264
|
-
|
265
|
-
ultravisor.__send__(:process_events)
|
266
|
-
end
|
267
|
-
|
268
|
-
it "starts up all children in order" do
|
269
|
-
expect(child1).to receive(:spawn).ordered
|
270
|
-
expect(child2).to receive(:spawn).ordered
|
271
|
-
expect(child3).to receive(:spawn).ordered
|
272
|
-
|
273
|
-
ultravisor.__send__(:process_events)
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
context "with a rest_for_one strategy" do
|
278
|
-
let(:args) do
|
279
|
-
{
|
280
|
-
strategy: :rest_for_one,
|
281
|
-
children: [
|
282
|
-
{
|
283
|
-
id: :one,
|
284
|
-
klass: Object,
|
285
|
-
method: :to_s,
|
286
|
-
},
|
287
|
-
{
|
288
|
-
id: :two,
|
289
|
-
klass: Object,
|
290
|
-
method: :to_s,
|
291
|
-
},
|
292
|
-
{
|
293
|
-
id: :three,
|
294
|
-
klass: Object,
|
295
|
-
method: :to_s,
|
296
|
-
},
|
297
|
-
{
|
298
|
-
id: :four,
|
299
|
-
klass: Object,
|
300
|
-
method: :to_s,
|
301
|
-
},
|
302
|
-
]
|
303
|
-
}
|
304
|
-
end
|
305
|
-
|
306
|
-
let(:child1) { Ultravisor::Child.new(id: :one, klass: Object, method: :to_s) }
|
307
|
-
let(:child2) { Ultravisor::Child.new(id: :two, klass: Object, method: :to_s) }
|
308
|
-
let(:child3) { Ultravisor::Child.new(id: :three, klass: Object, method: :to_s) }
|
309
|
-
let(:child4) { Ultravisor::Child.new(id: :four, klass: Object, method: :to_s) }
|
310
|
-
|
311
|
-
before(:each) do
|
312
|
-
ultravisor.instance_variable_set(:@children, [[:one, child1], [:two, child2], [:three, child3], [:four, child4]])
|
313
|
-
allow(ultravisor.instance_variable_get(:@queue)).to receive(:pop).and_return(child2, :shutdown)
|
314
|
-
allow(ultravisor).to receive(:sleep)
|
315
|
-
ultravisor.instance_variable_set(:@running_thread, mock_thread)
|
316
|
-
end
|
317
|
-
|
318
|
-
it "shuts down only the children after the failed one, in reverse order" do
|
319
|
-
expect(child4).to receive(:shutdown).ordered
|
320
|
-
expect(child3).to receive(:shutdown).ordered
|
321
|
-
|
322
|
-
ultravisor.__send__(:process_events)
|
323
|
-
end
|
324
|
-
|
325
|
-
it "starts up all the relevant children in order" do
|
326
|
-
expect(child2).to receive(:spawn).ordered
|
327
|
-
expect(child3).to receive(:spawn).ordered
|
328
|
-
expect(child4).to receive(:spawn).ordered
|
329
|
-
|
330
|
-
ultravisor.__send__(:process_events)
|
331
|
-
end
|
332
|
-
end
|
333
|
-
end
|
334
|
-
end
|
@@ -1,106 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative "../spec_helper"
|
3
|
-
|
4
|
-
require_relative "../../lib/ultravisor"
|
5
|
-
|
6
|
-
describe Ultravisor do
|
7
|
-
let(:args) { {} }
|
8
|
-
let(:ultravisor) { Ultravisor.new(**args) }
|
9
|
-
let(:mock_thread) { instance_double(Thread) }
|
10
|
-
|
11
|
-
describe "#shutdown" do
|
12
|
-
it "takes the @op_m lock" do
|
13
|
-
expect(ultravisor.instance_variable_get(:@op_m)).to receive(:synchronize).and_call_original
|
14
|
-
|
15
|
-
ultravisor.shutdown
|
16
|
-
end
|
17
|
-
|
18
|
-
context "when the ultravisor isn't running" do
|
19
|
-
it "returns itself" do
|
20
|
-
expect(ultravisor.shutdown).to eq(ultravisor)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "when the ultravisor is running" do
|
25
|
-
before(:each) do
|
26
|
-
ultravisor.instance_variable_set(:@running_thread, mock_thread)
|
27
|
-
allow(ultravisor.instance_variable_get(:@op_cv))
|
28
|
-
.to receive(:wait) do
|
29
|
-
ultravisor.instance_variable_set(:@running_thread, nil)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it "signals the ultravisor to shutdown" do
|
34
|
-
expect(ultravisor.instance_variable_get(:@queue)).to receive(:<<).with(:shutdown)
|
35
|
-
|
36
|
-
ultravisor.shutdown
|
37
|
-
end
|
38
|
-
|
39
|
-
it "waits until the CV is signalled" do
|
40
|
-
expect(ultravisor.instance_variable_get(:@op_cv)).to receive(:wait) do |m|
|
41
|
-
expect(m).to eq(ultravisor.instance_variable_get(:@op_m))
|
42
|
-
ultravisor.instance_variable_set(:@running_thread, nil)
|
43
|
-
nil
|
44
|
-
end
|
45
|
-
|
46
|
-
ultravisor.shutdown
|
47
|
-
end
|
48
|
-
|
49
|
-
context "when asked to not wait" do
|
50
|
-
it "doesn't wait on the CV" do
|
51
|
-
expect(ultravisor.instance_variable_get(:@op_cv)).to_not receive(:wait)
|
52
|
-
|
53
|
-
ultravisor.shutdown(wait: false)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
it "returns itself" do
|
58
|
-
expect(ultravisor.shutdown).to eq(ultravisor)
|
59
|
-
end
|
60
|
-
|
61
|
-
context "when forced" do
|
62
|
-
before(:each) do
|
63
|
-
allow(mock_thread).to receive(:kill)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "kills the thread" do
|
67
|
-
expect(mock_thread).to receive(:kill)
|
68
|
-
|
69
|
-
ultravisor.shutdown(force: true)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "tells everyone waiting for the shutdown that the deed is done" do
|
73
|
-
expect(ultravisor.instance_variable_get(:@op_cv)).to receive(:broadcast)
|
74
|
-
|
75
|
-
ultravisor.shutdown(force: true)
|
76
|
-
end
|
77
|
-
|
78
|
-
it "unsets the running thread" do
|
79
|
-
ultravisor.shutdown(force: true)
|
80
|
-
|
81
|
-
expect(ultravisor.instance_variable_get(:@running_thread)).to be(nil)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "doesn't wait on the CV" do
|
85
|
-
expect(ultravisor.instance_variable_get(:@op_cv)).to_not receive(:wait)
|
86
|
-
|
87
|
-
ultravisor.shutdown(force: true)
|
88
|
-
end
|
89
|
-
|
90
|
-
context "with children" do
|
91
|
-
let(:child) { Ultravisor::Child.new(id: :one, klass: Object, method: :to_s) }
|
92
|
-
|
93
|
-
before(:each) do
|
94
|
-
ultravisor.instance_variable_set(:@children, [[:child, child]])
|
95
|
-
end
|
96
|
-
|
97
|
-
it "forcibly shuts down the children" do
|
98
|
-
expect(child).to receive(:shutdown).with(force: true)
|
99
|
-
|
100
|
-
ultravisor.shutdown(force: true)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|