sanford 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA512:
3
- metadata.gz: 179edb42ed70349903ee1c61dac5d041ce8ccf2224121e952871965635ea4f26541f58468c3f7bfc6842dfae80551993dae461845024e26a89bfbbfb315f144a
4
- data.tar.gz: dc50fc52dcabe5aaea8969654bdd1af13fc40cb1bd62ffaafc38a845b3fe1127a17b1f1adfcd2880a828a18241b869c5f4ad3782c71bcd40c5635d285e633a3a
3
+ data.tar.gz: b37cfd3f2c40682c86f0beb66377fa878e9e9afa7176607ef4c8d5ca342f6bbf5bc79be72e6f57a34d77730bead2c61af1c3cde5e336ede29fb1de4f3910528e
4
+ metadata.gz: db614d3e51992924e70599df591799d0437fc39790fdf279bf5f896db4dfab2d4f7da2f205d9d9cd1128aa120f6f7f14eb827a9cd3888fe2e9223188f5ddc21c
5
5
  SHA1:
6
- metadata.gz: da5833891f1c7570eb1cb642bbd506487eb2f3c8
7
- data.tar.gz: 3b093248ea8ac8cd931f1cb05db52d676a34494c
6
+ data.tar.gz: 982aa3206746b65d6fd27d6c285df134f78a8e80
7
+ metadata.gz: e351442a99e056e6b8779701e9357dcb306cf48a
data/Gemfile CHANGED
@@ -3,4 +3,4 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'pry', "~> 0.9.0"
6
- gem 'bson_ext'
6
+ gem 'bson_ext', '~>1.7'
data/bench/report.rb CHANGED
@@ -1,3 +1,5 @@
1
+ $LOAD_PATH.push(File.expand_path('../..', __FILE__))
2
+
1
3
  require 'benchmark'
2
4
  require 'bench/client'
3
5
 
data/bench/report.txt CHANGED
@@ -2,46 +2,37 @@ Running benchmark report...
2
2
 
3
3
  Hitting "simple" service with {}, 10000 times
4
4
  ....................................................................................................
5
- Total Time: 7600.3550ms
6
- Average Time: 0.7600ms
7
- Min Time: 0.3941ms
8
- Max Time: 38.5608ms
5
+ Total Time: 7117.6994ms
6
+ Average Time: 0.7117ms
7
+ Min Time: 0.4079ms
8
+ Max Time: 71.8839ms
9
9
 
10
10
  Distribution (number of requests):
11
- 0ms: 9812
12
- 0.3ms: 15
13
- 0.4ms: 2030
14
- 0.5ms: 2816
15
- 0.6ms: 3236
16
- 0.7ms: 1250
17
- 0.8ms: 327
18
- 0.9ms: 138
19
- 1ms: 134
20
- 1.0ms: 60
21
- 1.1ms: 24
22
- 1.2ms: 16
23
- 1.3ms: 11
24
- 1.4ms: 5
25
- 1.5ms: 6
26
- 1.6ms: 5
27
- 1.7ms: 4
28
- 1.8ms: 2
29
- 1.9ms: 1
30
- 2ms: 4
31
- 6ms: 1
32
- 7ms: 1
11
+ 0ms: 9917
12
+ 0.4ms: 2569
13
+ 0.5ms: 2754
14
+ 0.6ms: 2608
15
+ 0.7ms: 1654
16
+ 0.8ms: 262
17
+ 0.9ms: 70
18
+ 1ms: 62
19
+ 1.0ms: 31
20
+ 1.1ms: 17
21
+ 1.2ms: 7
22
+ 1.3ms: 5
23
+ 1.5ms: 1
24
+ 1.8ms: 1
25
+ 3ms: 1
33
26
  8ms: 1
34
- 9ms: 1
35
27
  10ms: 1
