celluloid 0.16.0 → 0.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +394 -0
- data/LICENSE.txt +1 -1
- data/README.md +28 -15
- data/culture/CONDUCT.md +28 -0
- data/culture/Gemfile +9 -0
- data/culture/LICENSE.txt +22 -0
- data/culture/README.md +22 -0
- data/culture/Rakefile +5 -0
- data/culture/SYNC.md +70 -0
- data/culture/celluloid-culture.gemspec +18 -0
- data/culture/gems/README.md +39 -0
- data/culture/gems/dependencies.yml +85 -0
- data/culture/gems/loader.rb +101 -0
- data/culture/rubocop/README.md +38 -0
- data/culture/rubocop/lint.yml +8 -0
- data/culture/rubocop/metrics.yml +15 -0
- data/culture/rubocop/perf.yml +0 -0
- data/culture/rubocop/rubocop.yml +5 -0
- data/culture/rubocop/style.yml +57 -0
- data/culture/spec/gems_spec.rb +2 -0
- data/culture/spec/spec_helper.rb +0 -0
- data/culture/spec/sync_spec.rb +2 -0
- data/culture/sync.rb +56 -0
- data/culture/tasks/rspec.rake +5 -0
- data/culture/tasks/rubocop.rake +2 -0
- data/examples/basic_usage.rb +49 -0
- data/examples/futures.rb +38 -0
- data/examples/ring.rb +61 -0
- data/examples/simple_pmap.rb +14 -0
- data/examples/stack.rb +47 -0
- data/examples/timers.rb +72 -0
- data/lib/celluloid/actor/manager.rb +7 -0
- data/lib/celluloid/actor/system.rb +163 -0
- data/lib/celluloid/actor.rb +53 -71
- data/lib/celluloid/autostart.rb +1 -1
- data/lib/celluloid/backported.rb +2 -0
- data/lib/celluloid/call/async.rb +16 -0
- data/lib/celluloid/call/block.rb +22 -0
- data/lib/celluloid/call/sync.rb +70 -0
- data/lib/celluloid/calls.rb +24 -114
- data/lib/celluloid/cell.rb +32 -20
- data/lib/celluloid/condition.rb +5 -6
- data/lib/celluloid/core_ext.rb +1 -1
- data/lib/celluloid/current.rb +2 -0
- data/lib/celluloid/debug.rb +1 -0
- data/lib/celluloid/deprecate.rb +21 -0
- data/lib/celluloid/exceptions.rb +22 -16
- data/lib/celluloid/fiber.rb +3 -3
- data/lib/celluloid/future.rb +46 -8
- data/lib/celluloid/group/pool.rb +125 -0
- data/lib/celluloid/group/spawner.rb +68 -0
- data/lib/celluloid/group.rb +61 -0
- data/lib/celluloid/logging.rb +5 -5
- data/lib/celluloid/mailbox/evented.rb +74 -0
- data/lib/celluloid/mailbox.rb +15 -14
- data/lib/celluloid/managed.rb +3 -0
- data/lib/celluloid/notices.rb +15 -0
- data/lib/celluloid/proxies.rb +11 -0
- data/lib/celluloid/proxy/abstract.rb +50 -0
- data/lib/celluloid/proxy/actor.rb +37 -0
- data/lib/celluloid/proxy/async.rb +15 -0
- data/lib/celluloid/proxy/block.rb +28 -0
- data/lib/celluloid/proxy/cell.rb +66 -0
- data/lib/celluloid/proxy/future.rb +20 -0
- data/lib/celluloid/proxy/sync.rb +24 -0
- data/lib/celluloid/rspec.rb +67 -9
- data/lib/celluloid/system_events.rb +69 -14
- data/lib/celluloid/task/fibered.rb +45 -0
- data/lib/celluloid/task/threaded.rb +59 -0
- data/lib/celluloid/{tasks.rb → task.rb} +30 -38
- data/lib/celluloid/test.rb +1 -1
- data/lib/celluloid/thread.rb +6 -1
- data/lib/celluloid/version.rb +3 -0
- data/lib/celluloid.rb +151 -130
- data/spec/celluloid/actor/system_spec.rb +83 -0
- data/spec/celluloid/actor_spec.rb +2 -2
- data/spec/celluloid/block_spec.rb +67 -8
- data/spec/celluloid/calls_spec.rb +28 -23
- data/spec/celluloid/condition_spec.rb +23 -14
- data/spec/celluloid/evented_mailbox_spec.rb +1 -31
- data/spec/celluloid/future_spec.rb +15 -12
- data/spec/celluloid/group/elastic_spec.rb +0 -0
- data/spec/celluloid/group/pool_spec.rb +8 -0
- data/spec/celluloid/group/spawner_spec.rb +17 -0
- data/spec/celluloid/mailbox/evented_spec.rb +40 -0
- data/spec/celluloid/mailbox_spec.rb +1 -3
- data/spec/celluloid/misc/leak_spec.rb +73 -0
- data/spec/celluloid/proxy_spec.rb +33 -0
- data/spec/celluloid/task/fibered_spec.rb +5 -0
- data/spec/celluloid/task/threaded_spec.rb +5 -0
- data/spec/celluloid/timer_spec.rb +14 -16
- data/spec/deprecate/actor_system_spec.rb +72 -0
- data/spec/deprecate/block_spec.rb +52 -0
- data/spec/deprecate/calls_spec.rb +39 -0
- data/spec/deprecate/evented_mailbox_spec.rb +34 -0
- data/spec/deprecate/future_spec.rb +32 -0
- data/spec/deprecate/internal_pool_spec.rb +4 -0
- data/spec/shared/actor_examples.rb +1259 -0
- data/spec/shared/group_examples.rb +121 -0
- data/spec/shared/mailbox_examples.rb +87 -0
- data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
- data/spec/spec_helper.rb +5 -42
- data/spec/support/configure_rspec.rb +77 -0
- data/spec/support/coverage.rb +4 -0
- data/spec/support/crash_checking.rb +68 -0
- data/spec/support/debugging.rb +31 -0
- data/spec/support/env.rb +21 -0
- data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
- data/spec/support/examples/call_class.rb +37 -0
- data/spec/support/examples/evented_mailbox_class.rb +27 -0
- data/spec/support/includer.rb +6 -0
- data/spec/support/logging.rb +55 -0
- data/spec/support/loose_threads.rb +68 -0
- data/spec/support/reset_class_variables.rb +27 -0
- data/spec/support/sleep_and_wait.rb +14 -0
- data/spec/support/stubbing.rb +14 -0
- metadata +276 -78
- data/lib/celluloid/actor_system.rb +0 -107
- data/lib/celluloid/call_chain.rb +0 -13
- data/lib/celluloid/cpu_counter.rb +0 -34
- data/lib/celluloid/evented_mailbox.rb +0 -73
- data/lib/celluloid/fsm.rb +0 -186
- data/lib/celluloid/handlers.rb +0 -41
- data/lib/celluloid/internal_pool.rb +0 -159
- data/lib/celluloid/legacy.rb +0 -9
- data/lib/celluloid/links.rb +0 -36
- data/lib/celluloid/logger.rb +0 -93
- data/lib/celluloid/logging/incident.rb +0 -21
- data/lib/celluloid/logging/incident_logger.rb +0 -129
- data/lib/celluloid/logging/incident_reporter.rb +0 -48
- data/lib/celluloid/logging/log_event.rb +0 -20
- data/lib/celluloid/logging/ring_buffer.rb +0 -65
- data/lib/celluloid/method.rb +0 -32
- data/lib/celluloid/notifications.rb +0 -83
- data/lib/celluloid/pool_manager.rb +0 -146
- data/lib/celluloid/probe.rb +0 -73
- data/lib/celluloid/properties.rb +0 -24
- data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
- data/lib/celluloid/proxies/actor_proxy.rb +0 -38
- data/lib/celluloid/proxies/async_proxy.rb +0 -31
- data/lib/celluloid/proxies/block_proxy.rb +0 -29
- data/lib/celluloid/proxies/cell_proxy.rb +0 -68
- data/lib/celluloid/proxies/future_proxy.rb +0 -35
- data/lib/celluloid/proxies/sync_proxy.rb +0 -36
- data/lib/celluloid/receivers.rb +0 -63
- data/lib/celluloid/registry.rb +0 -57
- data/lib/celluloid/responses.rb +0 -44
- data/lib/celluloid/rspec/actor_examples.rb +0 -1054
- data/lib/celluloid/rspec/mailbox_examples.rb +0 -84
- data/lib/celluloid/signals.rb +0 -23
- data/lib/celluloid/stack_dump.rb +0 -133
- data/lib/celluloid/supervision_group.rb +0 -169
- data/lib/celluloid/supervisor.rb +0 -22
- data/lib/celluloid/task_set.rb +0 -49
- data/lib/celluloid/tasks/task_fiber.rb +0 -43
- data/lib/celluloid/tasks/task_thread.rb +0 -53
- data/lib/celluloid/thread_handle.rb +0 -50
- data/lib/celluloid/uuid.rb +0 -38
- data/spec/celluloid/actor_system_spec.rb +0 -69
- data/spec/celluloid/cpu_counter_spec.rb +0 -82
- data/spec/celluloid/fsm_spec.rb +0 -107
- data/spec/celluloid/internal_pool_spec.rb +0 -52
- data/spec/celluloid/links_spec.rb +0 -45
- data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
- data/spec/celluloid/notifications_spec.rb +0 -120
- data/spec/celluloid/pool_spec.rb +0 -92
- data/spec/celluloid/probe_spec.rb +0 -121
- data/spec/celluloid/properties_spec.rb +0 -42
- data/spec/celluloid/registry_spec.rb +0 -64
- data/spec/celluloid/stack_dump_spec.rb +0 -64
- data/spec/celluloid/supervision_group_spec.rb +0 -65
- data/spec/celluloid/supervisor_spec.rb +0 -103
- data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
- data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
- data/spec/celluloid/thread_handle_spec.rb +0 -26
- data/spec/celluloid/uuid_spec.rb +0 -11
|
@@ -1,42 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
RSpec.describe Celluloid::Call::Sync, actor_system: :global do
|
|
2
|
+
# TODO: these should be Call::Sync unit tests (without working on actual actors)
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
let(:actor) { CallExampleActor.new }
|
|
5
|
+
let(:logger) { Specs::FakeLogger.current }
|
|
6
|
+
|
|
7
|
+
context "when obj does not respond to a method" do
|
|
8
|
+
# bypass this until rubinius/rubinius#3373 is resolved
|
|
9
|
+
# under Rubinius, `method` calls `inspect` on an object when a method is not found
|
|
10
|
+
unless RUBY_ENGINE == "rbx"
|
|
11
|
+
it "raises a NoMethodError" do
|
|
12
|
+
allow(logger).to receive(:crash).with("Actor crashed!", NoMethodError)
|
|
13
|
+
|
|
14
|
+
expect do
|
|
15
|
+
actor.the_method_that_wasnt_there
|
|
16
|
+
end.to raise_exception(NoMethodError)
|
|
17
|
+
end
|
|
9
18
|
end
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
context "when obj raises during inspect" do
|
|
21
|
+
it "should emulate obj.inspect" do
|
|
22
|
+
allow(logger).to receive(:crash).with("Actor crashed!", NoMethodError)
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
if RUBY_ENGINE == "rbx"
|
|
25
|
+
expected = /undefined method `no_such_method' on an instance of CallExampleActor/
|
|
26
|
+
else
|
|
27
|
+
expected = /undefined method `no_such_method' for #\<CallExampleActor:0x[a-f0-9]+\>/
|
|
28
|
+
end
|
|
29
|
+
end
|
|
15
30
|
end
|
|
16
31
|
end
|
|
17
32
|
|
|
18
|
-
let(:actor) { CallExampleActor.new }
|
|
19
|
-
|
|
20
|
-
it "aborts with NoMethodError when a nonexistent method is called" do
|
|
21
|
-
expect do
|
|
22
|
-
actor.the_method_that_wasnt_there
|
|
23
|
-
end.to raise_exception(NoMethodError)
|
|
24
|
-
|
|
25
|
-
actor.should be_alive
|
|
26
|
-
end
|
|
27
|
-
|
|
28
33
|
it "aborts with ArgumentError when a method is called with too many arguments" do
|
|
34
|
+
allow(logger).to receive(:crash).with("Actor crashed!", ArgumentError)
|
|
35
|
+
|
|
29
36
|
expect do
|
|
30
37
|
actor.actual_method("with too many arguments")
|
|
31
38
|
end.to raise_exception(ArgumentError)
|
|
32
|
-
|
|
33
|
-
actor.should be_alive
|
|
34
39
|
end
|
|
35
40
|
|
|
36
41
|
it "preserves call chains across synchronous calls" do
|
|
37
42
|
actor2 = CallExampleActor.new(actor)
|
|
38
43
|
|
|
39
44
|
uuid, next_actor_uuid = actor2.chained_call_ids
|
|
40
|
-
uuid.
|
|
45
|
+
expect(uuid).to eq next_actor_uuid
|
|
41
46
|
end
|
|
42
47
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
RSpec.describe Celluloid::Condition, actor_system: :global do
|
|
2
|
+
let(:logger) { Specs::FakeLogger.current }
|
|
2
3
|
|
|
3
|
-
describe Celluloid::Condition, actor_system: :global do
|
|
4
4
|
class ConditionExample
|
|
5
5
|
include Celluloid
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ describe Celluloid::Condition, actor_system: :global do
|
|
|
9
9
|
def initialize
|
|
10
10
|
@condition = Condition.new
|
|
11
11
|
|
|
12
|
-
@waiting
|
|
12
|
+
@waiting = false
|
|
13
13
|
@signaled_times = 0
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -29,7 +29,9 @@ describe Celluloid::Condition, actor_system: :global do
|
|
|
29
29
|
value
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def waiting
|
|
32
|
+
def waiting?
|
|
33
|
+
@waiting
|
|
34
|
+
end
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
let(:actor) { ConditionExample.new }
|
|
@@ -37,40 +39,47 @@ describe Celluloid::Condition, actor_system: :global do
|
|
|
37
39
|
|
|
38
40
|
it "sends signals" do
|
|
39
41
|
3.times { actor.async.wait_for_condition }
|
|
40
|
-
actor.signaled_times.
|
|
42
|
+
expect(actor.signaled_times).to be_zero
|
|
41
43
|
|
|
42
44
|
actor.condition.signal
|
|
43
|
-
actor.signaled_times.
|
|
45
|
+
expect(actor.signaled_times).to be(1)
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
it "broadcasts signals" do
|
|
47
49
|
3.times { actor.async.wait_for_condition }
|
|
48
|
-
actor.signaled_times.
|
|
50
|
+
expect(actor.signaled_times).to be_zero
|
|
49
51
|
|
|
50
52
|
actor.condition.broadcast
|
|
51
|
-
actor.signaled_times.
|
|
53
|
+
expect(actor.signaled_times).to be(3)
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
it "sends values along with signals" do
|
|
55
57
|
future = actor.future(:wait_for_condition)
|
|
56
58
|
actor.condition.signal(:example_value)
|
|
57
|
-
future.value.
|
|
59
|
+
expect(future.value).to be(:example_value)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "supports running blocks with value once obtained" do
|
|
63
|
+
condition = Celluloid::Condition.new
|
|
64
|
+
actor.async.signal_condition condition, :value
|
|
65
|
+
expect(condition.wait { |value| "#{value} post-handled" }).to eq("value post-handled")
|
|
58
66
|
end
|
|
59
67
|
|
|
60
68
|
it "supports waiting outside actors" do
|
|
61
69
|
condition = Celluloid::Condition.new
|
|
62
70
|
actor.async.signal_condition condition, :value
|
|
63
|
-
condition.wait.
|
|
71
|
+
expect(condition.wait).to eq(:value)
|
|
64
72
|
end
|
|
65
73
|
|
|
66
74
|
it "times out inside normal Threads" do
|
|
67
75
|
condition = Celluloid::Condition.new
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
expect { condition.wait(1) }
|
|
77
|
+
.to raise_error(Celluloid::ConditionError)
|
|
70
78
|
end
|
|
71
79
|
|
|
72
80
|
it "times out inside Tasks" do
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
allow(logger).to receive(:crash).with("Actor crashed!", Celluloid::ConditionError)
|
|
82
|
+
expect { actor.wait_for_condition(1) }
|
|
83
|
+
.to raise_error(Celluloid::ConditionError)
|
|
75
84
|
end
|
|
76
85
|
end
|
|
@@ -1,34 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
class TestEventedMailbox < Celluloid::EventedMailbox
|
|
4
|
-
class Reactor
|
|
5
|
-
def initialize
|
|
6
|
-
@condition = ConditionVariable.new
|
|
7
|
-
@mutex = Mutex.new
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def wakeup
|
|
11
|
-
@mutex.synchronize do
|
|
12
|
-
@condition.signal
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def run_once(timeout)
|
|
17
|
-
@mutex.synchronize do
|
|
18
|
-
@condition.wait(@mutex, timeout)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def shutdown
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def initialize
|
|
27
|
-
super(Reactor)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
describe Celluloid::EventedMailbox do
|
|
1
|
+
RSpec.describe Celluloid::Mailbox::Evented do
|
|
32
2
|
subject { TestEventedMailbox.new }
|
|
33
3
|
it_behaves_like "a Celluloid Mailbox"
|
|
34
4
|
end
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
describe Celluloid::Future, actor_system: :global do
|
|
1
|
+
RSpec.describe Celluloid::Future, actor_system: :global do
|
|
4
2
|
it "creates future objects that can be retrieved later" do
|
|
5
3
|
future = Celluloid::Future.new { 40 + 2 }
|
|
6
|
-
future.value.
|
|
4
|
+
expect(future.value).to eq(42)
|
|
7
5
|
end
|
|
8
6
|
|
|
9
7
|
it "passes arguments to future blocks" do
|
|
10
8
|
future = Celluloid::Future.new(40) { |n| n + 2 }
|
|
11
|
-
future.value.
|
|
9
|
+
expect(future.value).to eq(42)
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
it "reraises exceptions that occur when the value is retrieved" do
|
|
15
13
|
class ExampleError < StandardError; end
|
|
16
14
|
|
|
17
|
-
future = Celluloid::Future.new {
|
|
15
|
+
future = Celluloid::Future.new { fail ExampleError, "oh noes crash!" }
|
|
18
16
|
expect { future.value }.to raise_exception(ExampleError)
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
it "knows if it's got a value yet" do
|
|
22
|
-
|
|
23
|
-
future.
|
|
24
|
-
|
|
25
|
-
future.
|
|
20
|
+
queue = Queue.new
|
|
21
|
+
future = Celluloid::Future.new { queue.pop }
|
|
22
|
+
|
|
23
|
+
expect(future).not_to be_ready
|
|
24
|
+
queue << nil # let it continue
|
|
25
|
+
|
|
26
|
+
Specs.sleep_and_wait_until { future.ready? }
|
|
27
|
+
|
|
28
|
+
expect(future).to be_ready
|
|
26
29
|
end
|
|
27
30
|
|
|
28
|
-
it "raises
|
|
31
|
+
it "raises TaskTimeout when the future times out" do
|
|
29
32
|
future = Celluloid::Future.new { sleep 2 }
|
|
30
|
-
expect { future.value(1) }.to raise_exception(Celluloid::
|
|
33
|
+
expect { future.value(1) }.to raise_exception(Celluloid::TaskTimeout)
|
|
31
34
|
end
|
|
32
35
|
end
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# set logger early on
|
|
2
|
+
require "celluloid/internals/logger"
|
|
3
|
+
|
|
4
|
+
if Celluloid.group_class == Celluloid::Group::Spawner
|
|
5
|
+
RSpec.describe Celluloid::Group::Spawner do
|
|
6
|
+
it_behaves_like "a Celluloid Group"
|
|
7
|
+
|
|
8
|
+
it "does not leak finished threads" do
|
|
9
|
+
queue = Queue.new
|
|
10
|
+
th = subject.get { queue.pop }
|
|
11
|
+
expect do
|
|
12
|
+
queue << nil
|
|
13
|
+
th.join
|
|
14
|
+
end.to change { subject.group.length }.by(-1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
RSpec.describe Celluloid::Mailbox::Evented do
|
|
2
|
+
subject { TestEventedMailbox.new }
|
|
3
|
+
it_behaves_like "a Celluloid Mailbox"
|
|
4
|
+
|
|
5
|
+
# NOTE: this example seems too exotic to "have to" succeed on RBX, though I
|
|
6
|
+
# don't know why it hangs on subject.receive and the timeout never occurs
|
|
7
|
+
#
|
|
8
|
+
# Other than
|
|
9
|
+
#
|
|
10
|
+
# Links:
|
|
11
|
+
# https://github.com/celluloid/celluloid-io/pull/98
|
|
12
|
+
# https://github.com/celluloid/celluloid-io/issues/56
|
|
13
|
+
#
|
|
14
|
+
unless RUBY_ENGINE == "rbx"
|
|
15
|
+
it "recovers from timeout exceeded to process mailbox message" do
|
|
16
|
+
timeout_interval = Specs::TIMER_QUANTUM + 0.1
|
|
17
|
+
started_at = Time.now
|
|
18
|
+
expect do
|
|
19
|
+
Kernel.send(:timeout, timeout_interval) do
|
|
20
|
+
subject.receive { false }
|
|
21
|
+
end
|
|
22
|
+
end.to raise_exception(Timeout::Error)
|
|
23
|
+
|
|
24
|
+
expect(Time.now - started_at).to be_within(Specs::TIMER_QUANTUM).of timeout_interval
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "discard messages when reactor wakeup fails" do
|
|
29
|
+
expect(Celluloid::Internals::Logger).to receive(:crash).with('reactor crashed', RuntimeError)
|
|
30
|
+
expect(Celluloid.logger).to receive(:debug).with("Discarded message (mailbox is dead): first")
|
|
31
|
+
|
|
32
|
+
bad_reactor = Class.new do
|
|
33
|
+
def wakeup
|
|
34
|
+
fail
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
mailbox = Celluloid::Mailbox::Evented.new(bad_reactor)
|
|
38
|
+
mailbox << :first
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require "weakref"
|
|
2
|
+
|
|
3
|
+
RSpec.describe "Leaks", actor_system: :global, leaktest: true,
|
|
4
|
+
skip: !ENV["CELLULOID_LEAKTEST"] && "leak test disabled" do
|
|
5
|
+
class LeakActor
|
|
6
|
+
include Celluloid
|
|
7
|
+
|
|
8
|
+
def initialize(arg)
|
|
9
|
+
@arg = arg
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(_arg)
|
|
13
|
+
[]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def terminate
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def wait_for_release(weak, _what, count=1000)
|
|
21
|
+
trash = []
|
|
22
|
+
count.times do |step|
|
|
23
|
+
GC.start
|
|
24
|
+
return true unless weak.weakref_alive?
|
|
25
|
+
trash << "*" * step
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def do_actor(what)
|
|
32
|
+
actor = LeakActor.new what
|
|
33
|
+
weak = yield actor
|
|
34
|
+
actor.terminate
|
|
35
|
+
actor = nil
|
|
36
|
+
weak
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def actor_life(what, &block)
|
|
40
|
+
GC.start
|
|
41
|
+
weak = do_actor what, &block
|
|
42
|
+
expect(wait_for_release(weak, what)).to be_truthy
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "celluloid actor" do
|
|
46
|
+
it "is properly destroyed upon termination" do
|
|
47
|
+
actor_life("actor") do |actor|
|
|
48
|
+
WeakRef.new actor
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "celluloid actor call" do
|
|
54
|
+
it "does not hold a reference its arguments on completion" do
|
|
55
|
+
actor_life("call-arg") do |actor|
|
|
56
|
+
arg = []
|
|
57
|
+
actor.call arg
|
|
58
|
+
weak = WeakRef.new arg
|
|
59
|
+
arg = nil
|
|
60
|
+
weak
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "does not hold a reference to the return value" do
|
|
65
|
+
actor_life("call-result") do |actor|
|
|
66
|
+
result = actor.call nil
|
|
67
|
+
weak = WeakRef.new result
|
|
68
|
+
result = nil
|
|
69
|
+
weak
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
RSpec.describe Celluloid::Proxy::Abstract do
|
|
2
|
+
around do |ex|
|
|
3
|
+
Celluloid.boot
|
|
4
|
+
ex.run
|
|
5
|
+
Celluloid.shutdown
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
let(:task_klass) { Celluloid.task_class }
|
|
9
|
+
let(:actor_class) { ExampleActorClass.create(CelluloidSpecs.included_module, task_klass) }
|
|
10
|
+
let(:actor) { actor_class.new "Troy McClure" }
|
|
11
|
+
|
|
12
|
+
let(:logger) { Specs::FakeLogger.current }
|
|
13
|
+
|
|
14
|
+
it "should be eql? to self" do
|
|
15
|
+
expect(actor.eql? actor).to be_truthy
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should be eql? to self even if dead" do
|
|
19
|
+
actor.terminate
|
|
20
|
+
expect(actor.eql? actor).to be_truthy
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should not be eql? to other proxy objects" do
|
|
24
|
+
other_future = Celluloid::Proxy::Future.new(actor.mailbox, actor.__klass__)
|
|
25
|
+
|
|
26
|
+
expect(actor.future.eql? other_future).to be_truthy
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should be possible to compare with non-proxy objects" do
|
|
30
|
+
expect(actor.eql? "string").to be_falsey
|
|
31
|
+
expect("string".eql? actor).to be_falsey
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
1
|
class EveryActor
|
|
4
2
|
include Celluloid
|
|
5
3
|
|
|
@@ -7,39 +5,39 @@ class EveryActor
|
|
|
7
5
|
@trace = []
|
|
8
6
|
@times = []
|
|
9
7
|
@start = Time.now
|
|
10
|
-
|
|
8
|
+
|
|
11
9
|
every(1) { log(1) }
|
|
12
10
|
every(2) { log(2) }
|
|
13
11
|
every(1) { log(11) }
|
|
14
12
|
every(2) { log(22) }
|
|
15
13
|
end
|
|
16
|
-
|
|
14
|
+
|
|
17
15
|
def log(t)
|
|
18
16
|
@trace << t
|
|
19
|
-
|
|
17
|
+
|
|
20
18
|
offset = Time.now - @start
|
|
21
19
|
@times << offset
|
|
22
|
-
|
|
20
|
+
|
|
23
21
|
# puts "log(#{t}) @ #{offset}"
|
|
24
22
|
end
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
|
|
24
|
+
attr_reader :trace
|
|
25
|
+
attr_reader :times
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
describe Celluloid::Actor do
|
|
28
|
+
RSpec.describe "Celluloid::Actor timers" do
|
|
31
29
|
it "run every(t) task several times" do
|
|
32
30
|
Celluloid.boot
|
|
33
|
-
|
|
31
|
+
|
|
34
32
|
every_actor = EveryActor.new
|
|
35
|
-
|
|
33
|
+
|
|
36
34
|
sleep 5.5
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
|
|
36
|
+
every_actor.times
|
|
39
37
|
trace = every_actor.trace
|
|
40
|
-
|
|
38
|
+
|
|
41
39
|
Celluloid.shutdown
|
|
42
|
-
|
|
40
|
+
|
|
43
41
|
expect(trace.count(1)).to be == 5
|
|
44
42
|
expect(trace.count(11)).to be == 5
|
|
45
43
|
expect(trace.count(2)).to be == 2
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
RSpec.describe "Deprecated Celluloid::ActorSystem" do
|
|
2
|
+
subject { Celluloid::ActorSystem.new }
|
|
3
|
+
|
|
4
|
+
class DeprecatedTestActor
|
|
5
|
+
include Celluloid
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "supports non-global ActorSystem" do
|
|
9
|
+
subject.within do
|
|
10
|
+
expect(Celluloid.actor_system).to eq(subject)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "starts default actors" do
|
|
15
|
+
subject.start
|
|
16
|
+
expect(subject.registered).to eq(Celluloid::ActorSystem::ROOT_SERVICES.map { |r| r[:as] })
|
|
17
|
+
subject.shutdown
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "support getting threads" do
|
|
21
|
+
subject.start
|
|
22
|
+
queue = Queue.new
|
|
23
|
+
thread = subject.get_thread do
|
|
24
|
+
expect(Celluloid.actor_system).to eq(subject)
|
|
25
|
+
queue << nil
|
|
26
|
+
end
|
|
27
|
+
queue.pop
|
|
28
|
+
subject.shutdown
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "allows a stack dump" do
|
|
32
|
+
expect(subject.stack_dump).to be_a(Celluloid::StackDump)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "returns named actors" do
|
|
36
|
+
subject.start
|
|
37
|
+
|
|
38
|
+
subject.within do
|
|
39
|
+
DeprecatedTestActor.supervise_as :test
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
expect(subject.registered).to include(:test)
|
|
43
|
+
subject.shutdown
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "returns running actors" do
|
|
47
|
+
expect(subject.running).to be_empty
|
|
48
|
+
|
|
49
|
+
first = subject.within do
|
|
50
|
+
DeprecatedTestActor.new
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
second = subject.within do
|
|
54
|
+
DeprecatedTestActor.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
expect(subject.running).to eq([first, second])
|
|
58
|
+
subject.shutdown
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "shuts down" do
|
|
62
|
+
subject.shutdown
|
|
63
|
+
|
|
64
|
+
expect { subject.get_thread }
|
|
65
|
+
.to raise_error(Celluloid::NotActive)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "warns nicely when no actor system is started" do
|
|
69
|
+
expect { DeprecatedTestActor.new }
|
|
70
|
+
.to raise_error("Celluloid is not yet started; use Celluloid.boot")
|
|
71
|
+
end
|
|
72
|
+
end unless $CELLULOID_BACKPORTED == false
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
RSpec.describe "Deprecated Blocks", actor_system: :global do
|
|
2
|
+
class DeprecatedBlockActor
|
|
3
|
+
include Celluloid
|
|
4
|
+
|
|
5
|
+
def initialize(name)
|
|
6
|
+
@name = name
|
|
7
|
+
end
|
|
8
|
+
attr_reader :name
|
|
9
|
+
|
|
10
|
+
def ask_for_something(other)
|
|
11
|
+
sender_actor = current_actor
|
|
12
|
+
$data << [:outside, @name, current_actor.name]
|
|
13
|
+
other.do_something_and_callback do |value|
|
|
14
|
+
$data << [:yielded, @name, current_actor.name]
|
|
15
|
+
$data << receive_result(:self)
|
|
16
|
+
$data << current_actor.receive_result(:current_actor)
|
|
17
|
+
$data << sender_actor.receive_result(:sender)
|
|
18
|
+
"somevalue"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def do_something_and_callback
|
|
23
|
+
$data << [:something, @name, current_actor.name]
|
|
24
|
+
$data << yield(:foo)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def receive_result(result)
|
|
28
|
+
[result, @name, current_actor.name]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "works" do
|
|
33
|
+
$data = []
|
|
34
|
+
|
|
35
|
+
a1 = DeprecatedBlockActor.new("one")
|
|
36
|
+
a2 = DeprecatedBlockActor.new("two")
|
|
37
|
+
|
|
38
|
+
a1.ask_for_something a2
|
|
39
|
+
|
|
40
|
+
expected = [
|
|
41
|
+
[:outside, "one", "one"],
|
|
42
|
+
[:something, "two", "two"],
|
|
43
|
+
[:yielded, "one", "one"],
|
|
44
|
+
[:self, "one", "one"],
|
|
45
|
+
[:current_actor, "one", "one"],
|
|
46
|
+
[:sender, "one", "one"],
|
|
47
|
+
"somevalue",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
expect($data).to eq(expected)
|
|
51
|
+
end
|
|
52
|
+
end unless $CELLULOID_BACKPORTED == false
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
RSpec.describe "Deprecated Celluloid::SyncCall", actor_system: :global do
|
|
2
|
+
subject { Celluloid::SyncCall.new }
|
|
3
|
+
|
|
4
|
+
let(:actor) { DeprecatedCallExampleActor.new }
|
|
5
|
+
|
|
6
|
+
context "when obj does not respond to a method" do
|
|
7
|
+
it "raises a NoMethodError" do
|
|
8
|
+
expect do
|
|
9
|
+
actor.the_method_that_wasnt_there
|
|
10
|
+
end.to raise_exception(NoMethodError)
|
|
11
|
+
expect(actor).to be_alive
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "when obj raises during inspect" do
|
|
15
|
+
it "should emulate obj.inspect" do
|
|
16
|
+
expect(actor).to_not receive(:inspect)
|
|
17
|
+
expect { actor.no_such_method }.to raise_exception(
|
|
18
|
+
NoMethodError,
|
|
19
|
+
/undefined method `no_such_method' for #\<DeprecatedCallExampleActor:0x[a-f0-9]+>/,
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "aborts with ArgumentError when a method is called with too many arguments" do
|
|
26
|
+
expect do
|
|
27
|
+
actor.actual_method("with too many arguments")
|
|
28
|
+
end.to raise_exception(ArgumentError)
|
|
29
|
+
|
|
30
|
+
expect(actor).to be_alive
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "preserves call chains across synchronous calls" do
|
|
34
|
+
actor2 = DeprecatedCallExampleActor.new(actor)
|
|
35
|
+
|
|
36
|
+
uuid, next_actor_uuid = actor2.chained_call_ids
|
|
37
|
+
expect(uuid).to eq next_actor_uuid
|
|
38
|
+
end
|
|
39
|
+
end unless $CELLULOID_BACKPORTED == false
|