celluloid 0.18.0.pre → 0.18.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +114 -39
  3. data/CONDUCT.md +13 -0
  4. data/CONTRIBUTING.md +39 -0
  5. data/README.md +59 -55
  6. data/architecture.md +120 -0
  7. data/examples/basic_usage.rb +1 -1
  8. data/examples/configurations.rb +78 -0
  9. data/examples/futures.rb +1 -1
  10. data/examples/ring.rb +5 -4
  11. data/examples/simple_pmap.rb +1 -1
  12. data/examples/stack.rb +2 -2
  13. data/examples/supervisors_and_registry.rb +82 -0
  14. data/examples/timers.rb +1 -1
  15. data/lib/celluloid.rb +72 -47
  16. data/lib/celluloid/actor.rb +27 -17
  17. data/lib/celluloid/actor/system.rb +13 -29
  18. data/lib/celluloid/autostart.rb +5 -5
  19. data/lib/celluloid/backported.rb +6 -2
  20. data/lib/celluloid/call/async.rb +2 -0
  21. data/lib/celluloid/call/sync.rb +10 -3
  22. data/lib/celluloid/calls.rb +5 -12
  23. data/lib/celluloid/cell.rb +5 -9
  24. data/lib/celluloid/condition.rb +3 -3
  25. data/lib/celluloid/core_ext.rb +0 -2
  26. data/lib/celluloid/current.rb +3 -1
  27. data/lib/celluloid/debug.rb +3 -0
  28. data/lib/celluloid/exceptions.rb +2 -2
  29. data/lib/celluloid/future.rb +7 -9
  30. data/lib/celluloid/group.rb +12 -8
  31. data/lib/celluloid/group/pool.rb +1 -3
  32. data/lib/celluloid/group/spawner.rb +2 -6
  33. data/lib/celluloid/internals/call_chain.rb +15 -0
  34. data/lib/celluloid/internals/cpu_counter.rb +62 -0
  35. data/lib/celluloid/internals/handlers.rb +42 -0
  36. data/lib/celluloid/internals/links.rb +38 -0
  37. data/lib/celluloid/internals/logger.rb +104 -0
  38. data/lib/celluloid/internals/method.rb +34 -0
  39. data/lib/celluloid/internals/properties.rb +32 -0
  40. data/lib/celluloid/internals/receivers.rb +64 -0
  41. data/lib/celluloid/internals/registry.rb +102 -0
  42. data/lib/celluloid/internals/responses.rb +46 -0
  43. data/lib/celluloid/internals/signals.rb +24 -0
  44. data/lib/celluloid/internals/stack.rb +74 -0
  45. data/lib/celluloid/internals/stack/dump.rb +12 -0
  46. data/lib/celluloid/internals/stack/states.rb +72 -0
  47. data/lib/celluloid/internals/stack/summary.rb +12 -0
  48. data/lib/celluloid/internals/task_set.rb +51 -0
  49. data/lib/celluloid/internals/thread_handle.rb +52 -0
  50. data/lib/celluloid/internals/uuid.rb +40 -0
  51. data/lib/celluloid/logging/incident.rb +21 -0
  52. data/lib/celluloid/logging/incident_logger.rb +147 -0
  53. data/lib/celluloid/logging/incident_reporter.rb +49 -0
  54. data/lib/celluloid/logging/log_event.rb +20 -0
  55. data/lib/celluloid/logging/ring_buffer.rb +64 -0
  56. data/lib/celluloid/mailbox.rb +22 -9
  57. data/lib/celluloid/mailbox/evented.rb +13 -5
  58. data/lib/celluloid/managed.rb +6 -3
  59. data/lib/celluloid/notifications.rb +95 -0
  60. data/lib/celluloid/pool.rb +6 -0
  61. data/lib/celluloid/probe.rb +81 -0
  62. data/lib/celluloid/proxy/abstract.rb +9 -9
  63. data/lib/celluloid/proxy/async.rb +1 -1
  64. data/lib/celluloid/proxy/block.rb +2 -2
  65. data/lib/celluloid/proxy/cell.rb +1 -1
  66. data/lib/celluloid/proxy/future.rb +2 -4
  67. data/lib/celluloid/proxy/sync.rb +1 -3
  68. data/lib/celluloid/rspec.rb +22 -33
  69. data/lib/celluloid/supervision.rb +17 -0
  70. data/lib/celluloid/supervision/configuration.rb +169 -0
  71. data/lib/celluloid/supervision/configuration/injections.rb +8 -0
  72. data/lib/celluloid/supervision/configuration/instance.rb +113 -0
  73. data/lib/celluloid/supervision/constants.rb +123 -0
  74. data/lib/celluloid/supervision/container.rb +144 -0
  75. data/lib/celluloid/supervision/container/behavior.rb +89 -0
  76. data/lib/celluloid/supervision/container/behavior/pool.rb +71 -0
  77. data/lib/celluloid/supervision/container/behavior/tree.rb +23 -0
  78. data/lib/celluloid/supervision/container/injections.rb +8 -0
  79. data/lib/celluloid/supervision/container/instance.rb +116 -0
  80. data/lib/celluloid/supervision/container/pool.rb +210 -0
  81. data/{culture/rubocop/perf.yml → lib/celluloid/supervision/container/tree.rb} +0 -0
  82. data/lib/celluloid/supervision/deprecate.rb +9 -0
  83. data/lib/celluloid/supervision/deprecate/supervise.rb +105 -0
  84. data/lib/celluloid/supervision/deprecate/validation.rb +54 -0
  85. data/lib/celluloid/supervision/service.rb +27 -0
  86. data/lib/celluloid/supervision/supervise.rb +34 -0
  87. data/lib/celluloid/supervision/validation.rb +40 -0
  88. data/lib/celluloid/supervision/version.rb +5 -0
  89. data/lib/celluloid/system_events.rb +11 -6
  90. data/lib/celluloid/task.rb +25 -12
  91. data/lib/celluloid/task/fibered.rb +2 -0
  92. data/lib/celluloid/task/threaded.rb +3 -3
  93. data/lib/celluloid/test.rb +5 -2
  94. data/lib/celluloid/thread.rb +0 -2
  95. data/lib/celluloid/version.rb +1 -1
  96. data/spec/celluloid/block_spec.rb +29 -32
  97. data/spec/celluloid/calls_spec.rb +5 -15
  98. data/spec/celluloid/future_spec.rb +2 -2
  99. data/spec/celluloid/internals/cpu_counter_spec.rb +129 -0
  100. data/spec/celluloid/internals/links_spec.rb +43 -0
  101. data/spec/celluloid/internals/properties_spec.rb +40 -0
  102. data/spec/celluloid/internals/registry_spec.rb +62 -0
  103. data/spec/celluloid/internals/stack/dump_spec.rb +4 -0
  104. data/spec/celluloid/internals/stack/summary_spec.rb +4 -0
  105. data/spec/celluloid/internals/thread_handle_spec.rb +60 -0
  106. data/spec/celluloid/internals/uuid_spec.rb +9 -0
  107. data/spec/celluloid/logging/ring_buffer_spec.rb +36 -0
  108. data/spec/celluloid/mailbox/evented_spec.rb +11 -22
  109. data/spec/celluloid/misc/leak_spec.rb +3 -4
  110. data/spec/celluloid/notifications_spec.rb +140 -0
  111. data/spec/celluloid/probe_spec.rb +102 -0
  112. data/spec/celluloid/proxy_spec.rb +30 -30
  113. data/spec/celluloid/supervision/behavior_spec.rb +74 -0
  114. data/spec/celluloid/supervision/configuration_spec.rb +181 -0
  115. data/spec/celluloid/supervision/container_spec.rb +72 -0
  116. data/spec/celluloid/supervision/instance_spec.rb +13 -0
  117. data/spec/celluloid/supervision/root_spec.rb +28 -0
  118. data/spec/celluloid/supervision/supervisor_spec.rb +93 -0
  119. data/spec/celluloid/task/fibered_spec.rb +1 -3
  120. data/spec/celluloid/task/threaded_spec.rb +1 -3
  121. data/spec/shared/actor_examples.rb +58 -33
  122. data/spec/shared/group_examples.rb +2 -2
  123. data/spec/shared/mailbox_examples.rb +1 -1
  124. data/spec/shared/stack_examples.rb +87 -0
  125. data/spec/shared/task_examples.rb +2 -3
  126. data/spec/spec_helper.rb +2 -4
  127. data/spec/support/configure_rspec.rb +2 -3
  128. data/spec/support/coverage.rb +2 -4
  129. data/spec/support/crash_checking.rb +2 -2
  130. data/spec/support/examples/actor_class.rb +3 -8
  131. data/spec/support/examples/call_class.rb +2 -2
  132. data/spec/support/examples/container_class.rb +35 -0
  133. data/spec/support/examples/evented_mailbox_class.rb +1 -2
  134. data/spec/support/examples/stack_classes.rb +58 -0
  135. data/spec/support/examples/stack_methods.rb +23 -0
  136. data/spec/support/examples/subordinate_class.rb +19 -0
  137. data/spec/support/logging.rb +2 -34
  138. data/spec/support/loose_threads.rb +3 -16
  139. data/spec/support/reset_class_variables.rb +5 -1
  140. data/spec/support/stubbing.rb +1 -1
  141. metadata +91 -316
  142. data/culture/CONDUCT.md +0 -38
  143. data/culture/GSoC/1010-why_we_will_participate.md +0 -17
  144. data/culture/GSoC/1020-how_mentors_stay_engaged.md +0 -7
  145. data/culture/GSoC/1030-keeping_students_on_schedule.md +0 -9
  146. data/culture/GSoC/1040-getting_students_involved.md +0 -5
  147. data/culture/GSoC/1050-student_involvement_after.md +0 -5
  148. data/culture/GSoC/README.md +0 -16
  149. data/culture/Gemfile +0 -9
  150. data/culture/LICENSE.txt +0 -22
  151. data/culture/README.md +0 -22
  152. data/culture/Rakefile +0 -5
  153. data/culture/SYNC.md +0 -70
  154. data/culture/celluloid-culture.gemspec +0 -18
  155. data/culture/gems/README.md +0 -39
  156. data/culture/gems/dependencies.yml +0 -93
  157. data/culture/gems/loader.rb +0 -101
  158. data/culture/rubocop/README.md +0 -38
  159. data/culture/rubocop/lint.yml +0 -8
  160. data/culture/rubocop/metrics.yml +0 -15
  161. data/culture/rubocop/rubocop.yml +0 -5
  162. data/culture/rubocop/style.yml +0 -61
  163. data/culture/spec/gems_spec.rb +0 -2
  164. data/culture/spec/spec_helper.rb +0 -0
  165. data/culture/spec/sync_spec.rb +0 -2
  166. data/culture/sync.rb +0 -56
  167. data/culture/tasks/rspec.rake +0 -5
  168. data/culture/tasks/rubocop.rake +0 -2
  169. data/lib/celluloid/actor/manager.rb +0 -7
  170. data/lib/celluloid/deprecate.rb +0 -34
  171. data/lib/celluloid/fiber.rb +0 -32
  172. data/lib/celluloid/notices.rb +0 -15
  173. data/spec/deprecate/actor_system_spec.rb +0 -72
  174. data/spec/deprecate/block_spec.rb +0 -52
  175. data/spec/deprecate/calls_spec.rb +0 -39
  176. data/spec/deprecate/evented_mailbox_spec.rb +0 -34
  177. data/spec/deprecate/future_spec.rb +0 -32
  178. data/spec/deprecate/internal_pool_spec.rb +0 -4
  179. data/spec/support/env.rb +0 -21