36
- 28ms: 1
37
- 30ms: 5
38
- 31ms: 14
39
- 32ms: 9
40
- 33ms: 7
41
- 34ms: 4
42
- 35ms: 2
43
- 36ms: 1
44
- 37ms: 1
45
- 38ms: 1
28
+ 27ms: 1
29
+ 41ms: 1
30
+ 47ms: 1
31
+ 65ms: 4
32
+ 66ms: 1
33
+ 67ms: 5
34
+ 68ms: 3
35
+ 70ms: 1
36
+ 71ms: 1
46
37
 
47
38
  Done running benchmark report
@@ -1,4 +1,5 @@
1
1
  require 'benchmark'
2
+ require 'dat-worker-pool'
2
3
  require 'sanford-protocol'
3
4
  require 'sanford/error_handler'
4
5
  require 'sanford/logger'
@@ -45,6 +46,11 @@ module Sanford
45
46
 
46
47
  response = route.run(request, @server_data)
47
48
  processed_service.response = response
49
+ rescue DatWorkerPool::ShutdownError => exception
50
+ error = ShutdownError.new(exception.message)
51
+ error.set_backtrace(exception.backtrace)
52
+ self.handle_exception(error, @server_data, processed_service)
53
+ raise exception
48
54
  rescue StandardError => exception
49
55
  self.handle_exception(exception, @server_data, processed_service)
50
56
  ensure
@@ -101,9 +107,8 @@ module Sanford
101
107
  end
102
108
 
103
109
  def log_exception(exception)
104
- backtrace = exception.backtrace.join("\n")
105
- message = "#{exception.class}: #{exception.message}\n#{backtrace}"
106
- log_verbose(message, :error)
110
+ log_verbose("#{exception.class}: #{exception.message}", :error)
111
+ (exception.backtrace || []).each{ |l| log_verbose(l, :error) }
107
112
  end
108
113
 
109
114
  def log_verbose(message, level = :info)
@@ -154,4 +159,6 @@ module Sanford
154
159
 
155
160
  end
156
161
 
162
+ ShutdownError = Class.new(DatWorkerPool::ShutdownError)
163
+
157
164
  end
@@ -45,13 +45,13 @@ module Sanford
45
45
  def response_from_exception(exception)
46
46
  if exception.kind_of?(Sanford::Protocol::BadMessageError) ||
47
47
  exception.kind_of?(Sanford::Protocol::Request::InvalidError)
48
- build_response :bad_request, :message => exception.message
48
+ build_response 400, :message => exception.message # BAD REQUEST
49
49
  elsif exception.kind_of?(Sanford::NotFoundError)
50
- build_response :not_found
50
+ build_response 404 # NOT FOUND
51
51
  elsif exception.kind_of?(Sanford::Protocol::TimeoutError)
52
- build_response :timeout
52
+ build_response 408 # TIMEOUT
53
53
  else
54
- build_response :error, :message => "An unexpected error occurred."
54
+ build_response 500, :message => "An unexpected error occurred." # ERROR
55
55
  end
56
56
  end
57
57
 
@@ -0,0 +1,40 @@
1
+ module Sanford
2
+
3
+ class IOPipe
4
+
5
+ NULL = File.open('/dev/null', 'w')
6
+ NUMBER_OF_BYTES = 1
7
+
8
+ attr_reader :reader, :writer
9
+
10
+ def initialize
11
+ @reader = NULL
12
+ @writer = NULL
13
+ end
14
+
15
+ def setup
16
+ @reader, @writer = ::IO.pipe
17
+ end
18
+
19
+ def teardown
20
+ @reader.close unless @reader === NULL
21
+ @writer.close unless @writer === NULL
22
+ @reader = NULL
23
+ @writer = NULL
24
+ end
25
+
26
+ def read
27
+ @reader.read_nonblock(NUMBER_OF_BYTES)
28
+ end
29
+
30
+ def write(value)
31
+ @writer.write_nonblock(value[0, NUMBER_OF_BYTES])
32
+ end
33
+
34
+ def wait(timeout = nil)
35
+ !!::IO.select([@reader], nil, nil, timeout)
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -1,17 +1,27 @@
1
+ require 'sanford/io_pipe'
1
2
  require 'sanford/pid_file'
