celluloid-supervision 0.20.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d758087a7c87232e429ecab55a0a1361cb3cca75
4
+ data.tar.gz: 7a2a877f7c9fb2d91de1e469b6464ff4db8c2a27
5
+ SHA512:
6
+ metadata.gz: a4e2a0fed81099cc2ec77bf10f42b137f1c3befaa50d5506d08044b5ab865232060d4bfb84455350cde1ae641fef9d1e936d1929fb3b2a3a0d2a3cbde60cc29a
7
+ data.tar.gz: afd6c4dc05c56e4ac9cf5d1968d848d6d39d334c415062594f62be54a84416f82b5df458213ea701c369d5418e26bab3abdc2c3980308110876f919393c684cb
data/.coveralls.yml ADDED
File without changes
data/.env-ci ADDED
@@ -0,0 +1,4 @@
1
+ CELLULOID_SPECS_LOG_STRATEGY=stderr
2
+ CELLULOID_SPECS_LOG_LEVEL=3
3
+ CELLULOID_SPECS_LOG_FILE=../../log/ci.log
4
+ CELLULOID_SPECS_LOG_SYNC=false
data/.env-dev ADDED
@@ -0,0 +1,4 @@
1
+ CELLULOID_SPECS_LOG_STRATEGY=single
2
+ CELLULOID_SPECS_LOG_FILE=../../log/test.log
3
+ CELLULOID_SPECS_LOG_LEVEL=0
4
+ CELLULOID_SPECS_LOG_SYNC=true
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ coverage/
2
+ rdoc/
3
+ doc/
4
+ pkg/
5
+ tmp/
6
+ .yardoc
7
+ .bundle
8
+ Gemfile.lock
9
+ log
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "culture"]
2
+ path = culture
3
+ url = http://github.com/celluloid/culture.git
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --color
2
+ --format documentation
3
+ --order random
4
+ --warnings
5
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ inherit_from:
2
+ - culture/rubocop/rubocop.yml
data/.travis.yml ADDED
@@ -0,0 +1,28 @@
1
+ script: rake ci
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.0
5
+ - 2.2.2
6
+ - jruby
7
+ - ruby-head
8
+ - jruby-head
9
+ - rbx-2
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: rbx-2
14
+ - rvm: ruby-head
15
+ - rvm: jruby-head
16
+ - env: CELLULOID_TASK_CLASS=Threaded
17
+
18
+ env:
19
+ matrix:
20
+ - CELLULOID_TASK_CLASS=Fibered
21
+ - CELLULOID_TASK_CLASS=Threaded
22
+ - CELLULOID_BACKPORTED=false
23
+
24
+ notifications:
25
+ irc: "irc.freenode.org#celluloid"
26
+
27
+ sudo: false
28
+ install: bundle install --retry=3 --without=development
data/CHANGES.md ADDED
File without changes
data/CONDUCT.md ADDED
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,31 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "coveralls", require: false
4
+
5
+ gemspec development_group: :gem_build_tools
6
+
7
+ group :development do
8
+ gem "pry"
9
+ # de gem 'guard'
10
+ # de gem 'guard-rspec'
11
+ # de gem 'rb-fsevent', '~> 0.9.1' if RUBY_PLATFORM =~ /darwin/
12
+ gem "rubocop"
13
+ end
14
+
15
+ group :test do
16
+ gem "dotenv", "~> 2.0"
17
+ gem "nenv"
18
+ gem "benchmark_suite"
19
+ gem "rspec", "~> 3.2"
20
+ gem "rspec-retry"
21
+ gem "rspec-log_split", github: "abstractive/rspec-log_split", branch: "master"
22
+ end
23
+
24
+ group :gem_build_tools do
25
+ gem "rake"
26
+ end
27
+
28
+ gem 'celluloid-essentials', github: 'celluloid/celluloid-essentials', branch: 'master'
29
+ gem 'celluloid-gems', github: 'celluloid/celluloid-gems', branch: 'master'
30
+
31
+ gem 'celluloid', github: 'celluloid/celluloid', branch: '0.17.0-prerelease'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Celluloid
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1 @@
1
+ Supervisors, Supervision Groups, and Supervision Trees for Celluloid.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir["tasks/**/*.rake"].each { |task| load task }
4
+
5
+ default_tasks = ["spec"]
6
+ default_tasks << "rubocop" unless ENV["CI"]
7
+ task default: default_tasks
8
+
9
+ task ci: %w(spec benchmark)
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/celluloid/supervision/version", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "celluloid-supervision"
6
+ gem.version = Celluloid::Supervision::VERSION
7
+ gem.platform = Gem::Platform::RUBY
8
+ gem.summary = "Celluloid Supervision"
9
+ gem.description = "Supervisors, Supervision Groups, and Supervision Trees for Celluloid."
10
+ gem.licenses = ["MIT"]
11
+
12
+ gem.authors = ["digitalextremist //", "Tony Arcieri", "Tim Carey-Smith"]
13
+ gem.email = ["code@extremist.digital", "tony.arcieri@gmail.com"]
14
+ gem.homepage = "https://github.com/celluloid/"
15
+
16
+ gem.required_ruby_version = ">= 1.9.2"
17
+ gem.required_rubygems_version = ">= 1.3.6"
18
+
19
+ gem.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|examples|spec|features)/}) }
20
+ gem.require_path = "lib"
21
+
22
+ gem.add_development_dependency "bundler"
23
+ gem.add_dependency "celluloid"
24
+ gem.add_dependency "celluloid-gems"
25
+ gem.add_dependency "celluloid-essentials"
26
+
27
+ end
@@ -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.select { |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
+ fail 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
+ fail 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_method :[]=, :set
95
+
96
+ def get(key)
97
+ @configuration[key]
98
+ end
99
+ alias_method :[], :get
100
+
101
+ def delete(k)
102
+ current_instance.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,205 @@
1
+ module Celluloid
2
+ module Supervision
3
+ class Configuration
4
+ class << self
5
+ def deploy(options={})
6
+ define(options).deploy
7
+ end
8
+
9
+ def define(options={})
10
+ new(options)
11
+ end
12
+
13
+ def valid?(configuration, fail=false)
14
+ parameters(:mandatory).each do |k|
15
+ unless configuration.key? k
16
+ if fail
17
+ fail Error::Incomplete, "Missing `:#{k}` in supervision configuration."
18
+ else
19
+ return false
20
+ end
21
+ end
22
+ end
23
+ arity.each do |klass, args|
24
+ unless configuration[args].is_a? Proc
25
+ __a = configuration[args] && configuration[args].count || 0
26
+ __arity = configuration[klass].allocate.method(:initialize).arity
27
+ unless __arity == -1 || __a == __arity
28
+ if fail
29
+ fail ArgumentError.new("#{__a} vs. #{__arity}")
30
+ else
31
+ return false
32
+ end
33
+ end
34
+ end
35
+ end
36
+ true
37
+ end
38
+
39
+ def options(args, options={})
40
+ configuration = args.merge(options)
41
+ return configuration if configuration.is_a? Configuration
42
+ configuration[:initialize] = Container::Behavior.configure(configuration)
43
+ valid?(configuration, true)
44
+ configuration
45
+ end
46
+ end
47
+
48
+ extend Forwardable
49
+
50
+ def_delegators :current_instance,
51
+ :delete,
52
+ :key?,
53
+ :set,
54
+ :get,
55
+ :[],
56
+ :[]=,
57
+ :injection!,
58
+ :injections!
59
+
60
+ attr_accessor :instances
61
+
62
+ def initialize(options={})
63
+ @instances = [Instance.new]
64
+ @branch = :services
65
+ @i = 0 # incrementer of instances in this branch
66
+ resync_accessors
67
+ @configuration = options
68
+ @supervisor ||= :"Celluloid.services"
69
+
70
+ if options.is_a? Hash
71
+ options[:initialize] ||= Container::Behavior.configure(options)
72
+ @configuration = instance_eval(&options[:initialize])
73
+ @supervisor ||= @configuration.fetch(:supervisor, :"Celluloid.services")
74
+ end
75
+
76
+ if (@configuration.is_a?(Hash) || @configuration.is_a?(Array)) && @configuration.any?
77
+ define(@configuration)
78
+ end
79
+ end
80
+
81
+ def provider
82
+ @provider ||= if @supervisor.is_a? Hash
83
+ @supervisor[:type].run!(as: @supervisor[:as])
84
+ elsif @supervisor.is_a? Symbol
85
+ @supervisor = Object.module_eval(@supervisor.to_s)
86
+ provider
87
+ elsif @supervisor.is_a? Class
88
+ @supervisor.run!
89
+ elsif @supervisor.respond_to? :supervise
90
+ @supervisor
91
+ else
92
+ fail Error::InvalidSupervisor
93
+ end
94
+ end
95
+
96
+ def deploy(options={})
97
+ define(options) if options.any?
98
+ @instances.each do |instance|
99
+ provider.supervise instance.merge(branch: @branch)
100
+ end
101
+ provider
102
+ end
103
+
104
+ def count
105
+ @instances.count
106
+ end
107
+
108
+ def each(&block)
109
+ @instances.each(&block)
110
+ end
111
+
112
+ def resync_accessors
113
+ # methods for setting and getting the usual defaults
114
+ Configuration.parameters(:mandatory, :optional, :plugins, :meta).each do |key|
115
+ [:"#{key}!", :"#{key}="].each do |m|
116
+ self.class.instance_eval do
117
+ remove_method :"#{m}" rescue nil # avoid warnings in tests
118
+ define_method(m) { |p| current_instance.send(m, p) }
119
+ end
120
+ end
121
+ [:"#{key}?", :"#{key}"].each do |m|
122
+ self.class.instance_eval do
123
+ remove_method :"#{m}" rescue nil # avoid warnings in tests
124
+ define_method(m) { current_instance.send(m) }
125
+ end
126
+ end
127
+ end
128
+
129
+ Configuration.aliases.each do |_alias, _original|
130
+ ["!", :"=", :"?", :""]. each do |m|
131
+ self.class.instance_eval do
132
+ remove_method :"#{_alias}#{m}" rescue nil # avoid warnings in tests
133
+ alias_method :"#{_alias}#{m}", :"#{_original}#{m}"
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ def merge!(values)
140
+ if values.is_a?(Configuration) || values.is_a?(Hash)
141
+ current_instance.merge!(values)
142
+ else
143
+ fail Error::Invalid
144
+ end
145
+ end
146
+
147
+ def merge(values)
148
+ if values.is_a?(Configuration) || values.is_a?(Hash)
149
+ current_instance.merge(values)
150
+ else
151
+ fail Error::Invalid
152
+ end
153
+ end
154
+
155
+ def export
156
+ return current_instance.to_hash if @i == 0
157
+ @instances.map(&:export)
158
+ end
159
+
160
+ def include?(name)
161
+ @instances.map(&:name).include? name
162
+ end
163
+
164
+ def define(configuration, fail=false)
165
+ if configuration.is_a? Array
166
+ configuration.each { |c| define(c, fail) }
167
+ else
168
+ unless include? configuration[:as]
169
+ begin
170
+ current_instance.define(configuration, fail)
171
+ rescue Error::AlreadyDefined
172
+ increment
173
+ retry
174
+ end
175
+ end
176
+ end
177
+ self
178
+ end
179
+
180
+ def increment
181
+ @i += 1
182
+ end
183
+ alias_method :another, :increment
184
+
185
+ def add(options)
186
+ define(options)
187
+ provider.supervise options if Configuration.valid? options
188
+ end
189
+
190
+ def shutdown
191
+ @provider.shutdown
192
+ end
193
+
194
+ private
195
+
196
+ def current_instance
197
+ @instances[@i] ||= Instance.new
198
+ end
199
+
200
+ def invoke_injection(_point)
201
+ # de puts "injection? #{point}"
202
+ end
203
+ end
204
+ end
205
+ 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 < StandardError; end
9
+ end
10
+
11
+ class Configuration
12
+ module Error
13
+ class AlreadyDefined < StandardError; end
14
+ class InvalidSupervisor < StandardError; end
15
+ class InvalidValues < StandardError; end
16
+ class Incomplete < StandardError; end
17
+ class Invalid < StandardError; 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: [
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: [
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.inject({}) { |p, (k, v)| p[k] = v.dup; p },
63
+ aliases: @@aliases.dup,
64
+ arity: @@arity.dup,
65
+ }
66
+ end
67
+
68
+ def resync_parameters
69
+ @@parameters = @@defaults[:parameters].inject({}) { |p, (k, v)| p[k] = v.dup; p }
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(*_args)
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 = [
110
+ :initialize,
111
+ :behavior,
112
+ ]
113
+
114
+ INJECTIONS = [
115
+ :configuration,
116
+ :before_initialization,
117
+ :after_initialization,
118
+ :before_start,
119
+ :before_restart,
120
+ ]
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,29 @@
1
+ module Celluloid
2
+ module Supervision
3
+ class Container
4
+ # class << self
5
+ # def tree(actors=[], *args, &block)
6
+ # blocks << lambda do |container|
7
+ # container.tree(Configuration.options(args, :supervise => actors, :block => block ))
8
+ # end
9
+ # end
10
+ # end
11
+
12
+ class Tree
13
+ include Behavior
14
+
15
+ identifier! :supervises, :supervise
16
+
17
+ configuration do
18
+ if @configuration[:supervise].is_a? Array
19
+ @supervisor = @configuration.dup
20
+ @branch = @configuration.fetch(:branch, @configuration[:as])
21
+ @configuration.delete(Behavior.parameter(:supervise, @configuration))
22
+ else
23
+ fail ArgumentError.new("No actors given to Tree to supervise.")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end