sanford 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'sanford-protocol'
|
3
|
+
|
4
|
+
require 'sanford/logger'
|
5
|
+
|
6
|
+
module Sanford
|
7
|
+
|
8
|
+
class Runner
|
9
|
+
|
10
|
+
ResponseArgs = Struct.new(:status, :data)
|
11
|
+
|
12
|
+
attr_reader :handler_class, :request, :logger
|
13
|
+
|
14
|
+
def initialize(handler_class, request, logger = nil)
|
15
|
+
@handler_class, @request = handler_class, request
|
16
|
+
@logger = logger || Sanford::NullLogger.new
|
17
|
+
@handler = @handler_class.new(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
response_args = catch_halt do
|
22
|
+
@handler.init
|
23
|
+
@handler.run
|
24
|
+
end
|
25
|
+
Sanford::Protocol::Response.new(response_args.status, response_args.data)
|
26
|
+
end
|
27
|
+
|
28
|
+
module HaltMethods
|
29
|
+
|
30
|
+
# It's best to keep what `halt` and `catch_halt` return in the same format.
|
31
|
+
# Currently this is a `ResponseArgs` object. This is so no matter how the
|
32
|
+
# block returns (either by throwing or running normally), you get the same
|
33
|
+
# thing kind of object.
|
34
|
+
|
35
|
+
def halt(status, options = nil)
|
36
|
+
options = OpenStruct.new(options || {})
|
37
|
+
response_status = [ status, options.message ]
|
38
|
+
throw :halt, ResponseArgs.new(response_status, options.data)
|
39
|
+
end
|
40
|
+
|
41
|
+
def catch_halt(&block)
|
42
|
+
catch(:halt){ ResponseArgs.new(*block.call) }
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
include HaltMethods
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/lib/sanford/server.rb
CHANGED
@@ -1,37 +1,53 @@
|
|
1
|
-
# Sanford's server uses DatTCP for a TCP Server. When a client connects, the
|
2
|
-
# `serve` method is called. Sanford creates a new instance of a connection
|
3
|
-
# handler and hands it the service host and client socket. This is because the
|
4
|
-
# `serve` method can be accessed by multiple threads, so we essentially create a
|
5
|
-
# new connection handler per thread.
|
6
|
-
#
|
7
1
|
require 'dat-tcp'
|
2
|
+
require 'sanford-protocol'
|
8
3
|
|
9
|
-
require 'sanford/
|
4
|
+
require 'sanford/host_data'
|
5
|
+
require 'sanford/worker'
|
10
6
|
|
11
7
|
module Sanford
|
12
8
|
|
13
9
|
class Server
|
14
10
|
include DatTCP::Server
|
15
11
|
|
16
|
-
attr_reader :
|
12
|
+
attr_reader :host_data
|
17
13
|
|
18
|
-
def initialize(
|
19
|
-
@
|
20
|
-
super(
|
14
|
+
def initialize(host, options = {})
|
15
|
+
@host_data = host.kind_of?(Sanford::HostData) ? host : Sanford::HostData.new(host)
|
16
|
+
super(@host_data.ip, @host_data.port, options)
|
21
17
|
end
|
22
18
|
|
23
19
|
def name
|
24
|
-
|
20
|
+
@host_data.name
|
25
21
|
end
|
26
22
|
|
23
|
+
# `serve` can be called at the same time by multiple threads. Thus we create
|
24
|
+
# a new instance of the handler for every request.
|
27
25
|
def serve(socket)
|
28
|
-
|
29
|
-
connection.process
|
26
|
+
Sanford::Worker.new(@host_data, Connection.new(socket)).run
|
30
27
|
end
|
31
28
|
|
32
29
|
def inspect
|
33
30
|
reference = '0x0%x' % (self.object_id << 1)
|
34
|
-
"#<#{self.class}:#{reference} @service_host=#{
|
31
|
+
"#<#{self.class}:#{reference} @service_host=#{@host_data.inspect}>"
|
32
|
+
end
|
33
|
+
|
34
|
+
class Connection
|
35
|
+
|
36
|
+
DEFAULT_TIMEOUT = 1
|
37
|
+
|
38
|
+
def initialize(socket)
|
39
|
+
@connection = Sanford::Protocol::Connection.new(socket)
|
40
|
+
@timeout = (ENV['SANFORD_TIMEOUT'] || DEFAULT_TIMEOUT).to_f
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_data
|
44
|
+
@connection.read(@timeout)
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_data(data)
|
48
|
+
@connection.write data
|
49
|
+
end
|
50
|
+
|
35
51
|
end
|
36
52
|
|
37
53
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'ostruct'
|
2
1
|
require 'sanford-protocol'
|
3
2
|
|
4
3
|
module Sanford
|
@@ -15,77 +14,69 @@ module Sanford
|
|
15
14
|
false
|
16
15
|
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
def initialize(logger, request)
|
21
|
-
@logger = logger
|
22
|
-
@request = request
|
17
|
+
def initialize(runner)
|
18
|
+
@sanford_runner = runner
|
23
19
|
end
|
24
20
|
|
25
21
|
def init
|
22
|
+
self.run_callback 'before_init'
|
26
23
|
self.init!
|
24
|
+
self.run_callback 'after_init'
|
27
25
|
end
|
28
26
|
|
29
27
|
def init!
|
30
28
|
end
|
31
29
|
|
32
|
-
# This method has very specific handling when before/after callbacks halt.
|
33
|
-
# It should always return a response tuple: `[ status, data ]`
|
34
|
-
# * If `before_run` halts, then the handler is not 'run' (it's `init` and
|
35
|
-
# `run` methods are not called) and it's response tuple is returned.
|
36
|
-
# * If `after_run` halts, then it's response tuple is returned, even if
|
37
|
-
# calling `before_run` or 'running' the handler generated a response
|
38
|
-
# tuple.
|
39
|
-
# * If `before_run` and `after_run` do not halt, then the response tuple
|
40
|
-
# from 'running' is used.
|
41
30
|
def run
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
[ 200, data ]
|
47
|
-
end
|
48
|
-
after_response_tuple = self.run_callback 'after_run'
|
49
|
-
(response_tuple = after_response_tuple) if after_response_tuple
|
50
|
-
response_tuple
|
31
|
+
self.run_callback 'before_run'
|
32
|
+
data = self.run!
|
33
|
+
self.run_callback 'after_run'
|
34
|
+
[ 200, data ]
|
51
35
|
end
|
52
36
|
|
53
37
|
def run!
|
54
38
|
raise NotImplementedError
|
55
39
|
end
|
56
40
|
|
41
|
+
def inspect
|
42
|
+
reference = '0x0%x' % (self.object_id << 1)
|
43
|
+
"#<#{self.class}:#{reference} @request=#{self.request.inspect}>"
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def before_init
|
49
|
+
end
|
50
|
+
|
51
|
+
def after_init
|
52
|
+
end
|
53
|
+
|
57
54
|
def before_run
|
58
55
|
end
|
59
56
|
|
60
57
|
def after_run
|
61
58
|
end
|
62
59
|
|
63
|
-
|
64
|
-
|
60
|
+
# Helpers
|
61
|
+
|
62
|
+
def halt(*args)
|
63
|
+
@sanford_runner.halt(*args)
|
65
64
|
end
|
66
65
|
|
67
|
-
def
|
68
|
-
|
69
|
-
"#<#{self.class}:#{reference} @request=#{self.request.inspect}>"
|
66
|
+
def request
|
67
|
+
@sanford_runner.request
|
70
68
|
end
|
71
69
|
|
72
|
-
|
70
|
+
def params
|
71
|
+
self.request.params
|
72
|
+
end
|
73
73
|
|
74
|
-
def
|
75
|
-
|
76
|
-
response_status = [ status, options.message ]
|
77
|
-
throw(:halt, [ response_status, options.data ])
|
74
|
+
def logger
|
75
|
+
@sanford_runner.logger
|
78
76
|
end
|
79
77
|
|
80
|
-
|
81
|
-
|
82
|
-
# also need to be sure to return nil if nothing is thrown, so that it
|
83
|
-
# is not considered as a response.
|
84
|
-
def run_callback(name)
|
85
|
-
catch(:halt) do
|
86
|
-
self.send(name.to_s)
|
87
|
-
nil
|
88
|
-
end
|
78
|
+
def run_callback(callback)
|
79
|
+
self.send(callback.to_s)
|
89
80
|
end
|
90
81
|
|
91
82
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'sanford-protocol'
|
2
|
+
|
3
|
+
require 'sanford/logger'
|
4
|
+
require 'sanford/runner'
|
5
|
+
|
6
|
+
module Sanford
|
7
|
+
|
8
|
+
class TestRunner
|
9
|
+
include Sanford::Runner::HaltMethods
|
10
|
+
|
11
|
+
attr_reader :handler, :response, :request, :logger
|
12
|
+
|
13
|
+
def initialize(handler_class, params = {}, logger = nil)
|
14
|
+
@handler_class = handler_class
|
15
|
+
@request = params.kind_of?(Sanford::Protocol::Request) ? params : test_request(params)
|
16
|
+
@logger = logger || Sanford::NullLogger.new
|
17
|
+
|
18
|
+
@handler = @handler_class.new(self)
|
19
|
+
@response = build_response catch(:halt){ @handler.init; nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
@response ||= build_response catch_halt{ @handler.run }
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def test_request(params)
|
29
|
+
Sanford::Protocol::Request.new('test_version', 'test_service', params)
|
30
|
+
end
|
31
|
+
|
32
|
+
def build_response(response_args)
|
33
|
+
Sanford::Protocol::Response.new(response_args.status, response_args.data) if response_args
|
34
|
+
end
|
35
|
+
|
36
|
+
module Helpers
|
37
|
+
module_function
|
38
|
+
|
39
|
+
def test_runner(*args)
|
40
|
+
TestRunner.new(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/sanford/version.rb
CHANGED
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'sanford-protocol'
|
3
|
+
|
4
|
+
require 'sanford/error_handler'
|
5
|
+
require 'sanford/logger'
|
6
|
+
require 'sanford/runner'
|
7
|
+
|
8
|
+
module Sanford
|
9
|
+
|
10
|
+
class Worker
|
11
|
+
|
12
|
+
ProcessedService = Struct.new(:request, :handler_class, :response, :exception, :time_taken)
|
13
|
+
|
14
|
+
attr_reader :logger
|
15
|
+
|
16
|
+
def initialize(host_data, connection)
|
17
|
+
@host_data, @connection = host_data, connection
|
18
|
+
|
19
|
+
@logger = Sanford::Logger.new(@host_data.logger, @host_data.verbose)
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
processed_service = nil
|
24
|
+
self.log_received
|
25
|
+
benchmark = Benchmark.measure do
|
26
|
+
processed_service = self.run!
|
27
|
+
end
|
28
|
+
processed_service.time_taken = self.round_time(benchmark.real)
|
29
|
+
self.log_complete(processed_service)
|
30
|
+
self.raise_if_debugging!(processed_service.exception)
|
31
|
+
processed_service
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def run!
|
37
|
+
request, handler_class, response, exception = nil, nil, nil, nil
|
38
|
+
begin
|
39
|
+
request = Sanford::Protocol::Request.parse(@connection.read_data)
|
40
|
+
self.log_request(request)
|
41
|
+
handler_class = @host_data.handler_class_for(request.version, request.name)
|
42
|
+
self.log_handler_class(handler_class)
|
43
|
+
response = Sanford::Runner.new(handler_class, request, @host_data.logger).run
|
44
|
+
rescue Exception => exception
|
45
|
+
error_handler = Sanford::ErrorHandler.new(exception, @host_data, request)
|
46
|
+
response = error_handler.run
|
47
|
+
self.log_exception(error_handler.exception)
|
48
|
+
ensure
|
49
|
+
@connection.write_data response.to_hash
|
50
|
+
end
|
51
|
+
ProcessedService.new(request, handler_class, response, exception)
|
52
|
+
end
|
53
|
+
|
54
|
+
def raise_if_debugging!(exception)
|
55
|
+
raise exception if exception && ENV['SANFORD_DEBUG']
|
56
|
+
end
|
57
|
+
|
58
|
+
def log_received
|
59
|
+
self.logger.verbose.info("Received request")
|
60
|
+
end
|
61
|
+
|
62
|
+
def log_request(request)
|
63
|
+
self.logger.verbose.info(" Version: #{request.version.inspect}")
|
64
|
+
self.logger.verbose.info(" Service: #{request.name.inspect}")
|
65
|
+
self.logger.verbose.info(" Params: #{request.params.inspect}")
|
66
|
+
end
|
67
|
+
|
68
|
+
def log_handler_class(handler_class)
|
69
|
+
self.logger.verbose.info(" Handler: #{handler_class}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def log_complete(processed_service)
|
73
|
+
self.logger.verbose.info "Completed in #{processed_service.time_taken}ms " \
|
74
|
+
"#{processed_service.response.status}\n"
|
75
|
+
self.logger.summary.info self.summary_line(processed_service).to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def log_exception(exception)
|
79
|
+
self.logger.verbose.error("#{exception.class}: #{exception.message}")
|
80
|
+
self.logger.verbose.error(exception.backtrace.join("\n"))
|
81
|
+
end
|
82
|
+
|
83
|
+
def summary_line(processed_service)
|
84
|
+
SummaryLine.new.tap do |line|
|
85
|
+
if (request = processed_service.request)
|
86
|
+
line.add 'version', request.version
|
87
|
+
line.add 'service', request.name
|
88
|
+
line.add 'params', request.params
|
89
|
+
end
|
90
|
+
line.add 'handler', processed_service.handler_class
|
91
|
+
line.add 'status', processed_service.response.status.code if processed_service.response
|
92
|
+
line.add 'duration', processed_service.time_taken
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
ROUND_PRECISION = 2
|
97
|
+
ROUND_MODIFIER = 10 ** ROUND_PRECISION
|
98
|
+
def round_time(time_in_seconds)
|
99
|
+
(time_in_seconds * 1000 * ROUND_MODIFIER).to_i / ROUND_MODIFIER.to_f
|
100
|
+
end
|
101
|
+
|
102
|
+
class SummaryLine
|
103
|
+
|
104
|
+
def initialize
|
105
|
+
@hash = {}
|
106
|
+
end
|
107
|
+
|
108
|
+
def add(key, value)
|
109
|
+
@hash[key] = value.inspect if value
|
110
|
+
end
|
111
|
+
|
112
|
+
# change the key's order in the array to change the order to change the
|
113
|
+
# order they appear in when logged
|
114
|
+
def to_s
|
115
|
+
[ 'version', 'service', 'handler', 'status', 'duration', 'params' ].map do |key|
|
116
|
+
"#{key}=#{@hash[key]}" if @hash[key]
|
117
|
+
end.compact.join(" ")
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
data/lib/sanford.rb
CHANGED
@@ -1,12 +1,26 @@
|
|
1
1
|
module Sanford; end
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
3
|
+
require 'ns-options'
|
4
|
+
require 'pathname'
|
5
|
+
require 'set'
|
6
|
+
|
5
7
|
require 'sanford/host'
|
8
|
+
require 'sanford/server'
|
9
|
+
require 'sanford/service_handler'
|
6
10
|
require 'sanford/version'
|
7
11
|
|
12
|
+
ENV['SANFORD_SERVICES_CONFIG'] ||= 'config/services'
|
13
|
+
|
8
14
|
module Sanford
|
9
15
|
|
16
|
+
def self.register(host)
|
17
|
+
@hosts.add(host)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.hosts
|
21
|
+
@hosts
|
22
|
+
end
|
23
|
+
|
10
24
|
def self.config
|
11
25
|
Sanford::Config
|
12
26
|
end
|
@@ -17,14 +31,43 @@ module Sanford
|
|
17
31
|
end
|
18
32
|
|
19
33
|
def self.init
|
34
|
+
@hosts ||= Hosts.new
|
20
35
|
require self.config.services_config
|
21
36
|
end
|
22
37
|
|
23
|
-
|
24
|
-
|
38
|
+
module Config
|
39
|
+
include NsOptions::Proxy
|
40
|
+
|
41
|
+
option :services_config, Pathname, :default => ENV['SANFORD_SERVICES_CONFIG']
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class Hosts
|
46
|
+
|
47
|
+
def initialize(values = [])
|
48
|
+
@set = Set.new(values)
|
49
|
+
end
|
50
|
+
|
51
|
+
# We want class names to take precedence over a configured name, so that if
|
52
|
+
# a user specifies a specific class, they always get it
|
53
|
+
def find(name)
|
54
|
+
self.find_by_class_name(name) || self.find_by_name(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_by_class_name(class_name)
|
58
|
+
@set.detect{|host_class| host_class.to_s == class_name.to_s }
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_by_name(name)
|
62
|
+
@set.detect{|host_class| host_class.name == name.to_s }
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_missing(method, *args, &block)
|
66
|
+
@set.send(method, *args, &block)
|
67
|
+
end
|
25
68
|
|
26
|
-
|
27
|
-
|
69
|
+
def respond_to?(method)
|
70
|
+
super || @set.respond_to?(method)
|
28
71
|
end
|
29
72
|
|
30
73
|
end
|
data/sanford.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
gem.add_dependency("daemons", ["~>1.1"])
|
21
21
|
gem.add_dependency("dat-tcp", ["~>0.1"])
|
22
|
-
gem.add_dependency("ns-options", ["~>1.0
|
22
|
+
gem.add_dependency("ns-options", ["~>1.0"])
|
23
23
|
gem.add_dependency("sanford-protocol", ["~>0.5"])
|
24
24
|
|
25
25
|
gem.add_development_dependency("assert", ["~>1.0"])
|
data/test/helper.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
class FakeConnection
|
2
|
+
|
3
|
+
attr_reader :read_data, :response
|
4
|
+
|
5
|
+
def self.with_request(version, name, params = {})
|
6
|
+
request = Sanford::Protocol::Request.new(version, name, params)
|
7
|
+
self.new(request.to_hash)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(read_data)
|
11
|
+
@read_data = read_data
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_data(data)
|
15
|
+
@response = Sanford::Protocol::Response.parse(data)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/test/support/helpers.rb
CHANGED
@@ -3,19 +3,17 @@ module Test
|
|
3
3
|
module Environment
|
4
4
|
|
5
5
|
def self.store_and_clear_hosts
|
6
|
-
@previous_hosts = Sanford.
|
7
|
-
Sanford.
|
6
|
+
@previous_hosts = Sanford.hosts.instance_variable_get("@set").dup
|
7
|
+
Sanford.hosts.clear
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.restore_hosts
|
11
|
-
Sanford.
|
11
|
+
Sanford.instance_variable_set("@hosts", Sanford::Hosts.new(@previous_hosts))
|
12
12
|
@previous_hosts = nil
|
13
13
|
end
|
14
14
|
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
17
|
module ForkServerHelper
|
20
18
|
|
21
19
|
def start_server(server, &block)
|
@@ -37,18 +35,16 @@ module Test
|
|
37
35
|
|
38
36
|
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
38
|
module ForkManagerHelper
|
43
39
|
|
44
40
|
# start a Sanford server using Sanford's manager in a forked process
|
45
41
|
def call_sanford_manager(*args, &block)
|
46
42
|
pid = fork do
|
47
|
-
STDOUT.reopen('/dev/null')
|
43
|
+
STDOUT.reopen('/dev/null') unless ENV['SANFORD_DEBUG']
|
48
44
|
trap("TERM"){ exit }
|
49
45
|
Sanford::Manager.call(*args)
|
50
46
|
end
|
51
|
-
sleep 1 # give time for the command to run
|
47
|
+
sleep 1.5 # give time for the command to run
|
52
48
|
yield
|
53
49
|
ensure
|
54
50
|
if pid
|
@@ -64,7 +60,7 @@ module Test
|
|
64
60
|
end
|
65
61
|
|
66
62
|
def expected_pid_file(host, ip, port)
|
67
|
-
host.
|
63
|
+
host.pid_dir.join("#{ip}_#{port}_#{host}.pid")
|
68
64
|
end
|
69
65
|
|
70
66
|
end
|