sanford 0.3.0 → 0.4.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/README.md +7 -5
- data/Rakefile +1 -1
- data/bench/report.txt +30 -30
- data/lib/sanford/error_handler.rb +3 -2
- data/lib/sanford/exceptions.rb +0 -1
- data/lib/sanford/host.rb +5 -0
- data/lib/sanford/host_data.rb +10 -3
- data/lib/sanford/manager.rb +5 -5
- data/lib/sanford/rake.rb +1 -5
- data/lib/sanford/server.rb +1 -0
- data/lib/sanford/version.rb +1 -1
- data/lib/sanford/worker.rb +27 -6
- data/test/support/fake_connection.rb +8 -3
- data/test/support/services.rb +8 -0
- data/test/unit/host_data_test.rb +27 -13
- data/test/unit/host_test.rb +1 -3
- data/test/unit/manager_test.rb +1 -1
- data/test/unit/worker_test.rb +19 -1
- metadata +4 -4
data/README.md
CHANGED
@@ -144,14 +144,16 @@ Define a `name` on a Host to set a string name for your host that can be used to
|
|
144
144
|
|
145
145
|
### Loading An Application
|
146
146
|
|
147
|
-
Typically, a Sanford host is part of a larger application and parts of the application need to be setup or loaded when you start your Sanford server.
|
147
|
+
Typically, a Sanford host is part of a larger application and parts of the application need to be setup or loaded when you start your Sanford server. to support this, Sanford provides a `setup` hook for hosts. The proc that is defined will be called before the Sanford server is started, properly running the server in your application's environment:
|
148
148
|
|
149
149
|
```ruby
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
150
|
+
class MyHost
|
151
|
+
include Sanford::Host
|
152
|
+
|
153
|
+
setup do
|
154
|
+
require File.expand_path("../config/environment", __FILE__)
|
154
155
|
end
|
156
|
+
|
155
157
|
end
|
156
158
|
```
|
157
159
|
|
data/Rakefile
CHANGED
data/bench/report.txt
CHANGED
@@ -2,39 +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: 10515.3759ms
|
6
|
+
Average Time: 1.0515ms
|
7
|
+
Min Time: 0.7140ms
|
8
|
+
Max Time: 114.8610ms
|
9
9
|
|
10
10
|
Distribution (number of requests):
|
11
|
-
0ms:
|
12
|
-
0.7ms:
|
13
|
-
0.8ms:
|
14
|
-
0.9ms:
|
15
|
-
1ms:
|
16
|
-
1.0ms:
|
17
|
-
1.1ms:
|
18
|
-
1.2ms:
|
19
|
-
1.3ms:
|
20
|
-
1.4ms:
|
21
|
-
1.5ms:
|
22
|
-
1.6ms:
|
23
|
-
1.7ms:
|
24
|
-
1.8ms:
|
11
|
+
0ms: 8614
|
12
|
+
0.7ms: 4945
|
13
|
+
0.8ms: 2641
|
14
|
+
0.9ms: 1028
|
15
|
+
1ms: 1339
|
16
|
+
1.0ms: 612
|
17
|
+
1.1ms: 370
|
18
|
+
1.2ms: 172
|
19
|
+
1.3ms: 90
|
20
|
+
1.4ms: 39
|
21
|
+
1.5ms: 19
|
22
|
+
1.6ms: 16
|
23
|
+
1.7ms: 10
|
24
|
+
1.8ms: 7
|
25
25
|
1.9ms: 4
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
86ms: 2
|
35
|
-
88ms: 3
|
36
|
-
89ms: 4
|
37
|
-
90ms: 2
|
26
|
+
2ms: 15
|
27
|
+
3ms: 10
|
28
|
+
4ms: 1
|
29
|
+
66ms: 1
|
30
|
+
86ms: 3
|
31
|
+
87ms: 4
|
32
|
+
89ms: 2
|
33
|
+
90ms: 3
|
38
34
|
91ms: 2
|
35
|
+
92ms: 2
|
36
|
+
93ms: 1
|
37
|
+
94ms: 2
|
38
|
+
114ms: 1
|
39
39
|
|
40
40
|
Done running benchmark report
|
@@ -7,8 +7,9 @@ module Sanford
|
|
7
7
|
|
8
8
|
attr_reader :exception, :host_data, :request
|
9
9
|
|
10
|
-
def initialize(exception, host_data, request = nil)
|
10
|
+
def initialize(exception, host_data = nil, request = nil)
|
11
11
|
@exception, @host_data, @request = exception, host_data, request
|
12
|
+
@error_proc = @host_data ? @host_data.error_proc : proc{ }
|
12
13
|
end
|
13
14
|
|
14
15
|
# The exception that we are generating a response for can change in the case
|
@@ -19,7 +20,7 @@ module Sanford
|
|
19
20
|
|
20
21
|
def run
|
21
22
|
begin
|
22
|
-
result = @
|
23
|
+
result = @error_proc.call(@exception, @host_data, @request)
|
23
24
|
rescue Exception => proc_exception
|
24
25
|
@exception = proc_exception
|
25
26
|
end
|
data/lib/sanford/exceptions.rb
CHANGED
data/lib/sanford/host.rb
CHANGED
@@ -25,6 +25,7 @@ module Sanford
|
|
25
25
|
option :logger, :default => proc{ Sanford::NullLogger.new }
|
26
26
|
option :verbose_logging, :default => true
|
27
27
|
option :error_proc, Proc, :default => proc{ }
|
28
|
+
option :setup_proc, Proc, :default => proc{ }
|
28
29
|
|
29
30
|
def initialize(host)
|
30
31
|
self.name = host.class.to_s
|
@@ -75,6 +76,10 @@ module Sanford
|
|
75
76
|
self.configuration.error_proc = block
|
76
77
|
end
|
77
78
|
|
79
|
+
def setup(&block)
|
80
|
+
self.configuration.setup_proc = block
|
81
|
+
end
|
82
|
+
|
78
83
|
def version(name, &block)
|
79
84
|
version_group = Sanford::Host::VersionGroup.new(name, &block)
|
80
85
|
@versioned_services.merge!(version_group.to_hash)
|
data/lib/sanford/host_data.rb
CHANGED
@@ -20,14 +20,21 @@ module Sanford
|
|
20
20
|
@pid_dir = configuration[:pid_dir]
|
21
21
|
@logger, @verbose = configuration[:logger], configuration[:verbose_logging]
|
22
22
|
@error_proc = configuration[:error_proc]
|
23
|
+
@setup_proc = configuration[:setup_proc]
|
23
24
|
|
24
|
-
@
|
25
|
-
|
26
|
-
end
|
25
|
+
@versioned_services = service_host.versioned_services
|
26
|
+
@handlers = {}
|
27
27
|
|
28
28
|
raise Sanford::InvalidHostError.new(service_host) if !self.port
|
29
29
|
end
|
30
30
|
|
31
|
+
def setup
|
32
|
+
@setup_proc.call
|
33
|
+
@handlers = @versioned_services.inject({}) do |hash, (version, services)|
|
34
|
+
hash.merge({ version => self.constantize_services(services) })
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
31
38
|
def handler_class_for(version, service)
|
32
39
|
version_group = @handlers[version] || {}
|
33
40
|
version_group[service] || raise(Sanford::NotFoundError)
|
data/lib/sanford/manager.rb
CHANGED
@@ -19,18 +19,18 @@ module Sanford
|
|
19
19
|
self.new(service_host, options).call(action)
|
20
20
|
end
|
21
21
|
|
22
|
-
attr_reader :
|
22
|
+
attr_reader :host_data, :process_name
|
23
23
|
|
24
24
|
def initialize(service_host, options = {})
|
25
|
-
@
|
26
|
-
@process_name = [ self.
|
25
|
+
@host_data = Sanford::HostData.new(service_host, options)
|
26
|
+
@process_name = [ self.host_data.ip, self.host_data.port, self.host_data.name ].join('_')
|
27
27
|
end
|
28
28
|
|
29
29
|
def call(action)
|
30
30
|
daemons_options = self.default_options.merge({ :ARGV => [ action.to_s ] })
|
31
31
|
FileUtils.mkdir_p(daemons_options[:dir])
|
32
32
|
::Daemons.run_proc(self.process_name, daemons_options) do
|
33
|
-
server = Sanford::Server.new(self.
|
33
|
+
server = Sanford::Server.new(self.host_data)
|
34
34
|
server.start
|
35
35
|
server.join_thread
|
36
36
|
end
|
@@ -40,7 +40,7 @@ module Sanford
|
|
40
40
|
|
41
41
|
def default_options
|
42
42
|
{ :dir_mode => :normal,
|
43
|
-
:dir => self.
|
43
|
+
:dir => self.host_data.pid_dir
|
44
44
|
}
|
45
45
|
end
|
46
46
|
|
data/lib/sanford/rake.rb
CHANGED
@@ -6,11 +6,7 @@ module Sanford::Rake
|
|
6
6
|
def self.load
|
7
7
|
namespace :sanford do
|
8
8
|
|
9
|
-
|
10
|
-
# be used with Sanford
|
11
|
-
task :setup
|
12
|
-
|
13
|
-
task :load_manager => :setup do
|
9
|
+
task :load_manager do
|
14
10
|
require 'sanford'
|
15
11
|
require 'sanford/manager'
|
16
12
|
Sanford.init
|
data/lib/sanford/server.rb
CHANGED
data/lib/sanford/version.rb
CHANGED
data/lib/sanford/worker.rb
CHANGED
@@ -34,21 +34,42 @@ module Sanford
|
|
34
34
|
protected
|
35
35
|
|
36
36
|
def run!
|
37
|
-
|
37
|
+
service = ProcessedService.new
|
38
38
|
begin
|
39
39
|
request = Sanford::Protocol::Request.parse(@connection.read_data)
|
40
40
|
self.log_request(request)
|
41
|
+
service.request = request
|
42
|
+
|
41
43
|
handler_class = @host_data.handler_class_for(request.version, request.name)
|
42
44
|
self.log_handler_class(handler_class)
|
45
|
+
service.handler_class = handler_class
|
46
|
+
|
43
47
|
response = Sanford::Runner.new(handler_class, request, @host_data.logger).run
|
48
|
+
service.response = response
|
44
49
|
rescue Exception => exception
|
45
|
-
|
46
|
-
response = error_handler.run
|
47
|
-
self.log_exception(error_handler.exception)
|
50
|
+
self.handle_exception(service, exception, @host_data)
|
48
51
|
ensure
|
49
|
-
|
52
|
+
self.write_response(service)
|
50
53
|
end
|
51
|
-
|
54
|
+
service
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_response(service)
|
58
|
+
begin
|
59
|
+
@connection.write_data service.response.to_hash
|
60
|
+
rescue Exception => exception
|
61
|
+
service = self.handle_exception(service, exception)
|
62
|
+
@connection.write_data service.response.to_hash
|
63
|
+
end
|
64
|
+
service
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle_exception(service, exception, host_data = nil)
|
68
|
+
error_handler = Sanford::ErrorHandler.new(exception, host_data, service.request)
|
69
|
+
service.response = error_handler.run
|
70
|
+
service.exception = error_handler.exception
|
71
|
+
self.log_exception(service.exception)
|
72
|
+
service
|
52
73
|
end
|
53
74
|
|
54
75
|
def raise_if_debugging!(exception)
|
@@ -2,16 +2,21 @@ class FakeConnection
|
|
2
2
|
|
3
3
|
attr_reader :read_data, :response
|
4
4
|
|
5
|
-
def self.with_request(version, name, params = {})
|
5
|
+
def self.with_request(version, name, params = {}, raise_on_write = false)
|
6
6
|
request = Sanford::Protocol::Request.new(version, name, params)
|
7
|
-
self.new(request.to_hash)
|
7
|
+
self.new(request.to_hash, raise_on_write)
|
8
8
|
end
|
9
9
|
|
10
|
-
def initialize(read_data)
|
10
|
+
def initialize(read_data, raise_on_write = false)
|
11
|
+
@raise_on_write = raise_on_write
|
11
12
|
@read_data = read_data
|
12
13
|
end
|
13
14
|
|
14
15
|
def write_data(data)
|
16
|
+
if @raise_on_write
|
17
|
+
@raise_on_write = false
|
18
|
+
raise 'test fail'
|
19
|
+
end
|
15
20
|
@response = Sanford::Protocol::Response.parse(data)
|
16
21
|
end
|
17
22
|
|
data/test/support/services.rb
CHANGED
@@ -3,6 +3,12 @@ require 'logger'
|
|
3
3
|
class TestHost
|
4
4
|
include Sanford::Host
|
5
5
|
|
6
|
+
attr_accessor :setup_has_been_called
|
7
|
+
|
8
|
+
setup do
|
9
|
+
self.setup_has_been_called = true
|
10
|
+
end
|
11
|
+
|
6
12
|
ip 'localhost'
|
7
13
|
port 12000
|
8
14
|
pid_dir File.expand_path('../../../tmp/', __FILE__)
|
@@ -107,6 +113,8 @@ end
|
|
107
113
|
class UndefinedHandlersHost
|
108
114
|
include Sanford::Host
|
109
115
|
|
116
|
+
port 12345
|
117
|
+
|
110
118
|
version 'v1' do
|
111
119
|
service 'undefined', 'ThisIsNotDefined'
|
112
120
|
end
|
data/test/unit/host_data_test.rb
CHANGED
@@ -12,7 +12,7 @@ class Sanford::HostData
|
|
12
12
|
subject{ @host_data }
|
13
13
|
|
14
14
|
should have_instance_methods :name, :ip, :port, :pid_dir, :logger, :verbose,
|
15
|
-
:error_proc, :handler_class_for
|
15
|
+
:error_proc, :handler_class_for, :setup
|
16
16
|
|
17
17
|
should "default it's configuration from the service host, but allow overrides" do
|
18
18
|
host_data = Sanford::HostData.new(TestHost, :ip => '1.2.3.4', :port => 12345)
|
@@ -22,16 +22,6 @@ class Sanford::HostData
|
|
22
22
|
assert_equal 12345, host_data.port
|
23
23
|
end
|
24
24
|
|
25
|
-
should "constantize a host's handlers" do
|
26
|
-
handlers = subject.instance_variable_get("@handlers")
|
27
|
-
|
28
|
-
assert_equal TestHost::Authorized, handlers['v1']['authorized']
|
29
|
-
assert_equal TestHost::Bad, handlers['v1']['bad']
|
30
|
-
assert_equal TestHost::Echo, handlers['v1']['echo']
|
31
|
-
assert_equal TestHost::HaltIt, handlers['v1']['halt_it']
|
32
|
-
assert_equal TestHost::Multiply, handlers['v1']['multiply']
|
33
|
-
end
|
34
|
-
|
35
25
|
should "ignore nil values passed as overrides" do
|
36
26
|
host_data = Sanford::HostData.new(TestHost, :ip => nil)
|
37
27
|
|
@@ -44,7 +34,31 @@ class Sanford::HostData
|
|
44
34
|
end
|
45
35
|
end
|
46
36
|
|
47
|
-
|
37
|
+
end
|
38
|
+
|
39
|
+
class SetupTest < BaseTest
|
40
|
+
desc "after calling setup"
|
41
|
+
setup do
|
42
|
+
TestHost.setup_has_been_called = false
|
43
|
+
@host_data.setup
|
44
|
+
end
|
45
|
+
|
46
|
+
should "have called the setup proc" do
|
47
|
+
assert_equal true, TestHost.setup_has_been_called
|
48
|
+
|
49
|
+
TestHost.setup_has_been_called = false
|
50
|
+
end
|
51
|
+
|
52
|
+
should "constantize a host's handlers" do
|
53
|
+
handlers = subject.instance_variable_get("@handlers")
|
54
|
+
assert_equal TestHost::Authorized, handlers['v1']['authorized']
|
55
|
+
assert_equal TestHost::Bad, handlers['v1']['bad']
|
56
|
+
assert_equal TestHost::Echo, handlers['v1']['echo']
|
57
|
+
assert_equal TestHost::HaltIt, handlers['v1']['halt_it']
|
58
|
+
assert_equal TestHost::Multiply, handlers['v1']['multiply']
|
59
|
+
end
|
60
|
+
|
61
|
+
should "look up handler classes with #handler_class_for" do
|
48
62
|
assert_equal TestHost::Echo, subject.handler_class_for('v1', 'echo')
|
49
63
|
end
|
50
64
|
|
@@ -56,7 +70,7 @@ class Sanford::HostData
|
|
56
70
|
|
57
71
|
should "raise a custom error when a service is configured with an undefined class" do
|
58
72
|
assert_raises(Sanford::NoHandlerClassError) do
|
59
|
-
Sanford::HostData.new(UndefinedHandlersHost)
|
73
|
+
Sanford::HostData.new(UndefinedHandlersHost).setup
|
60
74
|
end
|
61
75
|
end
|
62
76
|
|
data/test/unit/host_test.rb
CHANGED
@@ -13,15 +13,13 @@ module Sanford::Host
|
|
13
13
|
subject{ MyHost.instance }
|
14
14
|
|
15
15
|
should have_instance_methods :configuration, :name, :ip, :port, :pid_dir, :logger,
|
16
|
-
:verbose_logging, :error, :version, :versioned_services
|
16
|
+
:verbose_logging, :error, :setup, :version, :versioned_services
|
17
17
|
|
18
18
|
should "get and set it's configuration options with their matching methods" do
|
19
19
|
subject.name 'my_awesome_host'
|
20
20
|
|
21
21
|
assert_equal 'my_awesome_host', subject.name
|
22
22
|
assert_equal subject.configuration.port, subject.port
|
23
|
-
|
24
|
-
|
25
23
|
end
|
26
24
|
|
27
25
|
should "add a version group with #version" do
|
data/test/unit/manager_test.rb
CHANGED
data/test/unit/worker_test.rb
CHANGED
@@ -24,7 +24,7 @@ class Sanford::Worker
|
|
24
24
|
|
25
25
|
desc "Sanford::Worker"
|
26
26
|
setup do
|
27
|
-
@host_data = Sanford::HostData.new(TestHost)
|
27
|
+
@host_data = Sanford::HostData.new(TestHost).tap{|hd| hd.setup }
|
28
28
|
@connection = FakeConnection.with_request('version', 'service', {})
|
29
29
|
@worker = Sanford::Worker.new(@host_data, @connection)
|
30
30
|
end
|
@@ -192,4 +192,22 @@ class Sanford::Worker
|
|
192
192
|
|
193
193
|
end
|
194
194
|
|
195
|
+
class WithBadResponseHashTest < BaseTest
|
196
|
+
desc "running a request that builds an object that can't be encoded"
|
197
|
+
setup do
|
198
|
+
@connection = FakeConnection.with_request('v1', 'echo', { :message => 'cant encode' }, true)
|
199
|
+
@worker = Sanford::Worker.new(@host_data, @connection)
|
200
|
+
end
|
201
|
+
|
202
|
+
should "return the response that was halted" do
|
203
|
+
assert_raises(RuntimeError){ @worker.run }
|
204
|
+
response = @connection.response
|
205
|
+
|
206
|
+
assert_equal 500, response.status.code
|
207
|
+
assert_equal "An unexpected error occurred.", response.status.message
|
208
|
+
assert_equal nil, response.data
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
195
213
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sanford
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Collin Redding
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2013-01-
|
19
|
+
date: 2013-01-28 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
prerelease: false
|