@@ -0,0 +1,181 @@
1
+ RSpec.describe Celluloid::Supervision::Configuration, actor_system: :global do
2
+ class TestActor
3
+ include Celluloid
4
+ def identity
5
+ :testing
6
+ end
7
+ end
8
+
9
+ let(:succeeding) do
10
+ {
11
+ as: :testing,
12
+ type: TestActor
13
+ }
14
+ end
15
+
16
+ let(:failing) do
17
+ {
18
+ as: :testing,
19
+ type: TestActor,
20
+ args: [:fail]
21
+ }
22
+ end
23
+
24
+ after(:each) do
25
+ Celluloid::Supervision::Configuration.resync_parameters
26
+ subject.resync_accessors
27
+ end
28
+
29
+ context("remains reusable without being mutated") do
30
+ it("properly") do
31
+ expect(Celluloid.actor_system.root_configuration.export).to eq(Celluloid::Actor::System::ROOT_SERVICES)
32
+ end
33
+ end
34
+
35
+ context("metaprogramming") do
36
+ context("Celluloid.services accessor") do
37
+ it("is dynamically added, and available") do
38
+ expect(Celluloid.services.respond_to?(:supervise)).to be_truthy
39
+ end
40
+ it("allows supervision") do
41
+ Celluloid.services.supervise(type: TestActor, as: :test_actor)
42
+ expect(Celluloid.services.test_actor.identity).to eq(:testing)
43
+ end
44
+ end
45
+
46
+ context("supervised actors can create accessors") do
47
+ it("which are dynamically added, and available as Celluloid.accessor") do
48
+ TestActor.supervise(as: :test_actor, accessors: [:test_actor])
49
+ expect(Celluloid.test_actor.identity).to eq(:testing)
50
+ end
51
+ end
52
+ end
53
+
54
+ context("parameters") do
55
+ context("can be added to") do
56
+ context("can be given new :mandatory parameters") do
57
+ before(:each) do
58
+ Celluloid::Supervision::Configuration.parameter! :mandatory, :special_requirement
59
+ subject.resync_accessors
60
+ end
61
+
62
+ it("programmatically") do
63
+ expect(Celluloid::Supervision::Configuration.parameters(:mandatory)).to include(:special_requirement)
64
+ end
65
+
66
+ it("and respond appropriately") do
67
+ subject.resync_accessors
68
+ expect(subject.methods).to include(:special_requirement)
69
+ expect(subject.respond_to?(:special_requirement!)).to be_truthy
70
+ expect(subject.respond_to?(:special_requirement?)).to be_truthy
71
+ expect(subject.respond_to?(:special_requirement=)).to be_truthy
72
+ expect(subject.respond_to?(:special_requirement)).to be_truthy
73
+ end
74
+
75
+ it("and instances will respond appropriately") do
76
+ subject.instances.first.resync_accessors
77
+ subject.define(type: TestActor, special_requirement: :valid)
78
+ expect(subject.respond_to?(:special_requirement)).to be_truthy
79
+ end
80
+
81
+ it("and be reset to defaults") do
82
+ Celluloid::Supervision::Configuration.resync_parameters
83
+ expect(Celluloid::Supervision::Configuration.parameters(:mandatory)).not_to include(:special_requirement)
84
+ end
85
+ end
86
+
87
+ context("can be aliased") do
88
+ before(:each) do
89
+ Celluloid::Supervision::Configuration.resync_parameters
90
+ Celluloid::Supervision::Configuration.alias! :nick, :as
91
+ subject.resync_accessors
92
+ end
93
+
94
+ it("programmatically") do
95
+ expect(Celluloid::Supervision::Configuration.aliases.keys).to include(:nick)
96
+ end
97
+
98
+ it("and respond appropriately by method") do
99
+ subject.define(type: TestActor, as: :test_name)
100
+ expect(subject.respond_to?(:nick!)).to be_truthy
101
+ expect(subject.respond_to?(:nick?)).to be_truthy
102
+ expect(subject.respond_to?(:nick=)).to be_truthy
103
+ expect(subject.respond_to?(:nick)).to be_truthy
104
+ expect(subject.nick).to eq(:test_name)
105
+ end
106
+
107
+ xit("and respond properly by current_instance, by method") do
108
+ # subject.current_instance[:aliased] gets subject.current_instance[:original]
109
+ end
110
+
111
+ it("and instances will respond properly by method") do
112
+ subject.define(as: :test_name, type: TestActor)
113
+ expect(subject.instances.first.respond_to?(:nick!)).to be_truthy
114
+ expect(subject.instances.first.respond_to?(:nick?)).to be_truthy
115
+ expect(subject.instances.first.respond_to?(:nick=)).to be_truthy
116
+ expect(subject.instances.first.respond_to?(:nick)).to be_truthy
117
+ expect(subject.instances.first.nick).to eq(:test_name)
118
+ end
119
+
120
+ xit("and respond appropriately by key") do
121
+ # subject[:aliased] gets subject[:original]
122
+ end
123
+
124
+ xit("and instances respond properly by current_instance, by key") do
125
+ # subject.instances.first[:aliased] gets subject.instances.first[:original]
126
+ end
127
+
128
+ xit("and instances respond properly by key") do
129
+ # subject.instances.first[:aliased] gets subject.instances.first[:original]
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ context("Configuration.define class method") do
136
+ xit("can take individual instance configuration") do
137
+ end
138
+
139
+ xit("can take array of instance configurations") do
140
+ end
141
+ end
142
+
143
+ context("Configuration#define instance method") do
144
+ xit("can take individual instance configuration") do
145
+ end
146
+
147
+ xit("can take array of instance configurations") do
148
+ end
149
+ end
150
+
151
+ context("Configuration.deploy class method") do
152
+ xit("can take individual instance configuration") do
153
+ end
154
+
155
+ xit("can take array of instance configurations") do
156
+ end
157
+ end
158
+
159
+ context("Configuration#deploy instance method") do
160
+ xit("can take individual instance configuration") do
161
+ end
162
+
163
+ xit("can take array of instance configurations") do
164
+ end
165
+ end
166
+
167
+ context("accessing information") do
168
+ before(:each) { subject.define(succeeding) }
169
+ it("can get values out of current level of configuration by [:key]") do
170
+ expect(subject[:as]).to eq(:testing)
171
+ end
172
+
173
+ it("can get values out of current level of configuration by #key") do
174
+ expect(subject.as).to eq(:testing)
175
+ end
176
+ end
177
+
178
+ it("verifies arity of intended actor's initialize method") do
179
+ expect { subject.define(failing) }.to raise_exception(ArgumentError)
180
+ end
181
+ end
@@ -0,0 +1,72 @@
1
+ RSpec.describe Celluloid::Supervision::Container, actor_system: :global do
2
+ let(:queue_count) { 1 }
3
+
4
+ before do
5
+ SupervisionContainerHelper.reset!
6
+ subject # init for easier debugging
7
+ queue_count.times { SupervisionContainerHelper.pop! }
8
+ end
9
+
10
+ after do
11
+ # TODO: hangs without condition on JRuby?
12
+ subject.terminate if subject.alive?
13
+ end
14
+
15
+ context "when supervising a single actor" do
16
+ subject do
17
+ Class.new(Celluloid::Supervision::Container) do
18
+ supervise type: MyContainerActor, as: :example
19
+ end.run!(*registry)
20
+ end
21
+
22
+ let(:registry) { [] }
23
+
24
+ it "runs applications" do
25
+ expect(Celluloid::Actor[:example]).to be_running
26
+ end
27
+
28
+ context "with a private registry" do
29
+ let(:registry) { Celluloid::Internals::Registry.new }
30
+
31
+ it "accepts a private actor registry" do
32
+ expect(registry[:example]).to be_running
33
+ end
34
+ end
35
+
36
+ it "removes actors from the registry when terminating" do
37
+ subject.terminate
38
+ expect(Celluloid::Actor[:example]).to be_nil
39
+ end
40
+
41
+ it "allows external access to the internal registry" do
42
+ expect(subject[:example]).to be_a MyContainerActor
43
+ end
44
+ end
45
+
46
+ context "with multiple args" do
47
+ subject do
48
+ Class.new(Celluloid::Supervision::Container) do
49
+ supervise type: MyContainerActor, as: :example, args: %i[foo bar]
50
+ end.run!
51
+ end
52
+
53
+ it "passes them" do
54
+ expect(Celluloid::Actor[:example].args).to eq(%i[foo bar])
55
+ end
56
+ end
57
+
58
+ context "with lazy evaluation" do
59
+ subject do
60
+ Class.new(Celluloid::Supervision::Container) do
61
+ supervise type: MyContainerActor, as: :example, args: -> { :lazy }
62
+ end.run!
63
+ end
64
+
65
+ it "evaluates correctly" do
66
+ expect(Celluloid::Actor[:example].args).to eq([:lazy])
67
+ end
68
+ end
69
+
70
+ xit("can remove members") do
71
+ end
72
+ end
@@ -0,0 +1,13 @@
1
+ # RSpec.describe Celluloid::Supervision::Configuration do
2
+ # xit("can be instantiated without a name") {
3
+ # }
4
+ #
5
+ # xit("can be instantiated with a name") {
6
+ # }
7
+ #
8
+ # context("can be terminated") {
9
+ # xit("cleanly") {
10
+ # }
11
+ # }
12
+ # end
13
+ # =
@@ -0,0 +1,28 @@
1
+ RSpec.describe Celluloid::Supervision::Service::Root, actor_system: :global do
2
+ class RootTestingActor
3
+ include Celluloid
4
+ def identity
5
+ :testing
6
+ end
7
+ end
8
+
9
+ before(:all) do
10
+ Celluloid::Supervision::Configuration.resync_parameters
11
+ end
12
+
13
+ context("deploys root services") do
14
+ it("properly") do
15
+ expect(Celluloid.actor_system.registered).to eq(Celluloid::Actor::System::ROOT_SERVICES.map { |r| r[:as] })
16
+ end
17
+ end
18
+
19
+ context("makes public services available") do
20
+ it("properly") do
21
+ expect(Celluloid.services.respond_to?(:supervise)).to be_truthy
22
+ end
23
+ it("and accepts one-off actor supervision") do
24
+ RootTestingActor.supervise as: :tester
25
+ expect(Celluloid[:tester].identity).to eq(:testing)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,93 @@
1
+ RSpec.describe "Celluloid supervisor", actor_system: :global do
2
+ let(:logger) { Specs::FakeLogger.current }
3
+
4
+ it "restarts actors when they die" do
5
+ supervisor = Celluloid.supervise(type: Subordinate, args: [:idle])
6
+ subordinate = supervisor.actors.first
7
+ expect(subordinate.state).to be(:idle)
8
+
9
+ subordinate.crack_the_whip
10
+ expect(subordinate.state).to be(:working)
11
+
12
+ allow(logger).to receive(:crash).with("Actor crashed!", SubordinateDead)
13
+
14
+ expect do
15
+ subordinate.crack_the_whip
16
+ end.to raise_exception(SubordinateDead)
17
+ sleep 0.1 # hax to prevent race :(
18
+ expect(subordinate).not_to be_alive
19
+
20
+ new_subordinate = supervisor.actors.first
21
+ expect(new_subordinate).not_to eq subordinate
22
+ expect(new_subordinate.state).to eq :idle
23
+ end
24
+
25
+ it "registers actors and reregisters them when they die" do
26
+ Celluloid.supervise(as: :subordinate, type: Subordinate, args: [:idle])
27
+ subordinate = Celluloid::Actor[:subordinate]
28
+ expect(subordinate.state).to be(:idle)
29
+
30
+ subordinate.crack_the_whip
31
+ expect(subordinate.state).to be(:working)
32
+
33
+ allow(logger).to receive(:crash).with("Actor crashed!", SubordinateDead)
34
+
35
+ expect do
36
+ subordinate.crack_the_whip
37
+ end.to raise_exception(SubordinateDead)
38
+ sleep 0.1 # hax to prevent race :(
39
+ expect(subordinate).not_to be_alive
40
+
41
+ new_subordinate = Celluloid::Actor[:subordinate]
42
+ expect(new_subordinate).not_to eq subordinate
43
+ expect(new_subordinate.state).to eq :idle
44
+ end
45
+
46
+ it "creates supervisors via Actor.supervise" do
47
+ supervisor = Subordinate.supervise(args: [:working])
48
+ subordinate = supervisor.actors.first
49
+ expect(subordinate.state).to be(:working)
50
+
51
+ allow(logger).to receive(:crash).with("Actor crashed!", SubordinateDead)
52
+
53
+ expect do
54
+ subordinate.crack_the_whip
55
+ end.to raise_exception(SubordinateDead, "the spec purposely crashed me :(")
56
+
57
+ sleep 0.1 # hax to prevent race :(
58
+ expect(subordinate).not_to be_alive
59
+
60
+ new_subordinate = supervisor.actors.first
61
+ expect(new_subordinate).not_to eq subordinate
62
+ expect(new_subordinate.state).to eq :working
63
+ end
64
+
65
+ it "creates supervisors and registers actors via Actor.supervise as:" do
66
+ supervisor = Subordinate.supervise(as: :subordinate, args: [:working])
67
+ subordinate = Celluloid::Actor[:subordinate]
68
+ expect(subordinate.state).to be(:working)
69
+
70
+ allow(logger).to receive(:crash).with("Actor crashed!", SubordinateDead)
71
+
72
+ expect do
73
+ subordinate.crack_the_whip
74
+ end.to raise_exception(SubordinateDead)
75
+ sleep 0.1 # hax to prevent race :(
76
+ expect(subordinate).not_to be_alive
77
+
78
+ new_subordinate = supervisor.actors.first
79
+ expect(new_subordinate).not_to eq subordinate
80
+ expect(new_subordinate.state).to be(:working)
81
+ end
82
+
83
+ it "removes an actor if it terminates cleanly" do
84
+ supervisor = Subordinate.supervise(args: [:working])
85
+ subordinate = supervisor.actors.first
86
+
87
+ expect(supervisor.actors).to eq([subordinate])
88
+
89
+ subordinate.terminate
90
+
91
+ expect(supervisor.actors).to be_empty
92
+ end
93
+ end
@@ -1,5 +1,3 @@
1
1
  RSpec.describe Celluloid::Task::Fibered, actor_system: :within do
