celluloid 0.18.0.pre → 0.18.0
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 +258 -39
- data/CONDUCT.md +13 -0
- data/CONTRIBUTING.md +39 -0
- data/README.md +54 -165
- data/REFACTOR.md +1 -0
- 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 +2 -2
- 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/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/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/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/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 -323
- 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/perf.yml +0 -0
- 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/backported.rb +0 -2
- data/lib/celluloid/current.rb +0 -2
- data/lib/celluloid/deprecate.rb +0 -34
- data/lib/celluloid/fiber.rb +0 -32
- data/lib/celluloid/managed.rb +0 -3
- 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,116 @@
|
|
1
|
+
module Celluloid
|
2
|
+
# Supervise collections of actors as a group
|
3
|
+
module Supervision
|
4
|
+
class Container
|
5
|
+
class Instance
|
6
|
+
attr_reader :name, :actor
|
7
|
+
|
8
|
+
# @option options [#call, Object] :args ([]) arguments array for the
|
9
|
+
# actor's constructor (lazy evaluation if it responds to #call)
|
10
|
+
def initialize(configuration = {})
|
11
|
+
@type = configuration.delete(:type)
|
12
|
+
@registry = configuration.delete(:registry)
|
13
|
+
@branch = configuration.delete(:branch) || :services
|
14
|
+
@configuration = configuration
|
15
|
+
|
16
|
+
# allows injections inside initialize, start, and restart
|
17
|
+
@injections = configuration.delete(:injections) || {}
|
18
|
+
invoke_injection(:before_initialize)
|
19
|
+
|
20
|
+
# Stringify keys :/
|
21
|
+
# de @configuration = configuration.each_with_object({}) { |(k,v), h| h[k.to_s] = v }
|
22
|
+
|
23
|
+
@name = @configuration[:as]
|
24
|
+
@block = @configuration[:block]
|
25
|
+
@args = prepare_args(@configuration[:args])
|
26
|
+
@method = @configuration[:method] || "new_link"
|
27
|
+
add_accessors
|
28
|
+
invoke_injection(:after_initialize)
|
29
|
+
start
|
30
|
+
end
|
31
|
+
|
32
|
+
def start
|
33
|
+
invoke_injection(:before_start)
|
34
|
+
@actor = @type.send(@method, *@args, &@block)
|
35
|
+
@registry.add(@name, @actor, @branch) if @name
|
36
|
+
invoke_injection(:after_start)
|
37
|
+
rescue Celluloid::TaskTimeout => ex
|
38
|
+
Internals::Logger.error("TaskTimeout at start of supervised instance of #{@type}")
|
39
|
+
raise ex
|
40
|
+
# TODO: Implement timeout/retry(?)
|
41
|
+
rescue => ex
|
42
|
+
Internals::Logger.error("Error ( #{ex.class} ) at start of supervised instance of #{@type}")
|
43
|
+
raise ex
|
44
|
+
end
|
45
|
+
|
46
|
+
def restart
|
47
|
+
# no need to reset @actor, as this is called in an `exclusive {}` block
|
48
|
+
# @actor = nil
|
49
|
+
# cleanup
|
50
|
+
invoke_injection(:before_restart)
|
51
|
+
start
|
52
|
+
invoke_injection(:after_restart)
|
53
|
+
end
|
54
|
+
|
55
|
+
def terminate
|
56
|
+
@actor.terminate if @actor
|
57
|
+
cleanup
|
58
|
+
rescue DeadActorError
|
59
|
+
end
|
60
|
+
|
61
|
+
def cleanup
|
62
|
+
@registry.delete(@name) if @name
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def add_accessors
|
68
|
+
remove_accessors
|
69
|
+
if @configuration[:accessors].is_a? Array
|
70
|
+
# TODO: Decide which level to keep, and only keep that.
|
71
|
+
# Do we provide access by Celluloid.accessor
|
72
|
+
# Do we provide access by Celluloid.actor_system.accessor
|
73
|
+
@configuration[:accessors].each do |name|
|
74
|
+
Celluloid.instance_exec(@configuration[:as], name) do |actor, _where|
|
75
|
+
define_method(name) do
|
76
|
+
Celluloid.actor_system[actor]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
Celluloid::Actor::System.instance_exec(@configuration[:as], name) do |actor, _where|
|
80
|
+
define_method(name) do
|
81
|
+
Celluloid.actor_system[actor]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def remove_accessors
|
89
|
+
if @configuration[:accessors].is_a? Array
|
90
|
+
@configuration[:accessors].each do |name|
|
91
|
+
Celluloid.instance_eval do
|
92
|
+
remove_method(name) rescue nil # avoid warnings in tests
|
93
|
+
end
|
94
|
+
Celluloid::Actor::System.instance_eval do
|
95
|
+
remove_method(name) rescue nil # avoid warnings in tests
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def invoke_injection(name)
|
102
|
+
return unless @injections
|
103
|
+
block = @injections[name]
|
104
|
+
instance_eval(&block) if block.is_a? Proc
|
105
|
+
end
|
106
|
+
|
107
|
+
# Executes args if it has the method #call, and converts the return
|
108
|
+
# value to an Array. Otherwise, it just converts it to an Array.
|
109
|
+
def prepare_args(args)
|
110
|
+
args = args.call if args.respond_to?(:call)
|
111
|
+
Array(args)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Supervision
|
3
|
+
class Container
|
4
|
+
# Manages a fixed-size pool of actors
|
5
|
+
# Delegates work (i.e. methods) and supervises actors
|
6
|
+
# Don't use this class directly. Instead use MyKlass.pool
|
7
|
+
class Pool
|
8
|
+
include Celluloid
|
9
|
+
|
10
|
+
trap_exit :__crash_handler__
|
11
|
+
finalizer :__shutdown__
|
12
|
+
|
13
|
+
attr_reader :size, :actors
|
14
|
+
|
15
|
+
def initialize(options = {})
|
16
|
+
@idle = []
|
17
|
+
@busy = []
|
18
|
+
@klass = options[:actors]
|
19
|
+
@actors = Set.new
|
20
|
+
@mutex = Mutex.new
|
21
|
+
|
22
|
+
@size = options[:size] || [Celluloid.cores || 2, 2].max
|
23
|
+
@args = options[:args] ? Array(options[:args]) : []
|
24
|
+
|
25
|
+
# Do this last since it can suspend and/or crash
|
26
|
+
@idle = @size.times.map { __spawn_actor__ }
|
27
|
+
end
|
28
|
+
|
29
|
+
def __shutdown__
|
30
|
+
return unless defined?(@actors) && @actors
|
31
|
+
# TODO: these can be nil if initializer crashes
|
32
|
+
terminators = @actors.map do |actor|
|
33
|
+
begin
|
34
|
+
actor.future(:terminate)
|
35
|
+
rescue DeadActorError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
terminators.compact.each { |terminator| terminator.value rescue nil }
|
40
|
+
end
|
41
|
+
|
42
|
+
def _send_(method, *args, &block)
|
43
|
+
actor = __provision_actor__
|
44
|
+
begin
|
45
|
+
actor._send_ method, *args, &block
|
46
|
+
rescue DeadActorError # if we get a dead actor out of the pool
|
47
|
+
wait :respawn_complete
|
48
|
+
actor = __provision_actor__
|
49
|
+
retry
|
50
|
+
rescue ::Exception => ex
|
51
|
+
abort ex
|
52
|
+
ensure
|
53
|
+
if actor.alive?
|
54
|
+
@idle << actor
|
55
|
+
@busy.delete actor
|
56
|
+
|
57
|
+
# Broadcast that actor is done processing and
|
58
|
+
# waiting idle
|
59
|
+
signal :actor_idle
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def name
|
65
|
+
_send_ @mailbox, :name
|
66
|
+
end
|
67
|
+
|
68
|
+
def is_a?(klass)
|
69
|
+
_send_ :is_a?, klass
|
70
|
+
end
|
71
|
+
|
72
|
+
def kind_of?(klass)
|
73
|
+
_send_ :kind_of?, klass
|
74
|
+
end
|
75
|
+
|
76
|
+
def methods(include_ancestors = true)
|
77
|
+
_send_ :methods, include_ancestors
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_s
|
81
|
+
_send_ :to_s
|
82
|
+
end
|
83
|
+
|
84
|
+
def inspect
|
85
|
+
_send_ :inspect
|
86
|
+
end
|
87
|
+
|
88
|
+
def size=(new_size)
|
89
|
+
new_size = [0, new_size].max
|
90
|
+
if new_size > size
|
91
|
+
delta = new_size - size
|
92
|
+
delta.times { @idle << __spawn_actor__ }
|
93
|
+
else
|
94
|
+
(size - new_size).times do
|
95
|
+
actor = __provision_actor__
|
96
|
+
unlink actor
|
97
|
+
@busy.delete actor
|
98
|
+
@actors.delete actor
|
99
|
+
actor.terminate
|
100
|
+
end
|
101
|
+
end
|
102
|
+
@size = new_size
|
103
|
+
end
|
104
|
+
|
105
|
+
def busy_size
|
106
|
+
@mutex.synchronize { @busy.length }
|
107
|
+
end
|
108
|
+
|
109
|
+
def idle_size
|
110
|
+
@mutex.synchronize { @idle.length }
|
111
|
+
end
|
112
|
+
|
113
|
+
def __idle?(actor)
|
114
|
+
@mutex.synchronize { @idle.include? actor }
|
115
|
+
end
|
116
|
+
|
117
|
+
def __busy?(actor)
|
118
|
+
@mutex.synchronize { @busy.include? actor }
|
119
|
+
end
|
120
|
+
|
121
|
+
def __busy
|
122
|
+
@mutex.synchronize { @busy }
|
123
|
+
end
|
124
|
+
|
125
|
+
def __idle
|
126
|
+
@mutex.synchronize { @idle }
|
127
|
+
end
|
128
|
+
|
129
|
+
def __state(actor)
|
130
|
+
return :busy if __busy?(actor)
|
131
|
+
return :idle if __idle?(actor)
|
132
|
+
:missing
|
133
|
+
end
|
134
|
+
|
135
|
+
# Instantiate an actor, add it to the actor Set, and return it
|
136
|
+
def __spawn_actor__
|
137
|
+
actor = @klass.new_link(*@args)
|
138
|
+
@mutex.synchronize { @actors.add(actor) }
|
139
|
+
@actors.add(actor)
|
140
|
+
actor
|
141
|
+
end
|
142
|
+
|
143
|
+
# Provision a new actor ( take it out of idle, move it into busy, and avail it )
|
144
|
+
def __provision_actor__
|
145
|
+
Task.current.guard_warnings = true
|
146
|
+
@mutex.synchronize do
|
147
|
+
while @idle.empty?
|
148
|
+
# Wait for responses from one of the busy actors
|
149
|
+
response = exclusive { receive { |msg| msg.is_a?(Internals::Response) } }
|
150
|
+
Thread.current[:celluloid_actor].handle_message(response)
|
151
|
+
end
|
152
|
+
|
153
|
+
actor = @idle.shift
|
154
|
+
@busy << actor
|
155
|
+
actor
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Spawn a new worker for every crashed one
|
160
|
+
def __crash_handler__(actor, reason)
|
161
|
+
@busy.delete actor
|
162
|
+
@idle.delete actor
|
163
|
+
@actors.delete actor
|
164
|
+
return unless reason
|
165
|
+
@idle << __spawn_actor__
|
166
|
+
signal :respawn_complete
|
167
|
+
end
|
168
|
+
|
169
|
+
def respond_to?(meth, include_private = false)
|
170
|
+
# NOTE: use method() here since this class
|
171
|
+
# shouldn't be used directly, and method() is less
|
172
|
+
# likely to be "reimplemented" inconsistently
|
173
|
+
# with other Object.*method* methods.
|
174
|
+
|
175
|
+
found = method(meth)
|
176
|
+
if include_private
|
177
|
+
found ? true : false
|
178
|
+
else
|
179
|
+
if found.is_a?(UnboundMethod)
|
180
|
+
found.owner.public_instance_methods.include?(meth) ||
|
181
|
+
found.owner.protected_instance_methods.include?(meth)
|
182
|
+
else
|
183
|
+
found.receiver.public_methods.include?(meth) ||
|
184
|
+
found.receiver.protected_methods.include?(meth)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
rescue NameError
|
188
|
+
false
|
189
|
+
end
|
190
|
+
|
191
|
+
def method_missing(method, *args, &block)
|
192
|
+
if respond_to?(method)
|
193
|
+
_send_ method, *args, &block
|
194
|
+
else
|
195
|
+
super
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Since Pool allocates worker objects only just before calling them,
|
200
|
+
# we can still help Celluloid::Call detect passing invalid parameters to
|
201
|
+
# async methods by checking for those methods on the worker class
|
202
|
+
def method(meth)
|
203
|
+
super
|
204
|
+
rescue NameError
|
205
|
+
@klass.instance_method(meth.to_sym)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Supervision
|
3
|
+
module Service
|
4
|
+
class Root < Container
|
5
|
+
class << self
|
6
|
+
def define
|
7
|
+
super({
|
8
|
+
supervise: Celluloid.actor_system.root_configuration,
|
9
|
+
as: :root_supervisor,
|
10
|
+
accessors: [:root],
|
11
|
+
branch: :root,
|
12
|
+
type: self
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
def deploy(instances)
|
17
|
+
super(supervise: instances, branch: :root, as: :root, type: self)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
def provider
|
21
|
+
Celluloid.root_services
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class Public < Container; end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# collect together all instances of the `supervise` method
|
2
|
+
module Celluloid
|
3
|
+
class << self
|
4
|
+
def supervise(config = {}, &block)
|
5
|
+
supervisor = Supervision.router(config)
|
6
|
+
supervisor.supervise(config, &block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
module ClassMethods
|
10
|
+
def supervise(config = {}, &block)
|
11
|
+
Celluloid.supervise(config.merge(type: self), &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
module Supervision
|
15
|
+
class << self
|
16
|
+
def router(_config = {})
|
17
|
+
# TODO: Actually route.
|
18
|
+
Celluloid.services # for now, hardcode .services
|
19
|
+
end
|
20
|
+
end
|
21
|
+
class Container
|
22
|
+
class << self
|
23
|
+
def supervise(config, &block)
|
24
|
+
blocks << lambda do |container|
|
25
|
+
container.add(config, &block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def supervise(config, &block)
|
30
|
+
add(Configuration.options(config, block: block))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Supervision
|
3
|
+
class Configuration
|
4
|
+
class << self
|
5
|
+
def valid?(configuration, fails = false)
|
6
|
+
parameters(:mandatory).each do |k|
|
7
|
+
unless configuration.key? k
|
8
|
+
if fails
|
9
|
+
raise Error::Incomplete, "Missing `:#{k}` in supervision configuration."
|
10
|
+
else
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
arity.each do |klass, args|
|
16
|
+
next if configuration[args].is_a? Proc
|
17
|
+
__a = configuration[args] && configuration[args].count || 0
|
18
|
+
__arity = configuration[klass].allocate.method(:initialize).arity
|
19
|
+
unless (__arity < 0 && __a >= __arity.abs - 1) || __a == __arity.abs
|
20
|
+
if fails
|
21
|
+
raise ArgumentError, "#{__a} vs. #{__arity}"
|
22
|
+
else
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def options(config = {}, options = {})
|
31
|
+
configuration = config.merge(options)
|
32
|
+
return configuration if configuration.is_a? Configuration
|
33
|
+
configuration[:configuration] = Container::Behavior.configure(configuration)
|
34
|
+
valid?(configuration, true)
|
35
|
+
configuration
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|