2
3
 
3
4
  module Sanford
4
5
 
5
6
  class Process
6
7
 
7
- attr_reader :server, :name, :pid_file, :restart_cmd
8
+ HALT = 'H'.freeze
9
+ STOP = 'S'.freeze
10
+ RESTART = 'R'.freeze
11
+
12
+ WAIT_FOR_SIGNALS_TIMEOUT = 15
13
+
14
+ attr_reader :server, :name, :pid_file, :signal_io, :restart_cmd
8
15
  attr_reader :server_ip, :server_port, :server_fd, :client_fds
9
16
 
10
17
  def initialize(server, options = nil)
11
18
  options ||= {}
12
19
  @server = server
20
+ @name = "sanford: #{@server.process_label}"
13
21
  @logger = @server.logger
14
- @pid_file = PIDFile.new(@server.pid_file)
22
+
23
+ @pid_file = PIDFile.new(@server.pid_file)
24
+ @signal_io = IOPipe.new
15
25
  @restart_cmd = RestartCmd.new
16
26
 
17
27
  @server_ip = @server.configured_ip
@@ -21,12 +31,10 @@ module Sanford
21
31
  end
22
32
  @listen_args = @server_fd ? [@server_fd] : [@server_ip, @server_port]
23
33
 
24
- @name = "sanford-#{@server.name}-#{@server_ip}-#{@server_port}"
25
-
26
34
  @client_fds = ENV['SANFORD_CLIENT_FDS'].to_s.split(',').map(&:to_i)
27
35
 
28
- @daemonize = !!options[:daemonize]
29
- @skip_daemonize = !ENV['SANFORD_SKIP_DAEMONIZE'].to_s.empty?
36
+ skip_daemonize = ignore_if_blank(ENV['SANFORD_SKIP_DAEMONIZE'])
37
+ @daemonize = !!options[:daemonize] && !skip_daemonize
30
38
  end
31
39
 
32
40
  def run
@@ -40,37 +48,82 @@ module Sanford
40
48
  @pid_file.write
41
49
  log "PID: #{@pid_file.pid}"
42
50
 
43
- ::Signal.trap("TERM"){ @server.stop }
44
- ::Signal.trap("INT"){ @server.halt }
45
- ::Signal.trap("USR2"){ @server.pause }
51
+ @signal_io.setup
52
+ trap_signals(@signal_io)
46
53
 
47
- thread = @server.start(@client_fds)
48
- log "#{@server.name} server started and ready."
49
- thread.join
50
- run_restart_cmd if @server.paused?
51
- rescue StandardError => exception
52
- log "Error: #{exception.message}"
53
- log "#{@server.name} server never started."
54
+ start_server(@server, @client_fds)
55
+
56
+ signal = catch(:signal) do
57
+ wait_for_signals(@signal_io, @server)
58
+ end
59
+ @signal_io.teardown
60
+
61
+ run_restart_cmd(@restart_cmd, @server) if signal == RESTART
54
62
  ensure
55
63
  @pid_file.remove
56
64
  end
57
65
 
58
- def daemonize?
59
- @daemonize && !@skip_daemonize
60
- end
66
+ def daemonize?; @daemonize; end
61
67
 
62
68
  private
63
69
 
