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.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -2
  3. data/.rubocop.yml +114 -9
  4. data/.travis.yml +11 -0
  5. data/README.md +153 -279
  6. data/lib/service_skeleton/background_worker.rb +80 -0
  7. data/lib/service_skeleton/config.rb +18 -78
  8. data/lib/service_skeleton/config_variable.rb +8 -29
  9. data/lib/service_skeleton/config_variables.rb +68 -54
  10. data/lib/service_skeleton/error.rb +3 -5
  11. data/lib/service_skeleton/filtering_logger.rb +0 -2
  12. data/lib/service_skeleton/logging_helpers.rb +3 -10
  13. data/lib/service_skeleton/metrics_methods.rb +13 -28
  14. data/lib/service_skeleton/signal_handler.rb +183 -0
  15. data/lib/service_skeleton.rb +145 -22
  16. data/service_skeleton.gemspec +9 -10
  17. metadata +19 -102
  18. data/.editorconfig +0 -7
  19. data/.git-blame-ignore-revs +0 -2
  20. data/.github/workflows/ci.yml +0 -50
  21. data/lib/service_skeleton/config_class.rb +0 -16
  22. data/lib/service_skeleton/config_variable/boolean.rb +0 -21
  23. data/lib/service_skeleton/config_variable/enum.rb +0 -27
  24. data/lib/service_skeleton/config_variable/float.rb +0 -25
  25. data/lib/service_skeleton/config_variable/integer.rb +0 -25
  26. data/lib/service_skeleton/config_variable/kv_list.rb +0 -26
  27. data/lib/service_skeleton/config_variable/path_list.rb +0 -13
  28. data/lib/service_skeleton/config_variable/string.rb +0 -18
  29. data/lib/service_skeleton/config_variable/url.rb +0 -36
  30. data/lib/service_skeleton/config_variable/yaml_file.rb +0 -42
  31. data/lib/service_skeleton/generator.rb +0 -165
  32. data/lib/service_skeleton/metric_method_name.rb +0 -9
  33. data/lib/service_skeleton/runner.rb +0 -46
  34. data/lib/service_skeleton/service_name.rb +0 -20
  35. data/lib/service_skeleton/signal_manager.rb +0 -202
  36. data/lib/service_skeleton/signals_methods.rb +0 -15
  37. data/lib/service_skeleton/ultravisor_children.rb +0 -20
  38. data/lib/service_skeleton/ultravisor_loggerstash.rb +0 -11
  39. data/ultravisor/.yardopts +0 -1
  40. data/ultravisor/Guardfile +0 -9
  41. data/ultravisor/README.md +0 -404
  42. data/ultravisor/lib/ultravisor/child/call.rb +0 -21
  43. data/ultravisor/lib/ultravisor/child/call_receiver.rb +0 -14
  44. data/ultravisor/lib/ultravisor/child/cast.rb +0 -16
  45. data/ultravisor/lib/ultravisor/child/cast_receiver.rb +0 -11
  46. data/ultravisor/lib/ultravisor/child/process_cast_call.rb +0 -39
  47. data/ultravisor/lib/ultravisor/child.rb +0 -481
  48. data/ultravisor/lib/ultravisor/error.rb +0 -25
  49. data/ultravisor/lib/ultravisor/logging_helpers.rb +0 -32
  50. data/ultravisor/lib/ultravisor.rb +0 -216
  51. data/ultravisor/spec/example_group_methods.rb +0 -19
  52. data/ultravisor/spec/example_methods.rb +0 -8
  53. data/ultravisor/spec/spec_helper.rb +0 -52
  54. data/ultravisor/spec/ultravisor/add_child_spec.rb +0 -79
  55. data/ultravisor/spec/ultravisor/child/call_spec.rb +0 -121
  56. data/ultravisor/spec/ultravisor/child/cast_spec.rb +0 -111
  57. data/ultravisor/spec/ultravisor/child/id_spec.rb +0 -21
  58. data/ultravisor/spec/ultravisor/child/new_spec.rb +0 -152
  59. data/ultravisor/spec/ultravisor/child/restart_delay_spec.rb +0 -40
  60. data/ultravisor/spec/ultravisor/child/restart_spec.rb +0 -70
  61. data/ultravisor/spec/ultravisor/child/run_spec.rb +0 -95
  62. data/ultravisor/spec/ultravisor/child/shutdown_spec.rb +0 -124
  63. data/ultravisor/spec/ultravisor/child/spawn_spec.rb +0 -107
  64. data/ultravisor/spec/ultravisor/child/unsafe_instance_spec.rb +0 -55
  65. data/ultravisor/spec/ultravisor/child/wait_spec.rb +0 -32
  66. data/ultravisor/spec/ultravisor/new_spec.rb +0 -71
  67. data/ultravisor/spec/ultravisor/remove_child_spec.rb +0 -49
  68. data/ultravisor/spec/ultravisor/run_spec.rb +0 -334
  69. data/ultravisor/spec/ultravisor/shutdown_spec.rb +0 -106
