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,113 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Supervision
|
3
|
+
class Configuration
|
4
|
+
class Instance
|
5
|
+
attr_accessor :configuration
|
6
|
+
|
7
|
+
def initialize(configuration = {})
|
8
|
+
@state = :initializing # :ready
|
9
|
+
resync_accessors
|
10
|
+
@configuration = configuration
|
11
|
+
define(configuration) if configuration.any?
|
12
|
+
end
|
13
|
+
|
14
|
+
def export
|
15
|
+
@configuration.reject { |k, _v| REMOVE_AT_EXPORT.include? k }
|
16
|
+
end
|
17
|
+
|
18
|
+
def ready?(fail = false)
|
19
|
+
unless @state == :ready
|
20
|
+
@state = :ready if Configuration.valid? @configuration, fail
|
21
|
+
end
|
22
|
+
@state == :ready
|
23
|
+
end
|
24
|
+
|
25
|
+
def define(instance, fail = false)
|
26
|
+
raise Configuration::Error::AlreadyDefined if ready? fail
|
27
|
+
invoke_injection(:before_configuration)
|
28
|
+
@configuration = Configuration.options(instance)
|
29
|
+
ready?
|
30
|
+
end
|
31
|
+
|
32
|
+
def injection!(key, proc)
|
33
|
+
@configuration[:injections] ||= {}
|
34
|
+
@configuration[:injections][key] = proc
|
35
|
+
end
|
36
|
+
|
37
|
+
def injections!(_procs)
|
38
|
+
@configuration[:injections] = proces
|
39
|
+
end
|
40
|
+
|
41
|
+
def resync_accessors
|
42
|
+
# methods for setting and getting the usual defaults
|
43
|
+
Configuration.parameters(:mandatory, :optional, :plugins, :meta).each do |key|
|
44
|
+
self.class.instance_eval do
|
45
|
+
remove_method :"#{key}!" rescue nil # avoid warnings in tests
|
46
|
+
define_method(:"#{key}!") { |value| @configuration[key] = value }
|
47
|
+
end
|
48
|
+
self.class.instance_eval do
|
49
|
+
remove_method :"#{key}=" rescue nil # avoid warnings in tests
|
50
|
+
define_method(:"#{key}=") { |value| @configuration[key] = value }
|
51
|
+
end
|
52
|
+
self.class.instance_eval do
|
53
|
+
remove_method :"#{key}?" rescue nil # avoid warnings in tests
|
54
|
+
define_method(:"#{key}?") { !@configuration[key].nil? }
|
55
|
+
end
|
56
|
+
self.class.instance_eval do
|
57
|
+
remove_method :"#{key}" rescue nil # avoid warnings in tests
|
58
|
+
define_method(:"#{key}") { @configuration[key] }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
Configuration.aliases.each do |_alias, _original|
|
63
|
+
["!", :"=", :"?", :""]. each do |m|
|
64
|
+
self.class.instance_eval do
|
65
|
+
remove_method :"#{_alias}#{m}" rescue nil # avoid warnings in tests
|
66
|
+
alias_method :"#{_alias}#{m}", :"#{_original}#{m}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
def merge!(values)
|
74
|
+
@configuration = @configuration.merge(values)
|
75
|
+
end
|
76
|
+
|
77
|
+
def merge(values)
|
78
|
+
if values.is_a? Configuration
|
79
|
+
@configuration.merge(values.configuration)
|
80
|
+
elsif values.is_a? Hash
|
81
|
+
@configuration.merge(values)
|
82
|
+
else
|
83
|
+
raise Error::Invalid
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def key?(k)
|
88
|
+
@configuration.key?(k)
|
89
|
+
end
|
90
|
+
|
91
|
+
def set(key, value)
|
92
|
+
@configuration[key] = value
|
93
|
+
end
|
94
|
+
alias []= set
|
95
|
+
|
96
|
+
def get(key)
|
97
|
+
@configuration[key]
|
98
|
+
end
|
99
|
+
alias [] get
|
100
|
+
|
101
|
+
def delete(k)
|
102
|
+
@configuration.delete(k)
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def invoke_injection(_point)
|
108
|
+
# de puts "injection? #{point}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Supervision
|
3
|
+
# TODO: Do not hard-code. Allow configurable values.
|
4
|
+
INSTANCE_RETRY_WAIT = 3
|
5
|
+
INSTANCE_RETRY_LIMIT = 5
|
6
|
+
|
7
|
+
module Error
|
8
|
+
class NoPublicService < Celluloid::Error; end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Configuration
|
12
|
+
module Error
|
13
|
+
class AlreadyDefined < Celluloid::Error; end
|
14
|
+
class InvalidSupervisor < Celluloid::Error; end
|
15
|
+
class InvalidValues < Celluloid::Error; end
|
16
|
+
class Incomplete < Celluloid::Error; end
|
17
|
+
class Invalid < Celluloid::Error; end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Using class variable so that parameters can be added by plugins.
|
21
|
+
|
22
|
+
@@parameters = {
|
23
|
+
|
24
|
+
mandatory: [:type],
|
25
|
+
|
26
|
+
optional: %i[
|
27
|
+
as
|
28
|
+
args
|
29
|
+
block
|
30
|
+
],
|
31
|
+
|
32
|
+
# TODO: Move these into Behaviors.
|
33
|
+
plugins: [
|
34
|
+
# de :size, # Supervision::Pool
|
35
|
+
# de :routers, # Supervision::Coordinator
|
36
|
+
# de :supervises # Supervision::Tree
|
37
|
+
],
|
38
|
+
|
39
|
+
meta: %i[
|
40
|
+
registry
|
41
|
+
branch
|
42
|
+
method
|
43
|
+
]
|
44
|
+
}
|
45
|
+
|
46
|
+
@@arity = {
|
47
|
+
type: :args
|
48
|
+
}
|
49
|
+
|
50
|
+
@@aliases = {
|
51
|
+
name: :as,
|
52
|
+
kind: :type,
|
53
|
+
# de :pool => :size, # TODO: Move into Behaviors.
|
54
|
+
# de :supervise => :supervises
|
55
|
+
}
|
56
|
+
|
57
|
+
@@defaults = {}
|
58
|
+
|
59
|
+
class << self
|
60
|
+
def save_defaults
|
61
|
+
@@defaults = {
|
62
|
+
parameters: @@parameters.each_with_object({}) { |(k, v), p| p[k] = v.dup; },
|
63
|
+
aliases: @@aliases.dup,
|
64
|
+
arity: @@arity.dup
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def resync_parameters
|
69
|
+
@@parameters = @@defaults[:parameters].each_with_object({}) { |(k, v), p| p[k] = v.dup; }
|
70
|
+
@@aliases = @@defaults[:aliases].dup
|
71
|
+
@@arity = @@defaults[:arity].dup
|
72
|
+
end
|
73
|
+
|
74
|
+
def parameters(*args)
|
75
|
+
args.inject([]) { |parameters, p| parameters += @@parameters[p]; parameters }
|
76
|
+
end
|
77
|
+
|
78
|
+
def parameter!(key, value)
|
79
|
+
@@parameters[key] << value unless @@parameters[key].include? value
|
80
|
+
end
|
81
|
+
|
82
|
+
def arity
|
83
|
+
@@arity
|
84
|
+
end
|
85
|
+
|
86
|
+
def arity!(key, value)
|
87
|
+
@@arity[key] = value
|
88
|
+
end
|
89
|
+
|
90
|
+
def aliases
|
91
|
+
@@aliases
|
92
|
+
end
|
93
|
+
|
94
|
+
def alias!(aliased, original)
|
95
|
+
@@aliases[aliased] = original
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
save_defaults
|
100
|
+
resync_parameters
|
101
|
+
|
102
|
+
# This was originally added for `#pool` and `PoolManager
|
103
|
+
# `:before_initialize` was added to allow detecting `:size => N`
|
104
|
+
# and turning that into a pool. Other uses could be for `coordinator`
|
105
|
+
# appointing a `router` by detecting `:routers => N`, and many other uses.
|
106
|
+
|
107
|
+
################ These are applied inside Supervision::Member ################
|
108
|
+
|
109
|
+
REMOVE_AT_EXPORT = %i[
|
110
|
+
configuration
|
111
|
+
behavior
|
112
|
+
].freeze
|
113
|
+
|
114
|
+
INJECTIONS = %i[
|
115
|
+
configuration
|
116
|
+
before_initialization
|
117
|
+
after_initialization
|
118
|
+
before_start
|
119
|
+
before_restart
|
120
|
+
].freeze
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module Celluloid
|
2
|
+
# Supervise actor instances in a container.
|
3
|
+
module Supervision
|
4
|
+
class Container
|
5
|
+
include Celluloid
|
6
|
+
|
7
|
+
trap_exit :restart_actor
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def define(options)
|
11
|
+
Configuration.define(top(options))
|
12
|
+
end
|
13
|
+
|
14
|
+
def deploy(options)
|
15
|
+
Configuration.deploy(top(options))
|
16
|
+
end
|
17
|
+
|
18
|
+
def top(options)
|
19
|
+
{
|
20
|
+
as: options.delete(:as),
|
21
|
+
type: (options.delete(:type) || self),
|
22
|
+
branch: (options.delete(:branch) || :services),
|
23
|
+
supervise: options.delete(:supervise) || []
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Actors or sub-applications to be supervised
|
28
|
+
def blocks
|
29
|
+
@blocks ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
# Start this application (and watch it with a supervisor)
|
33
|
+
def run!(options = {})
|
34
|
+
container = new(options) do |g|
|
35
|
+
blocks.each do |block|
|
36
|
+
block.call(g)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
container
|
40
|
+
end
|
41
|
+
|
42
|
+
# Run the application in the foreground with a simple watchdog
|
43
|
+
def run(options = {})
|
44
|
+
loop do
|
45
|
+
supervisor = run!(options)
|
46
|
+
|
47
|
+
# Take five, toplevel supervisor
|
48
|
+
sleep 5 while supervisor.alive? # Why 5?
|
49
|
+
|
50
|
+
Internals::Logger.error "!!! Celluloid::Supervision::Container #{self} crashed. Restarting..."
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
finalizer :finalize
|
56
|
+
|
57
|
+
attr_accessor :registry
|
58
|
+
|
59
|
+
# Start the container.
|
60
|
+
def initialize(options = {})
|
61
|
+
options = { registry: options } if options.is_a? Internals::Registry
|
62
|
+
@state = :initializing
|
63
|
+
@actors = [] # instances in the container
|
64
|
+
@registry = options.delete(:registry) || Celluloid.actor_system.registry
|
65
|
+
@branch = options.delete(:branch) || :services
|
66
|
+
yield current_actor if block_given?
|
67
|
+
end
|
68
|
+
|
69
|
+
execute_block_on_receiver :initialize, :supervise, :supervise_as
|
70
|
+
|
71
|
+
def add(configuration)
|
72
|
+
Configuration.valid?(configuration, true)
|
73
|
+
@actors << Instance.new(configuration.merge(registry: @registry, branch: @branch))
|
74
|
+
@state = :running
|
75
|
+
add_accessors configuration
|
76
|
+
Actor.current
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_accessors(configuration)
|
80
|
+
if configuration[:as]
|
81
|
+
unless methods.include? configuration[:as]
|
82
|
+
self.class.instance_eval do
|
83
|
+
define_method(configuration[:as]) do
|
84
|
+
@registry[configuration[:as]]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def remove_accessors; end
|
92
|
+
|
93
|
+
def remove(actor)
|
94
|
+
actor = Celluloid::Actor[actor] if actor.is_a? Symbol
|
95
|
+
instance = find(actor)
|
96
|
+
instance.terminate if instance
|
97
|
+
end
|
98
|
+
|
99
|
+
def actors
|
100
|
+
@actors.map(&:actor)
|
101
|
+
end
|
102
|
+
|
103
|
+
def find(actor)
|
104
|
+
@actors.find do |instance|
|
105
|
+
instance.actor == actor
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def [](actor_name)
|
110
|
+
@registry[actor_name]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Restart a crashed actor
|
114
|
+
def restart_actor(actor, reason)
|
115
|
+
return if @state == :shutdown
|
116
|
+
instance = find(actor)
|
117
|
+
raise "a container instance went missing. This shouldn't be!" unless instance
|
118
|
+
|
119
|
+
if reason
|
120
|
+
exclusive { instance.restart }
|
121
|
+
else
|
122
|
+
instance.cleanup
|
123
|
+
@actors.delete(instance)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def shutdown
|
128
|
+
@state = :shutdown
|
129
|
+
finalize
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def finalize
|
135
|
+
if @actors
|
136
|
+
@actors.reverse_each do |instance|
|
137
|
+
instance.terminate
|
138
|
+
@actors.delete(instance)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Supervision
|
3
|
+
class Container
|
4
|
+
module Behavior
|
5
|
+
@@injections = {} # Hash of Class => Hash of Injections
|
6
|
+
@@behaviors = {} # Hash of identifying symbol parameter => Class
|
7
|
+
|
8
|
+
module Error
|
9
|
+
class Mutant < Celluloid::Error; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def included(klass)
|
14
|
+
klass.send :extend, ClassMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
def injections
|
18
|
+
@@injections
|
19
|
+
end
|
20
|
+
|
21
|
+
def [](identifier)
|
22
|
+
@@behaviors[identifier]
|
23
|
+
end
|
24
|
+
|
25
|
+
def []=(identifier, behavior)
|
26
|
+
@@behaviors[identifier] = behavior
|
27
|
+
end
|
28
|
+
|
29
|
+
def parameter(identifier, options)
|
30
|
+
found = nil
|
31
|
+
p = Configuration.aliases.each_with_object([identifier]) { |(a, i), invoke| invoke << a if i == identifier; }
|
32
|
+
case p.count { |parameter| found = parameter; options.key?(parameter) }
|
33
|
+
when 1
|
34
|
+
found
|
35
|
+
when 0
|
36
|
+
|
37
|
+
else
|
38
|
+
raise Error::Mutant, "More than one kind of identifiable behavior parameter."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Beware of order. There may be multiple behavior injections, but their order is not determined ( yet )
|
43
|
+
# Right now, something like a pool-coordinator-tree supervisor mutant are absolutely expected to crash.
|
44
|
+
# Therefore, sorry Professor X -- we kill every Mutant. On sight, no questions asked. Zero mutant love.
|
45
|
+
def configure(options)
|
46
|
+
behavior = nil
|
47
|
+
injection = nil
|
48
|
+
@@behaviors.map do |identifier, injector|
|
49
|
+
if identifier = parameter(identifier, options)
|
50
|
+
if behavior
|
51
|
+
raise Error::Mutant, "More than one type of behavior expected."
|
52
|
+
else
|
53
|
+
if @@injections[injector].include?(:configuration)
|
54
|
+
injection = @@injections[behavior = injector][:configuration]
|
55
|
+
options[:behavior] ||= behavior
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
options[:type] ||= behavior
|
62
|
+
injection || proc { @configuration }
|
63
|
+
end
|
64
|
+
|
65
|
+
module ClassMethods
|
66
|
+
def identifier!(identifier, *aliases)
|
67
|
+
Behavior[identifier] = self
|
68
|
+
Configuration.parameter! :plugins, identifier
|
69
|
+
aliases.each do |aliased|
|
70
|
+
Configuration.alias! aliased, identifier
|
71
|
+
end
|
72
|
+
Configuration.save_defaults
|
73
|
+
end
|
74
|
+
|
75
|
+
def behavior_injections
|
76
|
+
Behavior.injections[self] ||= {}
|
77
|
+
end
|
78
|
+
|
79
|
+
Configuration::INJECTIONS.each do |point|
|
80
|
+
define_method(point) do |&injector|
|
81
|
+
behavior_injections[point] = injector
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|