70
+ def start_server(server, client_fds)
71
+ server.start(client_fds)
72
+ log "#{server.name} server started and ready."
73
+ rescue StandardError => exception
74
+ log "#{server.name} server never started."
75
+ raise exception
76
+ end
77
+
78
+ def trap_signals(signal_io)
79
+ trap_signal('INT'){ signal_io.write(HALT) }
80
+ trap_signal('TERM'){ signal_io.write(STOP) }
81
+ trap_signal('USR2'){ signal_io.write(RESTART) }
82
+ end
83
+
84
+ def trap_signal(signal, &block)
85
+ ::Signal.trap(signal, &block)
86
+ rescue ArgumentError
87
+ log "'#{signal}' signal not supported"
88
+ end
89
+
90
+ def wait_for_signals(signal_io, server)
91
+ loop do
92
+ ready = signal_io.wait(WAIT_FOR_SIGNALS_TIMEOUT)
93
+ handle_signal(signal_io.read, server) if ready
94
+
95
+ if !server.running?
96
+ log "Server crashed, restarting"
97
+ start_server(server, server.client_file_descriptors)
98
+ end
99
+ end
100
+ end
101
+
102
+ def handle_signal(signal, server)
103
+ log "Got '#{signal}' signal"
104
+ case signal
105
+ when HALT
106
+ server.halt(true)
107
+ when STOP
108
+ server.stop(true)
109
+ when RESTART
110
+ server.pause(true)
111
+ end
112
+ throw :signal, signal
113
+ end
114
+
115
+ def run_restart_cmd(restart_cmd, server)
116
+ log "Restarting #{server.name} daemon..."
117
+ restart_cmd.run(server)
118
+ end
119
+
64
120
  def log(message)
65
121
  @logger.info "[Sanford] #{message}"
66
122
  end
67
123
 
68
- def run_restart_cmd
69
- log "Restarting #{@server.name} daemon..."
70
- ENV['SANFORD_SERVER_FD'] = @server.file_descriptor.to_s
71
- ENV['SANFORD_CLIENT_FDS'] = @server.client_file_descriptors.join(',')
72
- ENV['SANFORD_SKIP_DAEMONIZE'] = 'yes'
73
- @restart_cmd.run
124
+ def ignore_if_blank(value, &block)
125
+ block ||= proc{ |v| v }
126
+ block.call(value) if value && !value.empty?
74
127
  end
75
128
 
76
129
  end
@@ -84,9 +137,36 @@ module Sanford
84
137
  @argv = [Gem.ruby, $0, ARGV.dup].flatten
85
138
  end
86
139
 
87
- def run
88
- Dir.chdir self.dir
89
- Kernel.exec(*self.argv)
140
+ if RUBY_VERSION == '1.8.7'
141
+
142
+ def run(server)
143
+ ENV['SANFORD_SERVER_FD'] = server.file_descriptor.to_s
144
+ ENV['SANFORD_CLIENT_FDS'] = server.client_file_descriptors.join(',')
145
+ ENV['SANFORD_SKIP_DAEMONIZE'] = 'yes'
146
+ Dir.chdir self.dir
147
+ Kernel.exec(*self.argv)
148
+ end
149
+
150
+ else
151
+
152
+ def run(server)
153
+ env = {
154
+ 'SANFORD_SERVER_FD' => server.file_descriptor.to_s,
155
+ 'SANFORD_CLIENT_FDS' => server.client_file_descriptors.join(','),
156
+ 'SANFORD_SKIP_DAEMONIZE' => 'yes'
157
+ }
158
+ # in ruby 1.9+ the `Kernel.exec` method is passed file descriptor
159
+ # redirects, this makes it so the child process that we are running via
160
+ # the `exec` has access to the file descriptors and can open them
161
+ fd_redirects = (
162
+ [server.file_descriptor] +
163
+ server.client_file_descriptors
164
+ ).inject({}){ |h, fd| h.merge!(fd => fd) }
165
+ options = { :chdir => self.dir }.merge!(fd_redirects)
166
+
167
+ Kernel.exec(*([env] + self.argv + [options]))
168
+ end
169
+
90
170
  end
91
171
 
92
172
  private
@@ -24,6 +24,11 @@ module Sanford
24
24
  @routes.push(Sanford::Route.new(name, handler_name))
25
25
  end
26
26
 
27
+ def validate!
28
+ self.routes.each(&:validate!)
29
+ true
30
+ end
31
+
27
32
  def inspect
28
33
  reference = '0x0%x' % (self.object_id << 1)
