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.
Files changed (43) hide show
  1. data/bench/report.txt +34 -4
  2. data/bench/runner.rb +122 -1
  3. data/bench/services.rb +5 -2
  4. data/lib/sanford/error_handler.rb +60 -0
  5. data/lib/sanford/exceptions.rb +11 -10
  6. data/lib/sanford/host.rb +79 -101
  7. data/lib/sanford/host_data.rb +55 -0
  8. data/lib/sanford/logger.rb +23 -0
  9. data/lib/sanford/manager.rb +13 -22
  10. data/lib/sanford/rake.rb +1 -0
  11. data/lib/sanford/runner.rb +50 -0
  12. data/lib/sanford/server.rb +31 -15
  13. data/lib/sanford/service_handler.rb +34 -43
  14. data/lib/sanford/test_runner.rb +47 -0
  15. data/lib/sanford/version.rb +1 -1
  16. data/lib/sanford/worker.rb +124 -0
  17. data/lib/sanford.rb +49 -6
  18. data/sanford.gemspec +1 -1
  19. data/test/helper.rb +1 -0
  20. data/test/support/fake_connection.rb +18 -0
  21. data/test/support/helpers.rb +6 -10
  22. data/test/support/service_handlers.rb +56 -68
  23. data/test/support/services.rb +55 -10
  24. data/test/system/managing_test.rb +18 -18
  25. data/test/system/request_handling_test.rb +10 -100
  26. data/test/unit/config_test.rb +1 -43
  27. data/test/unit/error_handler_test.rb +133 -0
  28. data/test/unit/host_configuration_test.rb +41 -0
  29. data/test/unit/host_data_test.rb +65 -0
  30. data/test/unit/host_test.rb +20 -112
  31. data/test/unit/{host/version_group_test.rb → host_version_group_test.rb} +0 -0
  32. data/test/unit/hosts_test.rb +56 -0
  33. data/test/unit/manager_test.rb +3 -3
  34. data/test/unit/runner_test.rb +26 -0
  35. data/test/unit/server_test.rb +10 -2
  36. data/test/unit/service_handler_test.rb +126 -115
  37. data/test/unit/worker_test.rb +195 -0
  38. metadata +28 -16
  39. data/lib/sanford/config.rb +0 -33
  40. data/lib/sanford/connection.rb +0 -70
  41. data/lib/sanford/exception_handler.rb +0 -43
  42. data/test/unit/connection_test.rb +0 -23
  43. 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: 15768.8473ms
6
- Average Time: 1.5768ms
7
- Min Time: 0.9949ms
8
- Max Time: 102.2670ms
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(total_time / benchmarks.size),
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
- self.port = 12000
5
- self.pid_dir = File.expand_path("../../tmp", __FILE__)
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
@@ -1,37 +1,38 @@
1
1
  module Sanford
2
2
 
3
- class BaseError < RuntimeError; end
3
+ BaseError = Class.new(RuntimeError)
4
4
 
5
- class NotFoundError < BaseError; end
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
- @message = if Sanford.config.hosts.empty?
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
- @message = "A port must be configured or provided to build an instance of '#{host}'"
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(host, handler_class_name)
32
- @message = "Sanford couldn't find the service handler '#{handler_class_name}'." \
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/service_handler'
5
+ require 'sanford/logger'
27
6
 
28
7
  module Sanford
8
+
29
9
  module Host
30
10
 
31
- # Notes:
32
- # * When Host is included on a class, it needs to mixin NsOptions and define
33
- # the options directly on the class (instead of on the Host module).
34
- # Otherwise, NsOptions will not work correctly for the class.
35
- def self.included(host_class)
36
- host_class.class_eval do
37
- include NsOptions
38
- extend Sanford::Host::Interface
39
-
40
- options :config do
41
- option :name, String, :default => host_class.to_s
42
- option :ip, String, :default => '0.0.0.0'
43
- option :port, Integer
44
- option :pid_dir, Pathname, :default => Dir.pwd
45
- option :logger, :default => proc{ Sanford::NullLogger.new }
46
-
47
- option :exception_handler, :default => Sanford::ExceptionHandler
48
- option :versioned_services, Hash, :default => {}
49
- end
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
- INTERFACE_OPTIONS.each do |name|
68
-
69
- define_method(name) do
70
- self.config.send(name)
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
- def run(request)
76
- request_handler(request).run
77
- end
43
+ attr_reader :configuration, :versioned_services
78
44
 
79
- def inspect
80
- reference = '0x0%x' % (self.object_id << 1)
81
- "#<#{self.class}:#{reference} ip=#{self.config.ip.inspect} " \
82
- "port=#{self.config.port.inspect}>"
45
+ def initialize
46
+ @configuration = Configuration.new(self)
47
+ @versioned_services = {}
83
48
  end
84
49
 
85
- protected
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 handler_class(class_name_str)
92
- self.logger.info(" Handler: #{class_name_str.inspect}")
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 get_handler_class_name(request)
99
- services = self.config.versioned_services[request.version] || {}
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 remove_nil_values(options)
106
- (options || {}).inject({}) do |hash, (k, v)|
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
- module Interface
113
-
114
- INTERFACE_OPTIONS.each do |name|
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
- define_method("#{name}=") do |new_value|
122
- self.config.send("#{name}=", new_value)
123
- end
70
+ def verbose_logging(*args)
71
+ self.configuration.verbose_logging *args
72
+ end
124
73
 
125
- end
74
+ def error(&block)
75
+ self.configuration.error_proc = block
76
+ end
126
77
 
127
- def version(name, &block)
128
- version_group = Sanford::Host::VersionGroup.new(name, &block)
129
- self.config.versioned_services.merge!(version_group.to_hash)
130
- end
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
@@ -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/config'
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
- host_class = if (host_class_or_name = options.delete(:host))
25
- Sanford.config.find_host(host_class_or_name)
26
- else
27
- Sanford.config.hosts.first
28
- end
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
- def initialize(host_class, options = {})
34
- @host = host_class.new(options)
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
- options = self.default_options.merge({ :ARGV => [ action.to_s ] })
40
- FileUtils.mkdir_p(options[:dir])
41
- ::Daemons.run_proc(self.process_name, options) do
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
data/lib/sanford/rake.rb CHANGED
@@ -12,6 +12,7 @@ module Sanford::Rake
12
12
 
13
13
  task :load_manager => :setup do
14
14
  require 'sanford'
15
+ require 'sanford/manager'
15
16
  Sanford.init
16
17
  end
17
18