celluloid 0.18.0.pre → 0.18.0.pre2
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/CHANGES.md +114 -39
- data/CONDUCT.md +13 -0
- data/CONTRIBUTING.md +39 -0
- data/README.md +59 -55
- data/architecture.md +120 -0
- data/examples/basic_usage.rb +1 -1
- data/examples/configurations.rb +78 -0
- data/examples/futures.rb +1 -1
- data/examples/ring.rb +5 -4
- data/examples/simple_pmap.rb +1 -1
- data/examples/stack.rb +2 -2
- data/examples/supervisors_and_registry.rb +82 -0
- data/examples/timers.rb +1 -1
- data/lib/celluloid.rb +72 -47
- data/lib/celluloid/actor.rb +27 -17
- data/lib/celluloid/actor/system.rb +13 -29
- data/lib/celluloid/autostart.rb +5 -5
- data/lib/celluloid/backported.rb +6 -2
- data/lib/celluloid/call/async.rb +2 -0
- data/lib/celluloid/call/sync.rb +10 -3
- data/lib/celluloid/calls.rb +5 -12
- data/lib/celluloid/cell.rb +5 -9
- data/lib/celluloid/condition.rb +3 -3
- data/lib/celluloid/core_ext.rb +0 -2
- data/lib/celluloid/current.rb +3 -1
- data/lib/celluloid/debug.rb +3 -0
- data/lib/celluloid/exceptions.rb +2 -2
- data/lib/celluloid/future.rb +7 -9
- data/lib/celluloid/group.rb +12 -8
- data/lib/celluloid/group/pool.rb +1 -3
- data/lib/celluloid/group/spawner.rb +2 -6
- data/lib/celluloid/internals/call_chain.rb +15 -0
- data/lib/celluloid/internals/cpu_counter.rb +62 -0
- data/lib/celluloid/internals/handlers.rb +42 -0
- data/lib/celluloid/internals/links.rb +38 -0
- data/lib/celluloid/internals/logger.rb +104 -0
- data/lib/celluloid/internals/method.rb +34 -0
- data/lib/celluloid/internals/properties.rb +32 -0
- data/lib/celluloid/internals/receivers.rb +64 -0
- data/lib/celluloid/internals/registry.rb +102 -0
- data/lib/celluloid/internals/responses.rb +46 -0
- data/lib/celluloid/internals/signals.rb +24 -0
- data/lib/celluloid/internals/stack.rb +74 -0
- data/lib/celluloid/internals/stack/dump.rb +12 -0
- data/lib/celluloid/internals/stack/states.rb +72 -0
- data/lib/celluloid/internals/stack/summary.rb +12 -0
- data/lib/celluloid/internals/task_set.rb +51 -0
- data/lib/celluloid/internals/thread_handle.rb +52 -0
- data/lib/celluloid/internals/uuid.rb +40 -0
- data/lib/celluloid/logging/incident.rb +21 -0
- data/lib/celluloid/logging/incident_logger.rb +147 -0
- data/lib/celluloid/logging/incident_reporter.rb +49 -0
- data/lib/celluloid/logging/log_event.rb +20 -0
- data/lib/celluloid/logging/ring_buffer.rb +64 -0
- data/lib/celluloid/mailbox.rb +22 -9
- data/lib/celluloid/mailbox/evented.rb +13 -5
- data/lib/celluloid/managed.rb +6 -3
- data/lib/celluloid/notifications.rb +95 -0
- data/lib/celluloid/pool.rb +6 -0
- data/lib/celluloid/probe.rb +81 -0
- data/lib/celluloid/proxy/abstract.rb +9 -9
- data/lib/celluloid/proxy/async.rb +1 -1
- data/lib/celluloid/proxy/block.rb +2 -2
- data/lib/celluloid/proxy/cell.rb +1 -1
- data/lib/celluloid/proxy/future.rb +2 -4
- data/lib/celluloid/proxy/sync.rb +1 -3
- data/lib/celluloid/rspec.rb +22 -33
- data/lib/celluloid/supervision.rb +17 -0
- data/lib/celluloid/supervision/configuration.rb +169 -0
- data/lib/celluloid/supervision/configuration/injections.rb +8 -0
- data/lib/celluloid/supervision/configuration/instance.rb +113 -0
- data/lib/celluloid/supervision/constants.rb +123 -0
- data/lib/celluloid/supervision/container.rb +144 -0
- data/lib/celluloid/supervision/container/behavior.rb +89 -0
- data/lib/celluloid/supervision/container/behavior/pool.rb +71 -0
- data/lib/celluloid/supervision/container/behavior/tree.rb +23 -0
- data/lib/celluloid/supervision/container/injections.rb +8 -0
- data/lib/celluloid/supervision/container/instance.rb +116 -0
- data/lib/celluloid/supervision/container/pool.rb +210 -0
- data/{culture/rubocop/perf.yml → lib/celluloid/supervision/container/tree.rb} +0 -0
- data/lib/celluloid/supervision/deprecate.rb +9 -0
- data/lib/celluloid/supervision/deprecate/supervise.rb +105 -0
- data/lib/celluloid/supervision/deprecate/validation.rb +54 -0
- data/lib/celluloid/supervision/service.rb +27 -0
- data/lib/celluloid/supervision/supervise.rb +34 -0
- data/lib/celluloid/supervision/validation.rb +40 -0
- data/lib/celluloid/supervision/version.rb +5 -0
- data/lib/celluloid/system_events.rb +11 -6
- data/lib/celluloid/task.rb +25 -12
- data/lib/celluloid/task/fibered.rb +2 -0
- data/lib/celluloid/task/threaded.rb +3 -3
- data/lib/celluloid/test.rb +5 -2
- data/lib/celluloid/thread.rb +0 -2
- data/lib/celluloid/version.rb +1 -1
- data/spec/celluloid/block_spec.rb +29 -32
- data/spec/celluloid/calls_spec.rb +5 -15
- data/spec/celluloid/future_spec.rb +2 -2
- data/spec/celluloid/internals/cpu_counter_spec.rb +129 -0
- data/spec/celluloid/internals/links_spec.rb +43 -0
- data/spec/celluloid/internals/properties_spec.rb +40 -0
- data/spec/celluloid/internals/registry_spec.rb +62 -0
- data/spec/celluloid/internals/stack/dump_spec.rb +4 -0
- data/spec/celluloid/internals/stack/summary_spec.rb +4 -0
- data/spec/celluloid/internals/thread_handle_spec.rb +60 -0
- data/spec/celluloid/internals/uuid_spec.rb +9 -0
- data/spec/celluloid/logging/ring_buffer_spec.rb +36 -0
- data/spec/celluloid/mailbox/evented_spec.rb +11 -22
- data/spec/celluloid/misc/leak_spec.rb +3 -4
- data/spec/celluloid/notifications_spec.rb +140 -0
- data/spec/celluloid/probe_spec.rb +102 -0
- data/spec/celluloid/proxy_spec.rb +30 -30
- data/spec/celluloid/supervision/behavior_spec.rb +74 -0
- data/spec/celluloid/supervision/configuration_spec.rb +181 -0
- data/spec/celluloid/supervision/container_spec.rb +72 -0
- data/spec/celluloid/supervision/instance_spec.rb +13 -0
- data/spec/celluloid/supervision/root_spec.rb +28 -0
- data/spec/celluloid/supervision/supervisor_spec.rb +93 -0
- data/spec/celluloid/task/fibered_spec.rb +1 -3
- data/spec/celluloid/task/threaded_spec.rb +1 -3
- data/spec/shared/actor_examples.rb +58 -33
- data/spec/shared/group_examples.rb +2 -2
- data/spec/shared/mailbox_examples.rb +1 -1
- data/spec/shared/stack_examples.rb +87 -0
- data/spec/shared/task_examples.rb +2 -3
- data/spec/spec_helper.rb +2 -4
- data/spec/support/configure_rspec.rb +2 -3
- data/spec/support/coverage.rb +2 -4
- data/spec/support/crash_checking.rb +2 -2
- data/spec/support/examples/actor_class.rb +3 -8
- data/spec/support/examples/call_class.rb +2 -2
- data/spec/support/examples/container_class.rb +35 -0
- data/spec/support/examples/evented_mailbox_class.rb +1 -2
- data/spec/support/examples/stack_classes.rb +58 -0
- data/spec/support/examples/stack_methods.rb +23 -0
- data/spec/support/examples/subordinate_class.rb +19 -0
- data/spec/support/logging.rb +2 -34
- data/spec/support/loose_threads.rb +3 -16
- data/spec/support/reset_class_variables.rb +5 -1
- data/spec/support/stubbing.rb +1 -1
- metadata +91 -316
- data/culture/CONDUCT.md +0 -38
- data/culture/GSoC/1010-why_we_will_participate.md +0 -17
- data/culture/GSoC/1020-how_mentors_stay_engaged.md +0 -7
- data/culture/GSoC/1030-keeping_students_on_schedule.md +0 -9
- data/culture/GSoC/1040-getting_students_involved.md +0 -5
- data/culture/GSoC/1050-student_involvement_after.md +0 -5
- data/culture/GSoC/README.md +0 -16
- data/culture/Gemfile +0 -9
- data/culture/LICENSE.txt +0 -22
- data/culture/README.md +0 -22
- data/culture/Rakefile +0 -5
- data/culture/SYNC.md +0 -70
- data/culture/celluloid-culture.gemspec +0 -18
- data/culture/gems/README.md +0 -39
- data/culture/gems/dependencies.yml +0 -93
- data/culture/gems/loader.rb +0 -101
- data/culture/rubocop/README.md +0 -38
- data/culture/rubocop/lint.yml +0 -8
- data/culture/rubocop/metrics.yml +0 -15
- data/culture/rubocop/rubocop.yml +0 -5
- data/culture/rubocop/style.yml +0 -61
- data/culture/spec/gems_spec.rb +0 -2
- data/culture/spec/spec_helper.rb +0 -0
- data/culture/spec/sync_spec.rb +0 -2
- data/culture/sync.rb +0 -56
- data/culture/tasks/rspec.rake +0 -5
- data/culture/tasks/rubocop.rake +0 -2
- data/lib/celluloid/actor/manager.rb +0 -7
- data/lib/celluloid/deprecate.rb +0 -34
- data/lib/celluloid/fiber.rb +0 -32
- data/lib/celluloid/notices.rb +0 -15
- data/spec/deprecate/actor_system_spec.rb +0 -72
- data/spec/deprecate/block_spec.rb +0 -52
- data/spec/deprecate/calls_spec.rb +0 -39
- data/spec/deprecate/evented_mailbox_spec.rb +0 -34
- data/spec/deprecate/future_spec.rb +0 -32
- data/spec/deprecate/internal_pool_spec.rb +0 -4
- 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
|
@@ -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?
|
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?
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
475
|
-
end.to raise_exception(TypeError, "Exception object/String expected, but
|
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,
|
608
|
+
def lambaste_subordinate(_actor, reason)
|
598
609
|
@subordinate_lambasted = true
|
599
|
-
@exception =
|
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
|
-
|
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([
|
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([
|
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
|
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
|
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
|
-
|
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
|
-
|
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 [
|
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
|
-
|
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
|
-
|
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
|
-
|
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) }
|
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
|
-
|
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) }
|
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
|