29
34
  "#<#{self.class}:#{reference} " \
@@ -1,8 +1,5 @@
1
1
  require 'dat-tcp'
2
2
  require 'much-plugin'
3
- require 'ns-options'
4
- require 'ns-options/boolean'
5
- require 'pathname'
6
3
  require 'sanford-protocol'
7
4
  require 'socket'
8
5
  require 'sanford/logger'
@@ -23,11 +20,35 @@ module Sanford
23
20
 
24
21
  module InstanceMethods
25
22
 
26
- attr_reader :server_data, :dat_tcp_server
23
+ attr_reader :server_data
27
24
 
28
25
  def initialize
29
- self.class.configuration.validate!
30
- @server_data = ServerData.new(self.class.configuration.to_hash)
26
+ config = self.class.config
27
+ begin
28
+ config.validate!
29
+ rescue InvalidError => exception
30
+ exception.set_backtrace(caller)
31
+ raise exception
32
+ end
33
+
34
+ @server_data = ServerData.new({
35
+ :name => config.name,
36
+ :ip => config.ip,
37
+ :port => config.port,
38
+ :pid_file => config.pid_file,
39
+ :shutdown_timeout => config.shutdown_timeout,
40
+ :worker_class => config.worker_class,
41
+ :worker_params => config.worker_params,
42
+ :num_workers => config.num_workers,
43
+ :error_procs => config.error_procs,
44
+ :template_source => config.template_source,
45
+ :logger => config.logger,
46
+ :router => config.router,
47
+ :receives_keep_alive => config.receives_keep_alive,
48
+ :verbose_logging => config.verbose_logging,
49
+ :routes => config.routes
50
+ })
51
+
31
52
  @dat_tcp_server = DatTCP::Server.new(self.server_data.worker_class, {
32
53
  :num_workers => self.server_data.num_workers,
33
54
  :logger => self.server_data.dtcp_logger,
@@ -36,13 +57,6 @@ module Sanford
36
57
  :sanford_server_data => self.server_data
37
58
  })
38
59
  })
39
- rescue InvalidError => exception
40
- exception.set_backtrace(caller)
41
- raise exception
42
- end
43
-
44
- def name
45
- @server_data.name
46
60
  end
47
61
 
48
62
  def ip
@@ -61,6 +75,10 @@ module Sanford
61
75
  @dat_tcp_server.client_file_descriptors
62
76
  end
63
77
 
78
+ def name
79
+ @server_data.name
80
+ end
81
+
64
82
  def configured_ip
65
83
  @server_data.ip
66
84
  end
@@ -69,6 +87,10 @@ module Sanford
69
87
  @server_data.port
70
88
  end
71
89
 
90
+ def process_label
91
+ @server_data.process_label
92
+ end
93
+
72
94
  def pid_file
73
95
  @server_data.pid_file
74
96
  end
@@ -110,8 +132,16 @@ module Sanford
110
132
  @dat_tcp_server.halt(*args)
111
133
  end
112
134
 
135
+ def listening?
136
+ @dat_tcp_server.listening?
137
+ end
138
+
139
+ def running?
140
+ @dat_tcp_server.running?
141
+ end
142
+
113
143
  def paused?
114
- @dat_tcp_server.listening? && !@dat_tcp_server.running?
144
+ self.listening? && !self.running?
115
145
  end
116
146
 
117
147
  private
@@ -128,149 +158,157 @@ module Sanford
128
158
 
129
159
  module ClassMethods
130
160
 
131
- def configuration
132
- @configuration ||= Configuration.new
161
+ def config
162
+ @config ||= Config.new
163
+ end
164
+
165
+ def name(value = nil)
166
+ self.config.name = value if !value.nil?
167
+ self.config.name
133
168
  end
134
169
 
135
- def name(*args)
136
- self.configuration.name *args
170
+ def ip(value = nil)
171
+ self.config.ip = value if !value.nil?
172
+ self.config.ip
137
173
  end
