sanford 0.1.0 → 0.2.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.
- data/bench/report.txt +34 -4
- data/bench/runner.rb +122 -1
- data/bench/services.rb +5 -2
- data/lib/sanford/error_handler.rb +60 -0
- data/lib/sanford/exceptions.rb +11 -10
- data/lib/sanford/host.rb +79 -101
- data/lib/sanford/host_data.rb +55 -0
- data/lib/sanford/logger.rb +23 -0
- data/lib/sanford/manager.rb +13 -22
- data/lib/sanford/rake.rb +1 -0
- data/lib/sanford/runner.rb +50 -0
- data/lib/sanford/server.rb +31 -15
- data/lib/sanford/service_handler.rb +34 -43
- data/lib/sanford/test_runner.rb +47 -0
- data/lib/sanford/version.rb +1 -1
- data/lib/sanford/worker.rb +124 -0
- data/lib/sanford.rb +49 -6
- data/sanford.gemspec +1 -1
- data/test/helper.rb +1 -0
- data/test/support/fake_connection.rb +18 -0
- data/test/support/helpers.rb +6 -10
- data/test/support/service_handlers.rb +56 -68
- data/test/support/services.rb +55 -10
- data/test/system/managing_test.rb +18 -18
- data/test/system/request_handling_test.rb +10 -100
- data/test/unit/config_test.rb +1 -43
- data/test/unit/error_handler_test.rb +133 -0
- data/test/unit/host_configuration_test.rb +41 -0
- data/test/unit/host_data_test.rb +65 -0
- data/test/unit/host_test.rb +20 -112
- data/test/unit/{host/version_group_test.rb → host_version_group_test.rb} +0 -0
- data/test/unit/hosts_test.rb +56 -0
- data/test/unit/manager_test.rb +3 -3
- data/test/unit/runner_test.rb +26 -0
- data/test/unit/server_test.rb +10 -2
- data/test/unit/service_handler_test.rb +126 -115
- data/test/unit/worker_test.rb +195 -0
- metadata +28 -16
- data/lib/sanford/config.rb +0 -33
- data/lib/sanford/connection.rb +0 -70
- data/lib/sanford/exception_handler.rb +0 -43
- data/test/unit/connection_test.rb +0 -23
- data/test/unit/exception_handler_test.rb +0 -69
data/bench/report.txt
CHANGED
@@ -2,9 +2,39 @@ Running benchmark report...
|
|
2
2
|
|
3
3
|
Hitting "simple" service with {}, 10000 times
|
4
4
|
....................................................................................................
|
5
|
-
Total Time:
|
6
|
-
Average Time: 1.
|
7
|
-
Min Time: 0.
|
8
|
-
Max Time:
|
5
|
+
Total Time: 10195.4432ms
|
6
|
+
Average Time: 1.0195ms
|
7
|
+
Min Time: 0.7040ms
|
8
|
+
Max Time: 117.8309ms
|
9
|
+
|
10
|
+
Distribution (number of requests):
|
11
|
+
0ms: 8897
|
12
|
+
0.7ms: 6897
|
13
|
+
0.8ms: 1451
|
14
|
+
0.9ms: 549
|
15
|
+
1ms: 1049
|
16
|
+
1.0ms: 308
|
17
|
+
1.1ms: 236
|
18
|
+
1.2ms: 198
|
19
|
+
1.3ms: 134
|
20
|
+
1.4ms: 66
|
21
|
+
1.5ms: 44
|
22
|
+
1.6ms: 26
|
23
|
+
1.7ms: 18
|
24
|
+
1.8ms: 15
|
25
|
+
1.9ms: 4
|
26
|
+
117ms: 1
|
27
|
+
2ms: 24
|
28
|
+
3ms: 7
|
29
|
+
4ms: 2
|
30
|
+
82ms: 1
|
31
|
+
83ms: 1
|
32
|
+
84ms: 3
|
33
|
+
85ms: 2
|
34
|
+
86ms: 2
|
35
|
+
88ms: 3
|
36
|
+
89ms: 4
|
37
|
+
90ms: 2
|
38
|
+
91ms: 2
|
9
39
|
|
10
40
|
Done running benchmark report
|
data/bench/runner.rb
CHANGED
@@ -43,10 +43,11 @@ module Bench
|
|
43
43
|
output("\n", false)
|
44
44
|
|
45
45
|
total_time = benchmarks.inject(0){|s, n| s + n }
|
46
|
+
average = total_time / benchmarks.size
|
46
47
|
data = {
|
47
48
|
:number_of_requests => times,
|
48
49
|
:total_time_taken => self.round_and_display(total_time),
|
49
|
-
:average_time_taken => self.round_and_display(
|
50
|
+
:average_time_taken => self.round_and_display(average),
|
50
51
|
:min_time_taken => self.round_and_display(benchmarks.min),
|
51
52
|
:max_time_taken => self.round_and_display(benchmarks.max)
|
52
53
|
}
|
@@ -55,6 +56,19 @@ module Bench
|
|
55
56
|
output "Average Time: #{data[:average_time_taken].rjust(size)}ms"
|
56
57
|
output "Min Time: #{data[:min_time_taken].rjust(size)}ms"
|
57
58
|
output "Max Time: #{data[:max_time_taken].rjust(size)}ms"
|
59
|
+
|
60
|
+
output "\n"
|
61
|
+
|
62
|
+
distribution = Distribution.new(benchmarks)
|
63
|
+
|
64
|
+
output "Distribution (number of requests):"
|
65
|
+
distribution.each do |grouping|
|
66
|
+
output " #{grouping.time}ms: #{grouping.number_of_requests}"
|
67
|
+
grouping.precise_groupings.each do |precise_grouping|
|
68
|
+
output " #{precise_grouping.time}ms: #{precise_grouping.number_of_requests}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
58
72
|
output "\n"
|
59
73
|
end
|
60
74
|
|
@@ -97,6 +111,113 @@ module Bench
|
|
97
111
|
[ integer, fractional.ljust(4, '0') ].join('.')
|
98
112
|
end
|
99
113
|
|
114
|
+
class Distribution
|
115
|
+
|
116
|
+
def initialize(benchmarks)
|
117
|
+
hash = benchmarks.inject({}) do |hash, benchmark|
|
118
|
+
index = Index.new(benchmark).number
|
119
|
+
hash[index] ||= Grouping.new(index)
|
120
|
+
hash[index].add(benchmark)
|
121
|
+
hash
|
122
|
+
end
|
123
|
+
@groupings = hash.values.sort
|
124
|
+
end
|
125
|
+
|
126
|
+
def each(&block)
|
127
|
+
@groupings.each(&block)
|
128
|
+
end
|
129
|
+
|
130
|
+
class BaseGrouping
|
131
|
+
|
132
|
+
def self.max_time(time = nil)
|
133
|
+
size = time.to_s.size
|
134
|
+
@max_time = size if size > @max_time.to_i
|
135
|
+
@max_time
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.max_number(number = nil)
|
139
|
+
size = number.to_s.size
|
140
|
+
@max_size = size if size > @max_size.to_i
|
141
|
+
@max_size
|
142
|
+
end
|
143
|
+
|
144
|
+
attr_reader :name
|
145
|
+
|
146
|
+
def initialize(index)
|
147
|
+
@name = index.to_s
|
148
|
+
@set = []
|
149
|
+
self.class.max_time(index.to_s.size)
|
150
|
+
end
|
151
|
+
|
152
|
+
def add(benchmark)
|
153
|
+
result = @set.push(benchmark)
|
154
|
+
self.class.max_number(@set.size.to_s.size)
|
155
|
+
result
|
156
|
+
end
|
157
|
+
|
158
|
+
def time
|
159
|
+
@name.rjust(self.class.max_time)
|
160
|
+
end
|
161
|
+
|
162
|
+
def number_of_requests
|
163
|
+
@set.size.to_s.rjust(self.class.max_number)
|
164
|
+
end
|
165
|
+
|
166
|
+
def <=>(other)
|
167
|
+
self.name.to_f <=> other.name.to_f
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
class Grouping < BaseGrouping
|
173
|
+
|
174
|
+
def initialize(index)
|
175
|
+
super
|
176
|
+
@precise_groupings = {}
|
177
|
+
end
|
178
|
+
|
179
|
+
def add(benchmark)
|
180
|
+
add_precise_grouping(benchmark) if self.collect_precise?
|
181
|
+
super(benchmark)
|
182
|
+
end
|
183
|
+
|
184
|
+
def collect_precise?
|
185
|
+
@name.to_i <= 1
|
186
|
+
end
|
187
|
+
|
188
|
+
def precise_groupings
|
189
|
+
@precise_groupings.values.sort
|
190
|
+
end
|
191
|
+
|
192
|
+
protected
|
193
|
+
|
194
|
+
def add_precise_grouping(benchmark)
|
195
|
+
index = PreciseIndex.new(benchmark).number
|
196
|
+
@precise_groupings[index] ||= BaseGrouping.new(index)
|
197
|
+
@precise_groupings[index].add(benchmark)
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
class Index < Struct.new(:number)
|
203
|
+
|
204
|
+
def initialize(benchmark)
|
205
|
+
super benchmark.to_i
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class PreciseIndex < Struct.new(:number)
|
210
|
+
|
211
|
+
MODIFIER = 10.to_f
|
212
|
+
|
213
|
+
def initialize(benchmark)
|
214
|
+
super((benchmark * MODIFIER).to_i / MODIFIER)
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
100
221
|
end
|
101
222
|
|
102
223
|
end
|
data/bench/services.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
class BenchHost
|
2
2
|
include Sanford::Host
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
port 12000
|
5
|
+
pid_dir File.expand_path("../../tmp", __FILE__)
|
6
|
+
|
7
|
+
logger Logger.new(STDOUT)
|
8
|
+
verbose_logging false
|
6
9
|
|
7
10
|
version 'v1' do
|
8
11
|
service 'simple', 'BenchHost::Simple'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'sanford-protocol'
|
3
|
+
|
4
|
+
module Sanford
|
5
|
+
|
6
|
+
class ErrorHandler
|
7
|
+
|
8
|
+
attr_reader :exception, :host_data, :request
|
9
|
+
|
10
|
+
def initialize(exception, host_data, request = nil)
|
11
|
+
@exception, @host_data, @request = exception, host_data, request
|
12
|
+
end
|
13
|
+
|
14
|
+
# The exception that we are generating a response for can change in the case
|
15
|
+
# that the configured error proc raises an exception. If this occurs, a
|
16
|
+
# response will be generated for that exception, instead of the original
|
17
|
+
# one. This is designed to avoid "hidden" errors happening, this way the
|
18
|
+
# server will respond and log based on the last exception that occurred.
|
19
|
+
|
20
|
+
def run
|
21
|
+
begin
|
22
|
+
result = @host_data.error_proc.call(@exception, @host_data, @request)
|
23
|
+
rescue Exception => proc_exception
|
24
|
+
@exception = proc_exception
|
25
|
+
end
|
26
|
+
self.response_from_proc(result) || self.response_from_exception(@exception)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def response_from_proc(result)
|
32
|
+
case result
|
33
|
+
when Sanford::Protocol::Response
|
34
|
+
result
|
35
|
+
when Integer, Symbol
|
36
|
+
build_response result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def response_from_exception(exception)
|
41
|
+
case(exception)
|
42
|
+
when Sanford::Protocol::BadMessageError, Sanford::Protocol::BadRequestError
|
43
|
+
build_response :bad_request, :message => exception.message
|
44
|
+
when Sanford::NotFoundError
|
45
|
+
build_response :not_found
|
46
|
+
when Sanford::Protocol::TimeoutError
|
47
|
+
build_response :timeout
|
48
|
+
when Exception
|
49
|
+
build_response :error, :message => "An unexpected error occurred."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_response(status, options = nil)
|
54
|
+
options = OpenStruct.new(options || {})
|
55
|
+
Sanford::Protocol::Response.new([ status, options.message ], options.data)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/lib/sanford/exceptions.rb
CHANGED
@@ -1,37 +1,38 @@
|
|
1
1
|
module Sanford
|
2
2
|
|
3
|
-
|
3
|
+
BaseError = Class.new(RuntimeError)
|
4
4
|
|
5
|
-
|
5
|
+
NotFoundError = Class.new(RuntimeError)
|
6
6
|
|
7
7
|
class NoHostError < BaseError
|
8
8
|
attr_reader :message
|
9
9
|
|
10
10
|
def initialize(host_name)
|
11
|
-
|
12
|
-
"No hosts have been defined. "
|
13
|
-
"Please define a host before trying to run Sanford."
|
11
|
+
message = if Sanford.hosts.empty?
|
12
|
+
"No hosts have been defined. Please define a host before trying to run Sanford."
|
14
13
|
else
|
15
14
|
"A host couldn't be found with the name #{host_name.inspect}. "
|
16
15
|
end
|
16
|
+
super message
|
17
17
|
end
|
18
|
+
|
18
19
|
end
|
19
20
|
|
20
21
|
class InvalidHostError < BaseError
|
21
|
-
attr_reader :message
|
22
22
|
|
23
23
|
def initialize(host)
|
24
|
-
|
24
|
+
super "A port must be configured or provided to run a server for '#{host}'"
|
25
25
|
end
|
26
|
+
|
26
27
|
end
|
27
28
|
|
28
29
|
class NoHandlerClassError < BaseError
|
29
|
-
attr_reader :message
|
30
30
|
|
31
|
-
def initialize(
|
32
|
-
|
31
|
+
def initialize(handler_class_name)
|
32
|
+
super "Sanford couldn't find the service handler '#{handler_class_name}'. " \
|
33
33
|
"It doesn't exist or hasn't been required in yet."
|
34
34
|
end
|
35
|
+
|
35
36
|
end
|
36
37
|
|
37
38
|
end
|
data/lib/sanford/host.rb
CHANGED
@@ -1,136 +1,93 @@
|
|
1
|
-
# Sanford's Host mixin is used to define service hosts. When mixed into a class
|
2
|
-
# it provides the interface for configuring the service host and for adding
|
3
|
-
# versioned services. It also contains the logic for routing a request to a
|
4
|
-
# a service handler.
|
5
|
-
#
|
6
|
-
# Options:
|
7
|
-
# * `name` - A string for naming this host. This can be used when specifying
|
8
|
-
# a host with the rake tasks and will be used to name the PID
|
9
|
-
# file. Defaults to the class's name.
|
10
|
-
# * `ip` - The string for the ip that the TCP Server should bind to. This
|
11
|
-
# defaults to '0.0.0.0'.
|
12
|
-
# * `port` - The integer for the port that the TCP Server should bind to.
|
13
|
-
# This isn't defaulted and must be provided.
|
14
|
-
# * `pid_dir` - The directory to write the PID file to. This is defaulted to
|
15
|
-
# Dir.pwd.
|
16
|
-
# * `logger` - The logger to use if the Sanford server logs messages. This is
|
17
|
-
# defaulted to an instance of Ruby's Logger.
|
18
|
-
#
|
19
|
-
require 'logger'
|
20
1
|
require 'ns-options'
|
21
2
|
require 'pathname'
|
22
3
|
|
23
|
-
require 'sanford/config'
|
24
|
-
require 'sanford/exception_handler'
|
25
4
|
require 'sanford/exceptions'
|
26
|
-
require 'sanford/
|
5
|
+
require 'sanford/logger'
|
27
6
|
|
28
7
|
module Sanford
|
8
|
+
|
29
9
|
module Host
|
30
10
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
11
|
+
class Configuration
|
12
|
+
include NsOptions::Proxy
|
13
|
+
|
14
|
+
# A Host's configuration is a seperate ns-options proxy class because
|
15
|
+
# `Host` is a module, so it itself cannot be a ns-options proxy (and
|
16
|
+
# still function as a mixin). Also, since it is making the `Host`
|
17
|
+
# a `Singleton`, mixing that with `NsOptions::Proxy` could have strange
|
18
|
+
# effects (messing up someone's `initialize`). Thus, the `Configuration`
|
19
|
+
# is a separate class and not on the `Host` directly.
|
20
|
+
|
21
|
+
option :name, String
|
22
|
+
option :ip, String, :default => '0.0.0.0'
|
23
|
+
option :port, Integer
|
24
|
+
option :pid_dir, Pathname, :default => Dir.pwd
|
25
|
+
option :logger, :default => proc{ Sanford::NullLogger.new }
|
26
|
+
option :verbose_logging, :default => true
|
27
|
+
option :error_proc, Proc, :default => proc{ }
|
28
|
+
|
29
|
+
def initialize(host)
|
30
|
+
self.name = host.class.to_s
|
50
31
|
end
|
51
|
-
Sanford.config.hosts.add(host_class)
|
52
|
-
end
|
53
32
|
|
54
|
-
INTERFACE_OPTIONS = [ :name, :ip, :port, :pid_dir, :logger, :exception_handler ]
|
55
|
-
|
56
|
-
# Notes:
|
57
|
-
# * The `initialize` takes the values configured on the class and merges
|
58
|
-
# the passed in options. This is used to set the individual instance's
|
59
|
-
# configuration (which allows overwriting options like the port).
|
60
|
-
def initialize(options = nil)
|
61
|
-
options = self.remove_nil_values(options)
|
62
|
-
config_options = self.class.config.to_hash.merge(options)
|
63
|
-
self.config.apply(config_options)
|
64
|
-
raise(Sanford::InvalidHostError.new(self.class)) if !self.port
|
65
33
|
end
|
66
34
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
35
|
+
def self.included(host_class)
|
36
|
+
host_class.class_eval do
|
37
|
+
include Singleton
|
38
|
+
extend Sanford::Host::ClassMethods
|
71
39
|
end
|
72
|
-
|
40
|
+
Sanford.register(host_class)
|
73
41
|
end
|
74
42
|
|
75
|
-
|
76
|
-
request_handler(request).run
|
77
|
-
end
|
43
|
+
attr_reader :configuration, :versioned_services
|
78
44
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
"port=#{self.config.port.inspect}>"
|
45
|
+
def initialize
|
46
|
+
@configuration = Configuration.new(self)
|
47
|
+
@versioned_services = {}
|
83
48
|
end
|
84
49
|
|
85
|
-
|
86
|
-
|
87
|
-
def request_handler(request)
|
88
|
-
handler_class(get_handler_class_name(request)).new(self.logger, request)
|
50
|
+
def name(*args)
|
51
|
+
self.configuration.name *args
|
89
52
|
end
|
90
53
|
|
91
|
-
def
|
92
|
-
self.
|
93
|
-
Sanford::ServiceHandler.constantize(class_name_str).tap do |handler_class|
|
94
|
-
raise Sanford::NoHandlerClassError.new(self, class_name_str) if !handler_class
|
95
|
-
end
|
54
|
+
def ip(*args)
|
55
|
+
self.configuration.ip *args
|
96
56
|
end
|
97
57
|
|
98
|
-
def
|
99
|
-
|
100
|
-
services[request.name].tap do |name|
|
101
|
-
raise Sanford::NotFoundError if !name
|
102
|
-
end
|
58
|
+
def port(*args)
|
59
|
+
self.configuration.port *args
|
103
60
|
end
|
104
61
|
|
105
|
-
def
|
106
|
-
|
107
|
-
hash.merge!({ k => v }) if !v.nil?
|
108
|
-
hash
|
109
|
-
end
|
62
|
+
def pid_dir(*args)
|
63
|
+
self.configuration.pid_dir *args
|
110
64
|
end
|
111
65
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
define_method(name) do |*args|
|
117
|
-
self.config.send("#{name}=", *args) if !args.empty?
|
118
|
-
self.config.send(name)
|
119
|
-
end
|
66
|
+
def logger(*args)
|
67
|
+
self.configuration.logger *args
|
68
|
+
end
|
120
69
|
|
121
|
-
|
122
|
-
|
123
|
-
|
70
|
+
def verbose_logging(*args)
|
71
|
+
self.configuration.verbose_logging *args
|
72
|
+
end
|
124
73
|
|
125
|
-
|
74
|
+
def error(&block)
|
75
|
+
self.configuration.error_proc = block
|
76
|
+
end
|
126
77
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
78
|
+
def version(name, &block)
|
79
|
+
version_group = Sanford::Host::VersionGroup.new(name, &block)
|
80
|
+
@versioned_services.merge!(version_group.to_hash)
|
81
|
+
end
|
131
82
|
|
83
|
+
def inspect
|
84
|
+
reference = '0x0%x' % (self.object_id << 1)
|
85
|
+
"#<#{self.class}:#{reference} ip=#{self.configuration.ip.inspect} " \
|
86
|
+
"port=#{self.configuration.port.inspect}>"
|
132
87
|
end
|
133
88
|
|
89
|
+
protected
|
90
|
+
|
134
91
|
class VersionGroup
|
135
92
|
attr_reader :name, :services
|
136
93
|
|
@@ -158,5 +115,26 @@ module Sanford
|
|
158
115
|
|
159
116
|
end
|
160
117
|
|
118
|
+
module ClassMethods
|
119
|
+
|
120
|
+
# the class level of a `Host` should just proxy it's methods down to it's
|
121
|
+
# instance (it's a `Singleton`)
|
122
|
+
|
123
|
+
# `name` is defined by all objects, so we can't rely on `method_missing`
|
124
|
+
def name(*args)
|
125
|
+
self.instance.name(*args)
|
126
|
+
end
|
127
|
+
|
128
|
+
def method_missing(method, *args, &block)
|
129
|
+
self.instance.send(method, *args, &block)
|
130
|
+
end
|
131
|
+
|
132
|
+
def respond_to?(method)
|
133
|
+
super || self.instance.respond_to?(method)
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
161
138
|
end
|
139
|
+
|
162
140
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'sanford/exceptions'
|
2
|
+
require 'sanford/service_handler'
|
3
|
+
|
4
|
+
module Sanford
|
5
|
+
|
6
|
+
class HostData
|
7
|
+
|
8
|
+
# When trying to run a server for a host, we need to build up the host's
|
9
|
+
# data to increase the performance of the server. This is done by
|
10
|
+
# constantizing a host's handlers and merging a host's configuration with
|
11
|
+
# optional overrides.
|
12
|
+
|
13
|
+
attr_reader :name, :ip, :port, :pid_dir, :logger, :verbose, :error_proc
|
14
|
+
|
15
|
+
def initialize(service_host, options = nil)
|
16
|
+
configuration = service_host.configuration.to_hash.merge(remove_nil_values(options || {}))
|
17
|
+
|
18
|
+
@name = configuration[:name]
|
19
|
+
@ip, @port = configuration[:ip], configuration[:port]
|
20
|
+
@pid_dir = configuration[:pid_dir]
|
21
|
+
@logger, @verbose = configuration[:logger], configuration[:verbose_logging]
|
22
|
+
@error_proc = configuration[:error_proc]
|
23
|
+
|
24
|
+
@handlers = service_host.versioned_services.inject({}) do |hash, (version, services)|
|
25
|
+
hash.merge({ version => self.constantize_services(services) })
|
26
|
+
end
|
27
|
+
|
28
|
+
raise Sanford::InvalidHostError.new(service_host) if !self.port
|
29
|
+
end
|
30
|
+
|
31
|
+
def handler_class_for(version, service)
|
32
|
+
version_group = @handlers[version] || {}
|
33
|
+
version_group[service] || raise(Sanford::NotFoundError)
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def constantize_services(services)
|
39
|
+
services.inject({}) do |hash, (name, handler_class_name)|
|
40
|
+
hash.merge({ name => self.constantize(handler_class_name) })
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def constantize(handler_class_name)
|
45
|
+
Sanford::ServiceHandler.constantize(handler_class_name) ||
|
46
|
+
raise(Sanford::NoHandlerClassError.new(handler_class_name))
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove_nil_values(hash)
|
50
|
+
hash.inject({}){|h, (k, v)| !v.nil? ? h.merge({ k => v }) : h }
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Sanford
|
2
|
+
|
3
|
+
class Logger
|
4
|
+
attr_reader :summary, :verbose
|
5
|
+
|
6
|
+
def initialize(logger, verbose = true)
|
7
|
+
loggers = [ logger, Sanford::NullLogger.new ]
|
8
|
+
loggers.reverse! if !verbose
|
9
|
+
@verbose, @summary = loggers
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class NullLogger
|
15
|
+
require 'logger'
|
16
|
+
|
17
|
+
::Logger::Severity.constants.each do |name|
|
18
|
+
define_method(name.downcase){|*args| } # no-op
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/sanford/manager.rb
CHANGED
@@ -1,44 +1,35 @@
|
|
1
|
-
# The Manager class is responsible for managing sanford's server process. Given
|
2
|
-
# a host, it can start and stop the host's server process. This is done using
|
3
|
-
# the Daemons gem and `run_proc`. The class provides a convenience method on the
|
4
|
-
# class called `call`, which will find a host, build a new manager and call the
|
5
|
-
# relevant action (this is what the rake tasks use).
|
6
|
-
#
|
7
1
|
require 'daemons'
|
8
2
|
|
9
|
-
require 'sanford/
|
10
|
-
require 'sanford/exceptions'
|
3
|
+
require 'sanford/host_data'
|
11
4
|
require 'sanford/server'
|
12
5
|
|
13
6
|
module Sanford
|
14
7
|
|
15
8
|
class Manager
|
16
|
-
attr_reader :host, :process_name
|
17
9
|
|
18
10
|
def self.call(action, options = nil)
|
19
11
|
options ||= {}
|
20
|
-
options[:host] ||= ENV['SANFORD_HOST']
|
21
12
|
options[:ip] ||= ENV['SANFORD_IP']
|
22
13
|
options[:port] ||= ENV['SANFORD_PORT']
|
23
14
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
raise(Sanford::NoHostError.new(host_class_or_name)) if !host_class
|
30
|
-
self.new(host_class, options).call(action)
|
15
|
+
name = options.delete(:host) || ENV['SANFORD_HOST']
|
16
|
+
service_host = name ? Sanford.hosts.find(name) : Sanford.hosts.first
|
17
|
+
raise(Sanford::NoHostError.new(name)) if !service_host
|
18
|
+
|
19
|
+
self.new(service_host, options).call(action)
|
31
20
|
end
|
32
21
|
|
33
|
-
|
34
|
-
|
22
|
+
attr_reader :host, :process_name
|
23
|
+
|
24
|
+
def initialize(service_host, options = {})
|
25
|
+
@host = Sanford::HostData.new(service_host, options)
|
35
26
|
@process_name = [ self.host.ip, self.host.port, self.host.name ].join('_')
|
36
27
|
end
|
37
28
|
|
38
29
|
def call(action)
|
39
|
-
|
40
|
-
FileUtils.mkdir_p(
|
41
|
-
::Daemons.run_proc(self.process_name,
|
30
|
+
daemons_options = self.default_options.merge({ :ARGV => [ action.to_s ] })
|
31
|
+
FileUtils.mkdir_p(daemons_options[:dir])
|
32
|
+
::Daemons.run_proc(self.process_name, daemons_options) do
|
42
33
|
server = Sanford::Server.new(self.host)
|
43
34
|
server.start
|
44
35
|
server.join_thread
|