2
- if Celluloid.task_class == Celluloid::Task::Fibered
3
- it_behaves_like "a Celluloid Task"
4
- end
2
+ it_behaves_like "a Celluloid Task" if Celluloid.task_class == Celluloid::Task::Fibered
5
3
  end
@@ -1,5 +1,3 @@
1
1
  RSpec.describe Celluloid::Task::Threaded, actor_system: :within do
2
- if Celluloid.task_class == Celluloid::Task::Threaded
3
- it_behaves_like "a Celluloid Task"
4
- end
2
+ it_behaves_like "a Celluloid Task" if Celluloid.task_class == Celluloid::Task::Threaded
5
3
  end
@@ -2,7 +2,7 @@ RSpec.shared_examples "a Celluloid Actor" do
2
2
  around do |ex|
3
3
  Celluloid.boot
4
4
  ex.run
5
- Celluloid.shutdown
5
+ Celluloid.shutdown if Celluloid.running?
6
6
  end
7
7
 
8
8
  let(:task_klass) { Celluloid.task_class }
@@ -11,6 +11,12 @@ RSpec.shared_examples "a Celluloid Actor" do
11
11
 
12
12
  let(:logger) { Specs::FakeLogger.current }
13
13
 
14
+ it "doesn't raise an error when rebooting" do
15
+ Celluloid.shutdown
16
+
17
+ expect { Celluloid.boot }.to change { Celluloid.running? }.from(false).to(true)
18
+ end
19
+
14
20
  it "returns the actor's class, not the proxy's" do