138
174
 
139
- def ip(*args)
140
- self.configuration.ip *args
175
+ def port(value = nil)
176
+ self.config.port = value if !value.nil?
177
+ self.config.port
141
178
  end
142
179
 
143
- def port(*args)
144
- self.configuration.port *args
180
+ def pid_file(value = nil)
181
+ self.config.pid_file = value if !value.nil?
182
+ self.config.pid_file
145
183
  end
146
184
 
147
- def pid_file(*args)
148
- self.configuration.pid_file *args
185
+ def shutdown_timeout(value = nil)
186
+ self.config.shutdown_timeout = value if !value.nil?
187
+ self.config.shutdown_timeout
149
188
  end
150
189
 
151
- def worker_class(new_worker_class = nil)
152
- self.configuration.worker_class = new_worker_class if new_worker_class
153
- self.configuration.worker_class
190
+ def worker_class(value = nil)
191
+ self.config.worker_class = value if !value.nil?
192
+ self.config.worker_class
154
193
  end
155
194
 
156
- def worker_params(new_worker_params = nil)
157
- self.configuration.worker_params = new_worker_params if new_worker_params
158
- self.configuration.worker_params
195
+ def worker_params(value = nil)
196
+ self.config.worker_params = value if !value.nil?
197
+ self.config.worker_params
159
198
  end
160
199
 
161
200
  def num_workers(new_num_workers = nil)
162
- self.configuration.num_workers = new_num_workers if new_num_workers
163
- self.configuration.num_workers
201
+ self.config.num_workers = new_num_workers if new_num_workers
202
+ self.config.num_workers
164
203
  end
165
204
  alias :workers :num_workers
166
205
 
167
- def receives_keep_alive(*args)
168
- self.configuration.receives_keep_alive *args
206
+ def init(&block)
207
+ self.config.init_procs << block
169
208
  end
170
209
 
171
- def verbose_logging(*args)
172
- self.configuration.verbose_logging *args
210
+ def error(&block)
211
+ self.config.error_procs << block
173
212
  end
174
213
 
175
- def logger(*args)
176
- self.configuration.logger *args
214
+ def template_source(value = nil)
215
+ self.config.template_source = value if !value.nil?
216
+ self.config.template_source
177
217
  end
178
218
 
179
- def shutdown_timeout(new_timeout = nil)
180
- self.configuration.shutdown_timeout = new_timeout if new_timeout
181
- self.configuration.shutdown_timeout
219
+ def logger(value = nil)
220
+ self.config.logger = value if !value.nil?
221
+ self.config.logger
182
222
  end
183
223
 
184
- def init(&block)
185
- self.configuration.init_procs << block
224
+ def router(value = nil, &block)
225
+ self.config.router = value if !value.nil?
226
+ self.config.router.instance_eval(&block) if block
227
+ self.config.router
186
228
  end
187
229
 
188
- def error(&block)
189
- self.configuration.error_procs << block
190
- end
230
+ # flags
191
231
 
192
- def router(value = nil, &block)
193
- self.configuration.router = value if !value.nil?
194
- self.configuration.router.instance_eval(&block) if block
195
- self.configuration.router
232
+ def receives_keep_alive(value = nil)
233
+ self.config.receives_keep_alive = value if !value.nil?
234
+ self.config.receives_keep_alive
196
235
  end
197
236
 
198
- def template_source(*args)
199
- self.configuration.template_source(*args)
237
+ def verbose_logging(value = nil)
238
+ self.config.verbose_logging = value if !value.nil?
239
+ self.config.verbose_logging
200
240
  end
201
241
 
202
242
  end
203
243
 
204
- class Configuration
205
- include NsOptions::Proxy
206
-
207
- DEFAULT_NUM_WORKERS = 4
244
+ class Config
208
245
 
