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 +4 -4
- data/Gemfile +1 -1
- data/bench/report.rb +2 -0
- data/bench/report.txt +28 -37
- data/lib/sanford/connection_handler.rb +10 -3
- data/lib/sanford/error_handler.rb +4 -4
- data/lib/sanford/io_pipe.rb +40 -0
- data/lib/sanford/process.rb +108 -28
- data/lib/sanford/router.rb +5 -0
- data/lib/sanford/server.rb +133 -95
- data/lib/sanford/server_data.rb +27 -28
- data/lib/sanford/template_source.rb +2 -2
- data/lib/sanford/version.rb +1 -1
- data/sanford.gemspec +4 -5
- data/test/helper.rb +11 -0
- data/test/support/app_server.rb +6 -3
- data/test/support/factory.rb +7 -0
- data/test/system/server_tests.rb +21 -3
- data/test/system/service_handler_tests.rb +4 -4
- data/test/unit/cli_tests.rb +2 -2
- data/test/unit/connection_handler_tests.rb +107 -47
- data/test/unit/error_handler_tests.rb +11 -11
- data/test/unit/io_pipe_tests.rb +84 -0
- data/test/unit/process_tests.rb +266 -131
- data/test/unit/router_tests.rb +25 -7
- data/test/unit/server_data_tests.rb +68 -46
- data/test/unit/server_tests.rb +197 -240
- data/test/unit/template_engine_tests.rb +1 -1
- data/test/unit/template_source_tests.rb +6 -0
- data/test/unit/test_runner_tests.rb +0 -19
- metadata +12 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA512:
|
3
|
-
|
4
|
-
|
3
|
+
data.tar.gz: b37cfd3f2c40682c86f0beb66377fa878e9e9afa7176607ef4c8d5ca342f6bbf5bc79be72e6f57a34d77730bead2c61af1c3cde5e336ede29fb1de4f3910528e
|
4
|
+
metadata.gz: db614d3e51992924e70599df591799d0437fc39790fdf279bf5f896db4dfab2d4f7da2f205d9d9cd1128aa120f6f7f14eb827a9cd3888fe2e9223188f5ddc21c
|
5
5
|
SHA1:
|
6
|
-
|
7
|
-
|
6
|
+
data.tar.gz: 982aa3206746b65d6fd27d6c285df134f78a8e80
|
7
|
+
metadata.gz: e351442a99e056e6b8779701e9357dcb306cf48a
|
data/Gemfile
CHANGED
data/bench/report.rb
CHANGED
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:
|
6
|
-
Average Time: 0.
|
7
|
-
Min Time: 0.
|
8
|
-
Max Time:
|
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:
|
12
|
-
0.
|
13
|
-
0.
|
14
|
-
0.
|
15
|
-
0.
|
16
|
-
0.
|
17
|
-
0.
|
18
|
-
|
19
|
-
|
20
|
-
1.
|
21
|
-
1.
|
22
|
-
1.
|
23
|
-
1.
|
24
|
-
1.
|
25
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
105
|
-
|
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
|
48
|
+
build_response 400, :message => exception.message # BAD REQUEST
|
49
49
|
elsif exception.kind_of?(Sanford::NotFoundError)
|
50
|
-
build_response
|
50
|
+
build_response 404 # NOT FOUND
|
51
51
|
elsif exception.kind_of?(Sanford::Protocol::TimeoutError)
|
52
|
-
build_response
|
52
|
+
build_response 408 # TIMEOUT
|
53
53
|
else
|
54
|
-
build_response
|
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
|
data/lib/sanford/process.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
29
|
-
@
|
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
|
-
|
44
|
-
|
45
|
-
::Signal.trap("USR2"){ @server.pause }
|
51
|
+
@signal_io.setup
|
52
|
+
trap_signals(@signal_io)
|
46
53
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
69
|
-
|
70
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
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
|
data/lib/sanford/router.rb
CHANGED
data/lib/sanford/server.rb
CHANGED
@@ -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
|
23
|
+
attr_reader :server_data
|
27
24
|
|
28
25
|
def initialize
|
29
|
-
self.class.
|
30
|
-
|
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
|
-
|
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
|
132
|
-
@
|
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
|
136
|
-
self.
|
170
|
+
def ip(value = nil)
|
171
|
+
self.config.ip = value if !value.nil?
|
172
|
+
self.config.ip
|
137
173
|
end
|
138
174
|
|
139
|
-
def
|
140
|
-
self.
|
175
|
+
def port(value = nil)
|
176
|
+
self.config.port = value if !value.nil?
|
177
|
+
self.config.port
|
141
178
|
end
|
142
179
|
|
143
|
-
def
|
144
|
-
self.
|
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
|
148
|
-
self.
|
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(
|
152
|
-
self.
|
153
|
-
self.
|
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(
|
157
|
-
self.
|
158
|
-
self.
|
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.
|
163
|
-
self.
|
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
|
168
|
-
self.
|
206
|
+
def init(&block)
|
207
|
+
self.config.init_procs << block
|
169
208
|
end
|
170
209
|
|
171
|
-
def
|
172
|
-
self.
|
210
|
+
def error(&block)
|
211
|
+
self.config.error_procs << block
|
173
212
|
end
|
174
213
|
|
175
|
-
def
|
176
|
-
self.
|
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
|
180
|
-
self.
|
181
|
-
self.
|
219
|
+
def logger(value = nil)
|
220
|
+
self.config.logger = value if !value.nil?
|
221
|
+
self.config.logger
|
182
222
|
end
|
183
223
|
|
184
|
-
def
|
185
|
-
self.
|
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
|
-
|
189
|
-
self.configuration.error_procs << block
|
190
|
-
end
|
230
|
+
# flags
|
191
231
|
|
192
|
-
def
|
193
|
-
self.
|
194
|
-
self.
|
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
|
199
|
-
self.
|
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
|
205
|
-
include NsOptions::Proxy
|
206
|
-
|
207
|
-
DEFAULT_NUM_WORKERS = 4
|
244
|
+
class Config
|
208
245
|
|
209
|
-
|
210
|
-
|
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
|
-
|
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 :
|
223
|
-
attr_accessor :
|
251
|
+
attr_accessor :init_procs, :error_procs, :template_source, :logger, :router
|
252
|
+
attr_accessor :receives_keep_alive, :verbose_logging
|
224
253
|
|
225
|
-
def initialize
|
226
|
-
|
227
|
-
@
|
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
|
-
@
|
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
|
-
|
268
|
+
|
269
|
+
@receives_keep_alive = false
|
270
|
+
@verbose_logging = true
|
271
|
+
|
272
|
+
@valid = nil
|
234
273
|
end
|
235
274
|
|
236
275
|
def routes
|
237
|
-
|
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
|
-
|
261
|
-
|
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
|
-
|
267
|
-
|
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
|
|