15
21
  expect(actor.class).to eq(actor_class)
16
22
  end
@@ -22,24 +28,24 @@ RSpec.shared_examples "a Celluloid Actor" do
22
28
  true
23
29
  else
24
30
  false
25
- end,
31
+ end
26
32
  ).to be_truthy
27
33
  end
28
34
 
29
35
  it "can be stored in hashes" do
30
36
  expect(actor.hash).not_to eq(Kernel.hash)
31
37
  expect(actor.object_id).not_to eq(Kernel.object_id)
32
- expect(actor.eql? actor).to be_truthy
38
+ expect(actor.eql?(actor)).to be_truthy
33
39
  end
34
40
 
35
41
  it "can be stored in hashes even when dead" do
36
42
  actor.terminate
37
-
43
+
38
44
  expect(actor.dead?).to be_truthy
39
-
45
+
40
46
  expect(actor.hash).not_to eq(Kernel.hash)
41
47
  expect(actor.object_id).not_to eq(Kernel.object_id)
42
- expect(actor.eql? actor).to be_truthy
48
+ expect(actor.eql?(actor)).to be_truthy
43
49
  end
44
50
 
45
51
  it "implements respond_to? correctly" do
@@ -201,7 +207,9 @@ RSpec.shared_examples "a Celluloid Actor" do
201
207
  end