209
- option :name, String, :required => true
210
- option :ip, String, :required => true, :default => '0.0.0.0'
211
- option :port, Integer, :required => true
212
- option :pid_file, Pathname
246
+ DEFAULT_NUM_WORKERS = 4.freeze
247
+ DEFAULT_IP_ADDRESS = '0.0.0.0'.freeze
213
248
 
214
- option :receives_keep_alive, NsOptions::Boolean, :default => false
215
-
216
- option :verbose_logging, :default => true
217
- option :logger, :default => proc{ NullLogger.new }
218
- option :template_source, :default => proc{ NullTemplateSource.new }
219
-
220
- attr_accessor :init_procs, :error_procs
249
+ attr_accessor :name, :ip, :port, :pid_file, :shutdown_timeout
221
250
  attr_accessor :worker_class, :worker_params, :num_workers
222
- attr_accessor :shutdown_timeout
223
- attr_accessor :router
251
+ attr_accessor :init_procs, :error_procs, :template_source, :logger, :router
252
+ attr_accessor :receives_keep_alive, :verbose_logging
224
253
 
225
- def initialize(values = nil)
226
- super(values)
227
- @init_procs, @error_procs = [], []
254
+ def initialize
255
+ @name = nil
256
+ @ip = DEFAULT_IP_ADDRESS
257
+ @port = nil
258
+ @pid_file = nil
259
+ @shutdown_timeout = nil
228
260
  @worker_class = DefaultWorker
229
261
  @worker_params = nil
230
262
  @num_workers = DEFAULT_NUM_WORKERS
231
- @shutdown_timeout = nil
263
+ @init_procs = []
264
+ @error_procs = []
265
+ @template_source = Sanford::NullTemplateSource.new(ENV['PWD'])
266
+ @logger = Sanford::NullLogger.new
232
267
  @router = Sanford::Router.new
233
- @valid = nil
268
+
269
+ @receives_keep_alive = false
270
+ @verbose_logging = true
271
+
272
+ @valid = nil
234
273
  end
235
274
 
236
275
  def routes
237
- @router.routes
238
- end
239
-
240
- def to_hash
241
- super.merge({
242
- :init_procs => self.init_procs,
243
- :error_procs => self.error_procs,
244
- :worker_class => self.worker_class,
245
- :worker_params => self.worker_params,
246
- :num_workers => self.num_workers,
247
- :shutdown_timeout => self.shutdown_timeout,
248
- :router => self.router,
249
- :routes => self.routes
250
- })
276
+ self.router.routes
251
277
  end
252
278
 
253
279
  def valid?
254
280
  !!@valid
255
281
  end
256
282
 
283
+ # for the config to be considered "valid", a few things need to happen.
284
+ # The key here is that this only needs to be done _once_ for each config.
285
+
257
286
  def validate!
258
- return @valid if !@valid.nil?
287
+ return @valid if !@valid.nil? # only need to run this once per config
288
+
289
+ # ensure all user and plugin configs/settings are applied
259
290
  self.init_procs.each(&:call)
260
- if !self.required_set?
261
- raise InvalidError, "a name, ip and port must be configured"
291
+ [:name, :ip, :port].each do |a|
292
+ if self.send(a).nil?
293
+ raise InvalidError, "a name, ip and port must be configured"
294
+ end
262
295
  end
296
+
297
+ # validate the worker class
263
298
  if !self.worker_class.kind_of?(Class) || !self.worker_class.include?(Sanford::Worker)
264
299
  raise InvalidError, "worker class must include `#{Sanford::Worker}`"
265
300
  end
266
- self.routes.each(&:validate!)
267
- @valid = true
301
+
302
+ # validate the router
303
+ self.router.validate!
304
+
305
+ @valid = true # if it made it this far, it's valid!
268
306
  end
307
+
269
308
  end
270
309
 
271
310
  DefaultWorker = Class.new{ include Sanford::Worker }
272
-
273
- InvalidError = Class.new(RuntimeError)
311
+ InvalidError = Class.new(RuntimeError)
274
312
 
275
313
  end
276
314