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.
Files changed (179) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +114 -39
  3. data/CONDUCT.md +13 -0
  4. data/CONTRIBUTING.md +39 -0
  5. data/README.md +59 -55
  6. data/architecture.md +120 -0
  7. data/examples/basic_usage.rb +1 -1
  8. data/examples/configurations.rb +78 -0
  9. data/examples/futures.rb +1 -1
  10. data/examples/ring.rb +5 -4
  11. data/examples/simple_pmap.rb +1 -1
  12. data/examples/stack.rb +2 -2
  13. data/examples/supervisors_and_registry.rb +82 -0
  14. data/examples/timers.rb +1 -1
  15. data/lib/celluloid.rb +72 -47
  16. data/lib/celluloid/actor.rb +27 -17
  17. data/lib/celluloid/actor/system.rb +13 -29
  18. data/lib/celluloid/autostart.rb +5 -5
  19. data/lib/celluloid/backported.rb +6 -2
  20. data/lib/celluloid/call/async.rb +2 -0
  21. data/lib/celluloid/call/sync.rb +10 -3
  22. data/lib/celluloid/calls.rb +5 -12
  23. data/lib/celluloid/cell.rb +5 -9
  24. data/lib/celluloid/condition.rb +3 -3
  25. data/lib/celluloid/core_ext.rb +0 -2
  26. data/lib/celluloid/current.rb +3 -1
  27. data/lib/celluloid/debug.rb +3 -0
  28. data/lib/celluloid/exceptions.rb +2 -2
  29. data/lib/celluloid/future.rb +7 -9
  30. data/lib/celluloid/group.rb +12 -8
  31. data/lib/celluloid/group/pool.rb +1 -3
  32. data/lib/celluloid/group/spawner.rb +2 -6
  33. data/lib/celluloid/internals/call_chain.rb +15 -0
  34. data/lib/celluloid/internals/cpu_counter.rb +62 -0
  35. data/lib/celluloid/internals/handlers.rb +42 -0
  36. data/lib/celluloid/internals/links.rb +38 -0
  37. data/lib/celluloid/internals/logger.rb +104 -0
  38. data/lib/celluloid/internals/method.rb +34 -0
  39. data/lib/celluloid/internals/properties.rb +32 -0
  40. data/lib/celluloid/internals/receivers.rb +64 -0
  41. data/lib/celluloid/internals/registry.rb +102 -0
  42. data/lib/celluloid/internals/responses.rb +46 -0
  43. data/lib/celluloid/internals/signals.rb +24 -0
  44. data/lib/celluloid/internals/stack.rb +74 -0
  45. data/lib/celluloid/internals/stack/dump.rb +12 -0
  46. data/lib/celluloid/internals/stack/states.rb +72 -0
  47. data/lib/celluloid/internals/stack/summary.rb +12 -0
  48. data/lib/celluloid/internals/task_set.rb +51 -0
  49. data/lib/celluloid/internals/thread_handle.rb +52 -0
  50. data/lib/celluloid/internals/uuid.rb +40 -0
  51. data/lib/celluloid/logging/incident.rb +21 -0
  52. data/lib/celluloid/logging/incident_logger.rb +147 -0
  53. data/lib/celluloid/logging/incident_reporter.rb +49 -0
  54. data/lib/celluloid/logging/log_event.rb +20 -0
  55. data/lib/celluloid/logging/ring_buffer.rb +64 -0
  56. data/lib/celluloid/mailbox.rb +22 -9
  57. data/lib/celluloid/mailbox/evented.rb +13 -5
  58. data/lib/celluloid/managed.rb +6 -3
  59. data/lib/celluloid/notifications.rb +95 -0
  60. data/lib/celluloid/pool.rb +6 -0
  61. data/lib/celluloid/probe.rb +81 -0
  62. data/lib/celluloid/proxy/abstract.rb +9 -9
  63. data/lib/celluloid/proxy/async.rb +1 -1
  64. data/lib/celluloid/proxy/block.rb +2 -2
  65. data/lib/celluloid/proxy/cell.rb +1 -1
  66. data/lib/celluloid/proxy/future.rb +2 -4
  67. data/lib/celluloid/proxy/sync.rb +1 -3
  68. data/lib/celluloid/rspec.rb +22 -33
  69. data/lib/celluloid/supervision.rb +17 -0
  70. data/lib/celluloid/supervision/configuration.rb +169 -0
  71. data/lib/celluloid/supervision/configuration/injections.rb +8 -0
  72. data/lib/celluloid/supervision/configuration/instance.rb +113 -0
  73. data/lib/celluloid/supervision/constants.rb +123 -0
  74. data/lib/celluloid/supervision/container.rb +144 -0
  75. data/lib/celluloid/supervision/container/behavior.rb +89 -0
  76. data/lib/celluloid/supervision/container/behavior/pool.rb +71 -0
  77. data/lib/celluloid/supervision/container/behavior/tree.rb +23 -0
  78. data/lib/celluloid/supervision/container/injections.rb +8 -0
  79. data/lib/celluloid/supervision/container/instance.rb +116 -0
  80. data/lib/celluloid/supervision/container/pool.rb +210 -0
  81. data/{culture/rubocop/perf.yml → lib/celluloid/supervision/container/tree.rb} +0 -0
  82. data/lib/celluloid/supervision/deprecate.rb +9 -0
  83. data/lib/celluloid/supervision/deprecate/supervise.rb +105 -0
  84. data/lib/celluloid/supervision/deprecate/validation.rb +54 -0
  85. data/lib/celluloid/supervision/service.rb +27 -0
  86. data/lib/celluloid/supervision/supervise.rb +34 -0
  87. data/lib/celluloid/supervision/validation.rb +40 -0
  88. data/lib/celluloid/supervision/version.rb +5 -0
  89. data/lib/celluloid/system_events.rb +11 -6
  90. data/lib/celluloid/task.rb +25 -12
  91. data/lib/celluloid/task/fibered.rb +2 -0
  92. data/lib/celluloid/task/threaded.rb +3 -3
  93. data/lib/celluloid/test.rb +5 -2
  94. data/lib/celluloid/thread.rb +0 -2
  95. data/lib/celluloid/version.rb +1 -1
  96. data/spec/celluloid/block_spec.rb +29 -32
  97. data/spec/celluloid/calls_spec.rb +5 -15
  98. data/spec/celluloid/future_spec.rb +2 -2
  99. data/spec/celluloid/internals/cpu_counter_spec.rb +129 -0
  100. data/spec/celluloid/internals/links_spec.rb +43 -0
  101. data/spec/celluloid/internals/properties_spec.rb +40 -0
  102. data/spec/celluloid/internals/registry_spec.rb +62 -0
  103. data/spec/celluloid/internals/stack/dump_spec.rb +4 -0
  104. data/spec/celluloid/internals/stack/summary_spec.rb +4 -0
  105. data/spec/celluloid/internals/thread_handle_spec.rb +60 -0
  106. data/spec/celluloid/internals/uuid_spec.rb +9 -0
  107. data/spec/celluloid/logging/ring_buffer_spec.rb +36 -0
  108. data/spec/celluloid/mailbox/evented_spec.rb +11 -22
  109. data/spec/celluloid/misc/leak_spec.rb +3 -4
  110. data/spec/celluloid/notifications_spec.rb +140 -0
  111. data/spec/celluloid/probe_spec.rb +102 -0
  112. data/spec/celluloid/proxy_spec.rb +30 -30
  113. data/spec/celluloid/supervision/behavior_spec.rb +74 -0
  114. data/spec/celluloid/supervision/configuration_spec.rb +181 -0
  115. data/spec/celluloid/supervision/container_spec.rb +72 -0
  116. data/spec/celluloid/supervision/instance_spec.rb +13 -0
  117. data/spec/celluloid/supervision/root_spec.rb +28 -0
  118. data/spec/celluloid/supervision/supervisor_spec.rb +93 -0
  119. data/spec/celluloid/task/fibered_spec.rb +1 -3
  120. data/spec/celluloid/task/threaded_spec.rb +1 -3
  121. data/spec/shared/actor_examples.rb +58 -33
  122. data/spec/shared/group_examples.rb +2 -2
  123. data/spec/shared/mailbox_examples.rb +1 -1
  124. data/spec/shared/stack_examples.rb +87 -0
  125. data/spec/shared/task_examples.rb +2 -3
  126. data/spec/spec_helper.rb +2 -4
  127. data/spec/support/configure_rspec.rb +2 -3
  128. data/spec/support/coverage.rb +2 -4
  129. data/spec/support/crash_checking.rb +2 -2
  130. data/spec/support/examples/actor_class.rb +3 -8
  131. data/spec/support/examples/call_class.rb +2 -2
  132. data/spec/support/examples/container_class.rb +35 -0
  133. data/spec/support/examples/evented_mailbox_class.rb +1 -2
  134. data/spec/support/examples/stack_classes.rb +58 -0
  135. data/spec/support/examples/stack_methods.rb +23 -0
  136. data/spec/support/examples/subordinate_class.rb +19 -0
  137. data/spec/support/logging.rb +2 -34
  138. data/spec/support/loose_threads.rb +3 -16
  139. data/spec/support/reset_class_variables.rb +5 -1
  140. data/spec/support/stubbing.rb +1 -1
  141. metadata +91 -316
  142. data/culture/CONDUCT.md +0 -38
  143. data/culture/GSoC/1010-why_we_will_participate.md +0 -17
  144. data/culture/GSoC/1020-how_mentors_stay_engaged.md +0 -7
  145. data/culture/GSoC/1030-keeping_students_on_schedule.md +0 -9
  146. data/culture/GSoC/1040-getting_students_involved.md +0 -5
  147. data/culture/GSoC/1050-student_involvement_after.md +0 -5
  148. data/culture/GSoC/README.md +0 -16
  149. data/culture/Gemfile +0 -9
  150. data/culture/LICENSE.txt +0 -22
  151. data/culture/README.md +0 -22
  152. data/culture/Rakefile +0 -5
  153. data/culture/SYNC.md +0 -70
  154. data/culture/celluloid-culture.gemspec +0 -18
  155. data/culture/gems/README.md +0 -39
  156. data/culture/gems/dependencies.yml +0 -93
  157. data/culture/gems/loader.rb +0 -101
  158. data/culture/rubocop/README.md +0 -38
  159. data/culture/rubocop/lint.yml +0 -8
  160. data/culture/rubocop/metrics.yml +0 -15
  161. data/culture/rubocop/rubocop.yml +0 -5
  162. data/culture/rubocop/style.yml +0 -61
  163. data/culture/spec/gems_spec.rb +0 -2
  164. data/culture/spec/spec_helper.rb +0 -0
  165. data/culture/spec/sync_spec.rb +0 -2
  166. data/culture/sync.rb +0 -56
  167. data/culture/tasks/rspec.rake +0 -5
  168. data/culture/tasks/rubocop.rake +0 -2
  169. data/lib/celluloid/actor/manager.rb +0 -7
  170. data/lib/celluloid/deprecate.rb +0 -34
  171. data/lib/celluloid/fiber.rb +0 -32
  172. data/lib/celluloid/notices.rb +0 -15
  173. data/spec/deprecate/actor_system_spec.rb +0 -72
  174. data/spec/deprecate/block_spec.rb +0 -52
  175. data/spec/deprecate/calls_spec.rb +0 -39
  176. data/spec/deprecate/evented_mailbox_spec.rb +0 -34
  177. data/spec/deprecate/future_spec.rb +0 -32
  178. data/spec/deprecate/internal_pool_spec.rb +0 -4
  179. data/spec/support/env.rb +0 -21
@@ -0,0 +1,8 @@
1
+ module Celluloid
2
+ module Supervision
3
+ class Configuration
4
+ class Injection
5
+ end
6
+ end
7
+ end
8
+ end
@@ -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