202
208
 
203
209
  it "warns about suspending the initialize" do
210
+ # rubocop:disable Metrics/LineLength
204
211
  expect(logger).to receive(:warn).with(/Dangerously suspending task: type=:call, meta={:dangerous_suspend=>true, :method_name=>:initialize}, status=:sleeping/)
212
+ # rubocop:enable Metrics/LineLength
205
213
 
206
214
  actor.terminate
207
215
  Specs.sleep_and_wait_until { !actor.alive? }
@@ -232,7 +240,9 @@ RSpec.shared_examples "a Celluloid Actor" do
232
240
  it "warns about suspending the finalizer" do
233
241
  allow(logger).to receive(:warn)
234
242
  allow(logger).to receive(:crash).with(/finalizer crashed!/, Celluloid::TaskTerminated)
243
+ # rubocop:disable Metrics/LineLength
235
244
  expect(logger).to receive(:warn).with(/Dangerously suspending task: type=:finalizer, meta={:dangerous_suspend=>true, :method_name=>:cleanup}, status=:sleeping/)
245
+ # rubocop:enable Metrics/LineLength
236
246
  actor.terminate
237
247
  Specs.sleep_and_wait_until { !actor.alive? }
238
248
  end
@@ -418,7 +428,7 @@ RSpec.shared_examples "a Celluloid Actor" do
418
428
  include CelluloidSpecs.included_module