@@ -1,152 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- let(:child) { Ultravisor::Child.new(**args) }
10
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end; def sigterm; end } } }
11
-
12
- describe ".new" do
13
- context "with minimal arguments" do
14
- let(:args) { { id: :bob, klass: mock_class, method: :run } }
15
-
16
- it "does not explode" do
17
- expect { Ultravisor::Child.new(**args) }.to_not raise_error
18
- end
19
-
20
- it "does not instantiate an instance of klass" do
21
- expect(mock_class).to_not receive(:new)
22
-
23
- Ultravisor::Child.new(**args)
24
- end
25
- end
26
-
27
- context "with defined args" do
28
- let(:args) { { id: :bob, klass: mock_class, args: [foo: "bar"], method: :run } }
29
-
30
- it "explodes" do
31
- expect { Ultravisor::Child.new(**args) }.to raise_error(Ultravisor::InvalidKAMError)
32
- end
33
- end
34
-
35
- context "with a class that takes args" do
36
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def initialize(*x); end } } }
37
- let(:args) { { id: :testy, klass: mock_class, args: [1, 2, 3], method: :to_s } }
38
-
39
- it "doesn't explode" do
40
- expect { Ultravisor::Child.new(**args) }.to_not raise_error
41
- end
42
- end
43
-
44
- context "with a non-existent method" do
45
- let(:args) { { id: :testy, klass: mock_class, method: :gogogo } }
46
-
47
- it "explodes" do
48
- expect { Ultravisor::Child.new(**args) }.to raise_error(Ultravisor::InvalidKAMError)
49
- end
50
- end
51
-
52
- context "with a method that takes args" do
53
- let(:args) { { id: :testy, klass: mock_class, method: :public_send } }
54
-
55
- it "explodes" do
56
- expect { Ultravisor::Child.new(**args) }.to raise_error(Ultravisor::InvalidKAMError)
57
- end
58
- end
59
-
60
- context "with a valid restart value" do
61
- it "is fine" do
62
- %i{always on_failure never}.each do |v|
63
- expect { Ultravisor::Child.new(id: :x, klass: Object, method: :to_s, restart: v) }.to_not raise_error
64
- end
65
- end
66
- end
67
-
68
- context "with an invalid restart value" do
69
- it "explodes" do
70
- [:sometimes, "always", 42, { max: 4 }].each do |v|
71
- expect { Ultravisor::Child.new(id: :x, klass: Object, method: :to_s, restart: v) }.to raise_error(ArgumentError)
72
- end
73
- end
74
- end
75
-
76
- context "with a valid restart_policy" do
77
- it "is happy" do
78
- expect do
79
- Ultravisor::Child.new(id: :rp, klass: Object, method: :to_s, restart_policy: { period: 5, max: 2, delay: 1 })
80
- end.to_not raise_error
81
- end
82
- end
83
-
84
- [
85
- { when: :never },
86
- { period: -1 },
87
- { period: "never" },
88
- { period: :sometimes },
89
- { period: (0..10) },
90
- { max: -1 },
91
- { max: "powers" },
92
- { max: (1..5) },
93
- { delay: -1 },
94
- { delay: "buses" },
95
- { delay: (-1..3) },
96
- { delay: (3..1) },
97
- "whenever you're ready",
98
- ].each do |p|
99
- it "explodes with invalid restart_policy #{p.inspect}" do
100
- expect do
101
- Ultravisor::Child.new(id: :boom, klass: Object, method: :to_s, restart_policy: p)
102
- end.to raise_error(ArgumentError)
103
- end
104
- end
105
-
106
- context "with a valid shutdown spec" do
107
- it "is happy" do
108
- expect do
109
- Ultravisor::Child.new(id: :rp, klass: mock_class, method: :to_s, shutdown: { method: :sigterm, timeout: 2 })
110
- end.to_not raise_error
111
- end
112
- end
113
-
114
- [
115
- { method: "man" },
116
- { method: :send },
117
- { method: :nonexistent_method },
118
- { timeout: -4 },
119
- { timeout: (3..5) },
120
- { timeout: "MC Hammer" },
121
- { woogiewoogie: "boo!" },
122
- "freddie!",
123
- ].each do |s|
124
- it "explodes with invalid shutdown spec #{s.inspect}" do
125
- expect do
126
- Ultravisor::Child.new(id: :boom, klass: Object, method: :to_s, shutdown: s)
127
- end.to raise_error(ArgumentError)
128
- end
129
- end
130
-
131
- context "with castcall enabled" do
132
- it "is happy" do
133
- expect do
134
- Ultravisor::Child.new(id: :castcall, klass: Object, method: :to_s, enable_castcall: true)
135
- end.to_not raise_error
136
- end
137
- end
138
-
139
- [
140
- :bob,
141
- 42,
142
- "unsafe",
143
- { safe: :un },
144
- ].each do |a|
145
- it "explodes with invalid access spec #{a.inspect}" do
146
- expect do
147
- Ultravisor::Child.new(id: :boom, klass: Object, method: :to_s, access: a)
148
- end.to raise_error(ArgumentError)
149
- end
150
- end
151
- end
152
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
-
7
- describe Ultravisor::Child do
8
- let(:base_args) { { id: :bob, klass: mock_class, method: :run } }
9
- let(:child) { Ultravisor::Child.new(**args) }
10
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end } } }
11
-
12
- describe "#restart_delay" do
13
- context "by default" do
14
- let(:args) { base_args }
15
-
16
- it "returns the default delay" do
17
- expect(child.restart_delay).to eq(1)
18
- end
19
- end
20
-
21
- context "with a specified numeric delay" do
22
- let(:args) { base_args.merge(restart_policy: { delay: 3.14159 }) }
23
-
24
- it "returns the specified delay" do
25
- expect(child.restart_delay).to be_within(0.00001).of(3.14159)
26
- end
27
- end
28
-
29
- context "with a delay range" do
30
- let(:args) { base_args.merge(restart_policy: { delay: 2..5 }) }
31
-
32
- it "returns a delay in the given range" do
33
- delays = 10.times.map { child.restart_delay }
34
-
35
- expect(delays.all? { |d| (2..5).include?(d) }).to be(true)
36
- expect(delays.uniq.length).to eq(10)
37
- end
38
- end
39
- end
40
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- let(:base_args) { { id: :bob, klass: Object, method: :to_s } }
10
- let(:child) { Ultravisor::Child.new(**args) }
11
-
12
- describe "#restart?" do
13
- context "when restart: :always" do
14
- # Yes, this is the default, but I do like to be explicit
15
- let(:args) { base_args.merge(restart: :always) }
16
-
17
- it "is true always" do
18
- expect(child.restart?).to be(true)
19
- end
20
- end
21
-
22
- context "when restart: :never" do
23
- let(:args) { base_args.merge(restart: :never) }
24
-
25
- it "is false always" do
26
- expect(child.restart?).to be(false)
27
- end
28
- end
29
-
30
- context "when restart: :on_failure" do
31
- let(:args) { base_args.merge(restart: :on_failure) }
32
-
33
- it "is true if the child terminated with an exception" do
34
- expect(child).to receive(:termination_exception).and_return(Exception.new("boom"))
35
-
36
- expect(child.restart?).to be(true)
37
- end
38
-
39
- it "is false if the child didn't terminate with an exception" do
40
- expect(child).to receive(:termination_exception).and_return(nil)
41
-
42
- expect(child.restart?).to be(false)
43
- end
44
- end
45
-
46
- context "with a restart history that isn't blown" do
47
- let(:args) { base_args.merge(restart: :always, restart_policy: { period: 10, max: 3 }) }
48
-
49
- before(:each) do
50
- child.instance_variable_set(:@runtime_history, [4.99, 4.99, 4.99])
51
- end
52
-
53
- it "still returns true" do
54
- expect(child.restart?).to be(true)
55
- end
56
- end
57
-
58
- context "with a restart history that is blown" do
59
- let(:args) { base_args.merge(restart: :always, restart_policy: { period: 10, max: 2 }) }
60
-
61
- before(:each) do
62
- child.instance_variable_set(:@runtime_history, [4.99, 4.99, 4.99])
63
- end
64
-
65
- it "explodes" do
66
- expect { child.restart? }.to raise_error(Ultravisor::BlownRestartPolicyError)
67
- end
68
- end
69
- end
70
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- let(:child) { Ultravisor::Child.new(**args) }
10
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end } } }
11
- let(:mock_instance) { double(mock_class) } # rubocop:disable RSpec/VerifiedDoubles
12
- let(:term_queue) { instance_double(Queue) }
13
-
14
- describe "#run" do
15
- before(:each) do
16
- allow(term_queue).to receive(:<<)
17
- end
18
-
19
- context "with minimal arguments" do
20
- let(:args) { { id: :bob, klass: mock_class, method: :run } }
21
-
22
- before(:each) do
23
- allow(mock_class).to receive(:new).and_return(mock_instance)
24
- allow(mock_instance).to receive(:run)
25
- end
26
-
27
- it "instantiates the class" do
28
- expect(mock_class).to receive(:new).with(no_args)
29
-
30
- child.spawn(term_queue).wait
31
- end
32
-
33
- it "calls the run method on the class instance" do
34
- expect(mock_instance).to receive(:run).with(no_args)
35
-
36
- child.spawn(term_queue).wait
37
- end
38
-
39
- it "registers the thread it is running in" do
40
- expect(mock_instance).to receive(:run) do
41
- expect(child.instance_variable_get(:@thread)).to eq(Thread.current)
42
- end
43
-
44
- child.spawn(term_queue).wait
45
- end
46
-
47
- it "notes the start time" do
48
- expect(mock_instance).to receive(:run) do
49
- # Can only check @start_time while the child is running, as the
50
- # variable gets nil'd after the run completes
51
- expect(child.instance_variable_get(:@start_time).to_f).to be_within(0.01).of(Time.now.to_f)
52
- end
53
-
54
- child.spawn(term_queue).wait
55
- end
56
-
57
- it "notes the termination value" do
58
- expect(mock_instance).to receive(:run).with(no_args).and_return(42)
59
-
60
- child.spawn(term_queue)
61
-
62
- expect(child.termination_value).to eq(42)
63
- end
64
-
65
- it "tells the ultravisor it terminated" do
66
- expect(term_queue).to receive(:<<).with(child)
67
-
68
- child.spawn(term_queue).wait
69
- end
70
-
71
- context "when the worker object's run method raises an exception" do
72
- before(:each) do
73
- allow(mock_instance).to receive(:run).and_raise(RuntimeError.new("FWACKOOM"))
74
- end
75
-
76
- it "makes a note of the exception" do
77
- child.spawn(term_queue)
78
-
79
- expect(child.termination_exception).to be_a(RuntimeError)
80
- end
81
- end
82
- end
83
-
84
- context "with a worker class that takes args" do
85
- let(:args) { { id: :testy, klass: mock_class, args: ["foo", "bar", baz: "wombat"], method: :run } }
86
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def initialize(*x); end; def run; end } } }
87
-
88
- it "creates the class instance with args" do
89
- expect(mock_class).to receive(:new).with("foo", "bar", baz: "wombat").and_call_original
90
-
91
- child.spawn(term_queue).wait
92
- end
93
- end
94
- end
95
- end
@@ -1,124 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- uses_logger
10
-
11
- let(:base_args) { { id: :bob, klass: mock_class, method: :run } }
12
- let(:child) { Ultravisor::Child.new(**args) }
13
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end; def sigterm; end } } }
14
- let(:mock_instance) { instance_double(mock_class) }
15
- let(:term_queue) { instance_double(Queue) }
16
-
17
- describe "#shutdown" do
18
- let(:args) { base_args }
19
-
20
- context "when the child isn't running" do
21
- it "returns immediately" do
22
- child.shutdown
23
- end
24
- end
25
-
26
- context "when the child is running" do
27
- before(:each) do
28
- orig_thread_new = Thread.method(:new)
29
- allow(Thread).to receive(:new) do |&b|
30
- orig_thread_new.call(&b).tap do |th|
31
- @thread = th
32
- allow(th).to receive(:kill).and_call_original
33
- allow(th).to receive(:join).and_call_original
34
- end
35
- end
36
-
37
- allow(mock_class).to receive(:new).and_return(mock_instance)
38
- allow(mock_instance).to receive(:run)
39
-
40
- allow(term_queue).to receive(:<<)
41
- end
42
-
43
- it "kills the thread" do
44
- child.spawn(term_queue).shutdown
45
-
46
- expect(@thread).to have_received(:kill)
47
- end
48
-
49
- it "waits for the thread to be done" do
50
- child.spawn(term_queue).shutdown
51
-
52
- expect(@thread).to have_received(:join).with(1)
53
- end
54
-
55
- it "doesn't put anything on the queue" do
56
- expect(term_queue).to_not receive(:<<)
57
-
58
- child.spawn(term_queue).shutdown
59
- end
60
-
61
- context "when there's a shutdown spec" do
62
- let(:args) { base_args.merge(shutdown: { method: :sigterm, timeout: 0.05 }) }
63
-
64
- before(:each) do
65
- allow(mock_instance).to receive(:sigterm)
66
- end
67
-
68
- it "calls the specified shutdown method" do
69
- expect(mock_instance).to receive(:sigterm)
70
-
71
- child.spawn(term_queue).shutdown
72
- end
73
-
74
- it "waits for up to the timeout period" do
75
- child.spawn(term_queue).shutdown
76
-
77
- expect(@thread).to have_received(:join).with(0.05)
78
- end
79
-
80
- context "the worker doesn't finish quickly enough" do
81
- before(:each) do
82
- allow(mock_instance).to receive(:run) { sleep 15 }
83
- end
84
-
85
- it "kills the thread" do
86
- child.spawn(term_queue).shutdown
87
-
88
- expect(@thread).to have_received(:kill)
89
- end
90
- end
91
- end
92
-
93
- context "when the thread infinihangs" do
94
- # No need for a big timeout, we know it's not going to succeed
95
- let(:args) { base_args.merge(shutdown: { timeout: 0.000001 }) }
96
- let(:m) { Mutex.new }
97
- let(:cv) { ConditionVariable.new }
98
-
99
- before(:each) do
100
- allow(mock_instance).to receive(:run) do
101
- Thread.handle_interrupt(Numeric => :never) do
102
- m.synchronize do
103
- @state = 1
104
- cv.signal
105
- cv.wait(m) until @state == 2
106
- end
107
- end
108
- end
109
-
110
- allow(logger).to receive(:error)
111
- end
112
-
113
- it "logs an error" do
114
- expect(logger).to receive(:error)
115
-
116
- child.spawn(term_queue)
117
- m.synchronize { cv.wait(m) until @state == 1 }
118
- child.shutdown
119
- m.synchronize { @state = 2; cv.signal }
120
- end
121
- end
122
- end
123
- end
124
- end
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- let(:child) { Ultravisor::Child.new(**args) }
10
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end } } }
11
- let(:mock_instance) { double(mock_class) } # rubocop:disable RSpec/VerifiedDoubles
12
- let(:term_queue) { instance_double(Queue) }
13
-
14
- describe "#spawn" do
15
- before(:each) do
16
- allow(term_queue).to receive(:<<)
17
- end
18
-
19
- context "with minimal arguments" do
20
- let(:args) { { id: :bob, klass: mock_class, method: :run } }
21
-
22
- before(:each) do
23
- allow(mock_class).to receive(:new).and_return(mock_instance)
24
- allow(mock_instance).to receive(:run)
25
- end
26
-
27
- it "instantiates the class" do
28
- expect(mock_class).to receive(:new).with(no_args)
29
-
30
- child.spawn(term_queue).wait
31
- end
32
-
33
- it "calls the run method on the class instance" do
34
- expect(mock_instance).to receive(:run).with(no_args)
35
-
36
- child.spawn(term_queue).wait
37
- end
38
-
39
- it "registers the thread it is running in" do
40
- expect(mock_instance).to receive(:run) do
41
- expect(child.instance_variable_get(:@thread)).to eq(Thread.current)
42
- end
43
-
44
- child.spawn(term_queue).wait
45
- end
46
-
47
- it "notes the start time" do
48
- expect(mock_instance).to receive(:run) do
49
- # Can only check @start_time while the child is running, as the
50
- # variable gets nil'd after the run completes
51
- expect(child.instance_variable_get(:@start_time).to_f).to be_within(0.01).of(Time.now.to_f)
52
- end
53
-
54
- child.spawn(term_queue).wait
55
- end
56
-
57
- it "notes the termination value" do
58
- expect(mock_instance).to receive(:run).with(no_args).and_return(42)
59
-
60
- child.spawn(term_queue)
61
-
62
- expect(child.termination_value).to eq(42)
63
- end
64
-
65
- it "tells the ultravisor it terminated" do
66
- expect(term_queue).to receive(:<<).with(child)
67
-
68
- child.spawn(term_queue).wait
69
- end
70
-
71
- it "creates a new thread" do
72
- expect(Thread).to receive(:new)
73
-
74
- child.spawn(term_queue).wait
75
- end
76
-
77
- context "when the worker object's run method raises an exception" do
78
- before(:each) do
79
- allow(mock_instance).to receive(:run).and_raise(RuntimeError.new("FWACKOOM"))
80
- end
81
-
82
- it "makes a note of the exception" do
83
- child.spawn(term_queue)
84
-
85
- expect(child.termination_exception).to be_a(RuntimeError)
86
- end
87
-
88
- it "tells the ultravisor it terminated" do
89
- expect(term_queue).to receive(:<<).with(child)
90
-
91
- child.spawn(term_queue).wait
92
- end
93
- end
94
- end
95
-
96
- context "with a worker class that takes args" do
97
- let(:args) { { id: :testy, klass: mock_class, args: ["foo", "bar", baz: "wombat"], method: :run } }
98
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def initialize(*x); end; def run; end } } }
99
-
100
- it "creates the class instance with args" do
101
- expect(mock_class).to receive(:new).with("foo", "bar", baz: "wombat").and_call_original
102
-
103
- child.spawn(term_queue).wait
104
- end
105
- end
106
- end
107
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- let(:args) { { id: :bob, klass: Object, method: :to_s } }
10
- let(:child) { Ultravisor::Child.new(**args) }
11
-
12
- describe "#unsafe_instance" do
13
- context "by default" do
14
- it "explodes" do
15
- expect { child.unsafe_instance }.to raise_error(Ultravisor::ThreadSafetyError)
16
- end
17
- end
18
-
19
- context "with access: :unsafe" do
20
- let(:args) { { id: :bob, klass: Object, method: :to_s, access: :unsafe } }
21
-
22
- context "when there's no instance object" do
23
- it "waits for the instance object to appear" do
24
- expect(child.instance_variable_get(:@spawn_cv)).to receive(:wait) do
25
- child.instance_variable_set(:@instance, "gogogo")
26
- end
27
-
28
- child.unsafe_instance
29
- end
30
- end
31
-
32
- context "when there's an instance object" do
33
- before(:each) do
34
- child.instance_variable_set(:@instance, "bob")
35
- end
36
-
37
- it "returns the instance object" do
38
- expect(child.unsafe_instance).to eq("bob")
39
- end
40
- end
41
- end
42
-
43
- context "when the child is running" do
44
- it "only exits once the child has finished" do
45
- child.instance_variable_set(:@thread, Thread.new {})
46
-
47
- expect(child.instance_variable_get(:@spawn_cv)).to receive(:wait).with(child.instance_variable_get(:@spawn_m)) do
48
- child.instance_variable_set(:@thread, nil)
49
- end
50
-
51
- child.wait
52
- end
53
- end
54
- end
55
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- require_relative "../../../lib/ultravisor/child"
6
- require_relative "../../../lib/ultravisor/error"
7
-
8
- describe Ultravisor::Child do
9
- let(:args) { { id: :bob, klass: mock_class, method: :run } }
10
- let(:child) { Ultravisor::Child.new(**args) }
11
- let(:mock_class) { Class.new.tap { |k| k.class_eval { def run; end } } }
12
-
13
- describe "#wait" do
14
- context "when the child isn't running" do
15
- it "just returns straight away" do
16
- child.wait
17
- end
18
- end
19
-
20
- context "when the child is running" do
21
- it "only exits once the child has finished" do
22
- child.instance_variable_set(:@thread, Thread.new {})
23
-
24
- expect(child.instance_variable_get(:@spawn_cv)).to receive(:wait).with(child.instance_variable_get(:@spawn_m)) do
25
- child.instance_variable_set(:@thread, nil)
26
- end
27
-
28
- child.wait
29
- end
30
- end
31
- end
32
- end