419
429
 
420
430
  define_method(:receiver_method) do
421
- fail ExampleCrash, "the spec purposely crashed me :("
431
+ raise ExampleCrash, "the spec purposely crashed me :("
422
432
  end
423
433
  end.new
424
434
 
@@ -430,18 +440,16 @@ RSpec.shared_examples "a Celluloid Actor" do
430
440
  end
431
441
  end.new
432
442
 
433
- ex = example_caller.sender_method rescue $ERROR_INFO
434
- Specs.sleep_and_wait_until { !example_caller.alive? }
435
- Specs.sleep_and_wait_until { !example_receiver.alive? }
436
-
437
- expect(ex).to be_a ExampleCrash
438
- expect(ex.backtrace.grep(/`sender_method'/)).to be_truthy
439
- expect(ex.backtrace.grep(/`receiver_method'/)).to be_truthy
443
+ expect { example_caller.sender_method }.to raise_error ExampleCrash
440
444
  end
441
445
 
442
446
  it "raises DeadActorError if methods are synchronously called on a dead actor" do
443
447
  allow(logger).to receive(:crash).with("Actor crashed!", ExampleCrash)
444
- actor.crash rescue ExampleCrash
448
+ begin
449
+ actor.crash
450
+ rescue
451
+ ExampleCrash
452
+ end
445
453
 
446
454
  # TODO: avoid this somehow
447
455
  sleep 0.1 # hax to prevent a race between exit handling and the next call
@@ -469,10 +477,11 @@ RSpec.shared_examples "a Celluloid Actor" do
469
477
  end
470
478
 
471
479
  it "crashes the sender if we pass neither String nor Exception" do
480
+ number = 10
472
481
  allow(logger).to receive(:crash).with("Actor crashed!", TypeError)
473
482
  expect do
474
- actor.crash_with_abort_raw 10
475
- end.to raise_exception(TypeError, "Exception object/String expected, but Fixnum received")
483
+ actor.crash_with_abort_raw number
484
+ end.to raise_exception(TypeError, "Exception object/String expected, but #{number.class} received")
476
485
 
477
486
  Specs.sleep_and_wait_until { !actor.alive? }
478
487
  expect(actor).not_to be_alive
@@ -550,7 +559,9 @@ RSpec.shared_examples "a Celluloid Actor" do
550
559
 
551
560
  context "when terminated" do
552
561
  it "logs a debug" do
562
+ # rubocop:disable Metrics/LineLength
553
563
  expect(logger).to receive(:debug).with(/^Terminating task: type=:call, meta={:dangerous_suspend=>false, :method_name=>:sleepy}, status=:sleeping/)
564
+ # rubocop:enable Metrics/LineLength
554
565
  actor.terminate
555
566
  Specs.sleep_and_wait_until { !actor.alive? }
556
567
  end
@@ -594,9 +605,9 @@ RSpec.shared_examples "a Celluloid Actor" do
594
605
  @subordinate_lambasted
595
606
  end
596
607
 
597
- def lambaste_subordinate(_actor, _reason)
608
+ def lambaste_subordinate(_actor, reason)
598
609
  @subordinate_lambasted = true
599
- @exception = _reason
610
+ @exception = reason
600
611
  end
601
612
  end
602
613
  end
@@ -704,7 +715,7 @@ RSpec.shared_examples "a Celluloid Actor" do
704
715
  end
705
716
 
706
717
  def wait_for_signal
707
- fail "already signaled" if @signaled
718
+ raise "already signaled" if @signaled
708
719
 
709
720
  @waiting = true
710
721
  value = wait :ponycopter
@@ -801,14 +812,14 @@ RSpec.shared_examples "a Celluloid Actor" do
801
812
  subject.async.exclusive_with_block_log_task(:one)
802
813
  subject.async.log_task(:two)
803
814
  sleep Specs::TIMER_QUANTUM * 2
804
- expect(subject.tasks).to eq([:one, :two])
815
+ expect(subject.tasks).to eq(%i[one two])
805
816
  end
806
817
 
807
818
  it "executes methods in the proper order with a class-level annotation" do
808
819
  subject.async.exclusive_log_task :one
809
820
  subject.async.log_task :two
810
821
  sleep Specs::TIMER_QUANTUM * 2
811
- expect(subject.tasks).to eq([:one, :two])
822
+ expect(subject.tasks).to eq(%i[one two])
812
823
  end
813
824
 
814
825
  it "knows when it's in exclusive mode" do
@@ -854,7 +865,7 @@ RSpec.shared_examples "a Celluloid Actor" do
854
865
  end
855
866
 
856
867
  it "executes in an exclusive order" do
857
- expect(actor.tasks).to eq(%w(donuts coffee))
868
+ expect(actor.tasks).to eq(%w[donuts coffee])
858
869
  end
859
870
  end
860
871
  end
@@ -949,7 +960,7 @@ RSpec.shared_examples "a Celluloid Actor" do
949
960
  expect(actor).to be_sleeping
950
961
 
951
962
  future.value
952
- # I got 0.558 (in a slighly busy MRI) which is outside 0.05 of 0.5, so let's use (0.05 * 2)
963
+ # I got 0.558 (in a slightly busy MRI) which is outside 0.05 of 0.5, so let's use (0.05 * 2)
953
964
  expect(Time.now - started_at).to be_within(Specs::TIMER_QUANTUM * 2).of interval
954
965
  end
955
966
 
@@ -1102,7 +1113,7 @@ RSpec.shared_examples "a Celluloid Actor" do
1102
1113
 
1103
1114
  klass = Class.new(Celluloid::Proxy::Cell) do
1104
1115
  def dividing_3_by(number)
1105
- fail ArgumentError, "<facepalm>" if number.zero?
1116
+ raise ArgumentError, "<facepalm>" if number.zero?
1106
1117
  super
1107
1118
  end
1108
1119
  end
@@ -1121,7 +1132,11 @@ RSpec.shared_examples "a Celluloid Actor" do
1121
1132
  end
1122
1133
 
1123
1134
  it "does not crash the actor" do
1124
- subject.dividing_3_by(0) rescue ArgumentError
1135
+ begin
1136
+ subject.dividing_3_by(0)
1137
+ rescue
1138
+ ArgumentError
1139
+ end
1125
1140
  expect(subject.dividing_3_by(3)).to eq(1)
1126
1141
  end
1127
1142
  end
@@ -1130,7 +1145,7 @@ RSpec.shared_examples "a Celluloid Actor" do
1130
1145
  context "when it includes method checking" do
1131
1146
  module MethodChecking
1132
1147
  def method_missing(meth, *args)
1133
- return super if [:__send__, :respond_to?, :method, :class, :__class__].include? meth
1148
+ return super if %i[__send__ respond_to? method class __class__].include? meth
1134
1149
 
1135
1150
  unmet_requirement = nil
1136
1151
 
@@ -1141,7 +1156,7 @@ RSpec.shared_examples "a Celluloid Actor" do
1141
1156
  mandatory_args = -arity - 1
1142
1157
  unmet_requirement = "#{mandatory_args}+" if args.size < mandatory_args
1143
1158
  end
1144
- fail ArgumentError, "wrong number of arguments (#{args.size} for #{unmet_requirement})" if unmet_requirement
1159
+ raise ArgumentError, "wrong number of arguments (#{args.size} for #{unmet_requirement})" if unmet_requirement
1145
1160
 
1146
1161
  super
1147
1162
  end
@@ -1160,7 +1175,7 @@ RSpec.shared_examples "a Celluloid Actor" do
1160
1175
  end
1161
1176
 
1162
1177
  def this_is_not_madness(word1, word2, word3, *_args)
1163
- fail "This is madness!" unless [word1, word2, word3] == [:this, :is, :Sparta]
1178
+ raise "This is madness!" unless [word1, word2, word3] == %i[this is Sparta]
1164
1179
  end
1165
1180
 
1166
1181
  proxy_class klass
@@ -1173,7 +1188,11 @@ RSpec.shared_examples "a Celluloid Actor" do
1173
1188
  end
1174
1189
 
1175
1190
  it "does not crash the actor" do
1176
- subject.method_to_madness rescue NoMethodError
1191
+ begin
1192
+ subject.method_to_madness
1193
+ rescue
1194
+ NoMethodError
1195
+ end
1177
1196
  expect(subject.madness).to eq("This is madness!")
1178
1197
  end
1179
1198
  end
@@ -1181,18 +1200,24 @@ RSpec.shared_examples "a Celluloid Actor" do
1181
1200
  context "when invoking a existing method with incorrect args" do
1182
1201
  context "with too many arguments" do
1183
1202
  it "raises an ArgumentError" do
1184
- expect { subject.madness(:Sparta) }.to raise_error(ArgumentError, "wrong number of arguments (1 for 0)")
1203
+ expect { subject.madness(:Sparta) }
1204
+ .to raise_error(ArgumentError, "wrong number of arguments (1 for 0)")
1185
1205
  end
1186
1206
 
1187
1207
  it "does not crash the actor" do
1188
- subject.madness(:Sparta) rescue ArgumentError
1208
+ begin
1209
+ subject.madness(:Sparta)
1210
+ rescue
1211
+ ArgumentError
1212
+ end
1189
1213
  expect(subject.madness).to eq("This is madness!")
1190
1214
  end
1191
1215
  end
1192
1216
 
1193
1217
  context "with not enough mandatory arguments" do
1194
1218
  it "raises an ArgumentError" do
1195
- expect { subject.this_is_not_madness(:this, :is) }.to raise_error(ArgumentError, "wrong number of arguments (2 for 3+)")
1219
+ expect { subject.this_is_not_madness(:this, :is) }
1220
+ .to raise_error(ArgumentError, "wrong number of arguments (2 for 3+)")
1196
1221
  end
1197
1222
  end
1198
1223
  end