ruby_skynet 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -2
- data/Gemfile.lock +8 -4
- data/Rakefile +5 -5
- data/examples/echo_server.rb +0 -4
- data/lib/rails/generators/ruby_skynet/config/templates/ruby_skynet.yml +11 -2
- data/lib/ruby_skynet/client.rb +1 -1
- data/lib/ruby_skynet/common.rb +1 -0
- data/lib/ruby_skynet/connection.rb +2 -2
- data/lib/ruby_skynet/railties/ruby_skynet.rake +1 -1
- data/lib/ruby_skynet/ruby_skynet.rb +48 -1
- data/lib/ruby_skynet/server.rb +3 -3
- data/lib/ruby_skynet/service_registry.rb +248 -0
- data/lib/ruby_skynet/version.rb +1 -1
- data/lib/ruby_skynet.rb +9 -10
- data/test/client_test.rb +2 -0
- data/test/service_registry_test.rb +122 -0
- metadata +15 -20
- data/examples/e.rb +0 -0
- data/lib/ruby_skynet/doozer/client.rb +0 -209
- data/lib/ruby_skynet/doozer/exceptions.rb +0 -5
- data/lib/ruby_skynet/doozer/msg.pb.rb +0 -118
- data/lib/ruby_skynet/registry.rb +0 -375
- data/test/doozer_client_test.rb +0 -70
- data/test/registry_test.rb +0 -99
data/lib/ruby_skynet/registry.rb
DELETED
@@ -1,375 +0,0 @@
|
|
1
|
-
require 'sync_attr'
|
2
|
-
require 'multi_json'
|
3
|
-
require 'thread_safe'
|
4
|
-
require 'gene_pool'
|
5
|
-
require 'resolv'
|
6
|
-
|
7
|
-
#
|
8
|
-
# RubySkynet Registry Client
|
9
|
-
#
|
10
|
-
# Keeps a local copy of the Skynet Registry
|
11
|
-
#
|
12
|
-
# Subscribes to Registry changes and the internal copy up to date
|
13
|
-
#
|
14
|
-
module RubySkynet
|
15
|
-
class Registry
|
16
|
-
include SyncAttr
|
17
|
-
|
18
|
-
# Service Registry has the following format
|
19
|
-
# Key: [String] 'name/version/region'
|
20
|
-
# Value: [Array<String>] 'host:port', 'host:port'
|
21
|
-
sync_cattr_reader :service_registry do
|
22
|
-
logger.benchmark_info "Connected to Doozer" do
|
23
|
-
start
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
@@on_server_removed_callbacks = ThreadSafe::Hash.new
|
28
|
-
@@monitor_thread = nil
|
29
|
-
|
30
|
-
DOOZER_SERVICES_PATH = "/services/*/*/*/*/*"
|
31
|
-
|
32
|
-
# Default doozer configuration
|
33
|
-
# To replace this default, set the config as follows:
|
34
|
-
# RubySkynet::Client.doozer_config = { .... }
|
35
|
-
#
|
36
|
-
# :servers [Array of String]
|
37
|
-
# Array of URL's of doozer servers to connect to with port numbers
|
38
|
-
# ['server1:2000', 'server2:2000']
|
39
|
-
#
|
40
|
-
# The second server will only be attempted once the first server
|
41
|
-
# cannot be connected to or has timed out on connect
|
42
|
-
# A read failure or timeout will not result in switching to the second
|
43
|
-
# server, only a connection failure or during an automatic reconnect
|
44
|
-
#
|
45
|
-
# :read_timeout [Float]
|
46
|
-
# Time in seconds to timeout on read
|
47
|
-
# Can be overridden by supplying a timeout in the read call
|
48
|
-
#
|
49
|
-
# :connect_timeout [Float]
|
50
|
-
# Time in seconds to timeout when trying to connect to the server
|
51
|
-
#
|
52
|
-
# :connect_retry_count [Fixnum]
|
53
|
-
# Number of times to retry connecting when a connection fails
|
54
|
-
#
|
55
|
-
# :connect_retry_interval [Float]
|
56
|
-
# Number of seconds between connection retry attempts after the first failed attempt
|
57
|
-
sync_cattr_accessor :doozer_config do
|
58
|
-
{
|
59
|
-
:servers => ['127.0.0.1:8046'],
|
60
|
-
:read_timeout => 5,
|
61
|
-
:connect_timeout => 3,
|
62
|
-
:connect_retry_interval => 1,
|
63
|
-
:connect_retry_count => 30
|
64
|
-
}
|
65
|
-
end
|
66
|
-
|
67
|
-
# Register the supplied service at this Skynet Server host and Port
|
68
|
-
def self.register_service(name, version, region, hostname, port)
|
69
|
-
config = {
|
70
|
-
"Config" => {
|
71
|
-
"UUID" => "#{hostname}:#{port}-#{$$}-#{name}-#{version}",
|
72
|
-
"Name" => name,
|
73
|
-
"Version" => version.to_s,
|
74
|
-
"Region" => region,
|
75
|
-
"ServiceAddr" => {
|
76
|
-
"IPAddress" => hostname,
|
77
|
-
"Port" => port,
|
78
|
-
"MaxPort" => port + 999
|
79
|
-
},
|
80
|
-
},
|
81
|
-
"Registered" => true
|
82
|
-
}
|
83
|
-
doozer_pool.with_connection do |doozer|
|
84
|
-
doozer["/services/#{name}/#{version}/#{region}/#{hostname}/#{port}"] = MultiJson.encode(config)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# Deregister the supplied service from the Registry
|
89
|
-
def self.deregister_service(name, version, region, hostname, port)
|
90
|
-
doozer_pool.with_connection do |doozer|
|
91
|
-
doozer.delete("/services/#{name}/#{version}/#{region}/#{hostname}/#{port}") rescue nil
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# Return a server that implements the specified service
|
96
|
-
def self.server_for(name, version='*', region='Development')
|
97
|
-
if servers = servers_for(name, version, region)
|
98
|
-
# Randomly select one of the servers offering the service
|
99
|
-
servers[rand(servers.size)]
|
100
|
-
else
|
101
|
-
msg = "No servers available for service: #{name} with version: #{version} in region: #{region}"
|
102
|
-
logger.warn msg
|
103
|
-
raise ServiceUnavailable.new(msg)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Returns [Array] of the hostname and port pair [String] that implements a particular service
|
108
|
-
# Performs a doozer lookup to find the servers
|
109
|
-
#
|
110
|
-
# name:
|
111
|
-
# Name of the service to lookup
|
112
|
-
# version:
|
113
|
-
# Version of service to locate
|
114
|
-
# Default: All versions
|
115
|
-
# region:
|
116
|
-
# Region to look for the service in
|
117
|
-
def self.registered_implementers(name='*', version='*', region='Development')
|
118
|
-
hosts = []
|
119
|
-
doozer_pool.with_connection do |doozer|
|
120
|
-
doozer.walk("/services/#{name}/#{version}/#{region}/*/*").each do |node|
|
121
|
-
entry = MultiJson.load(node.value)
|
122
|
-
hosts << entry if entry['Registered']
|
123
|
-
end
|
124
|
-
end
|
125
|
-
hosts
|
126
|
-
end
|
127
|
-
|
128
|
-
# Returns [Array<String>] a list of servers implementing the requested service
|
129
|
-
def self.servers_for(name, version='*', region='Development')
|
130
|
-
if version == '*'
|
131
|
-
# Find the highest version for the named service in this region
|
132
|
-
version = -1
|
133
|
-
service_registry.keys.each do |key|
|
134
|
-
if match = key.match(/#{name}\/(\d+)\/#{region}/)
|
135
|
-
ver = match[1].to_i
|
136
|
-
version = ver if ver > version
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
if server_infos = service_registry["#{name}/#{version}/#{region}"]
|
141
|
-
server_infos.first.servers
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# Invokes registered callbacks when a specific server is shutdown or terminates
|
146
|
-
# Not when a server de-registers itself
|
147
|
-
# The callback will only be called once and will need to be re-registered
|
148
|
-
# after being called if future callbacks are required for that server
|
149
|
-
def self.on_server_removed(server, &block)
|
150
|
-
(@@on_server_removed_callbacks[server] ||= ThreadSafe::Array.new) << block
|
151
|
-
end
|
152
|
-
|
153
|
-
IPV4_REG_EXP = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
|
154
|
-
|
155
|
-
# Returns [Integer] the score for the supplied ip_address
|
156
|
-
# Score currently ranges from 0 to 4 with 4 being the best score
|
157
|
-
# If the IP address does not match an IP v4 address a DNS lookup will
|
158
|
-
# be performed
|
159
|
-
def self.score_for_server(ip_address)
|
160
|
-
score = 0
|
161
|
-
# Each matching element adds 1 to the score
|
162
|
-
# 192.168. 0. 0
|
163
|
-
# 1
|
164
|
-
# 1
|
165
|
-
# 1
|
166
|
-
# 1
|
167
|
-
server_match = IPV4_REG_EXP.match(ip_address) || IPV4_REG_EXP.match(Resolv::DNS.new.getaddress(ip_address).to_s)
|
168
|
-
if server_match
|
169
|
-
@@local_match ||= IPV4_REG_EXP.match(RubySkynet.local_ip_address)
|
170
|
-
score = 0
|
171
|
-
(1..4).each do |i|
|
172
|
-
break if @@local_match[i].to_i != server_match[i].to_i
|
173
|
-
score += 1
|
174
|
-
end
|
175
|
-
end
|
176
|
-
score
|
177
|
-
end
|
178
|
-
|
179
|
-
############################
|
180
|
-
protected
|
181
|
-
|
182
|
-
# Logging instance for this class
|
183
|
-
include SemanticLogger::Loggable
|
184
|
-
|
185
|
-
# Lazy initialize Doozer Client Connection pool
|
186
|
-
sync_cattr_reader :doozer_pool do
|
187
|
-
GenePool.new(
|
188
|
-
:name =>"Doozer Connection Pool",
|
189
|
-
:pool_size => 5,
|
190
|
-
:timeout => 30,
|
191
|
-
:warn_timeout => 5,
|
192
|
-
:idle_timeout => 600,
|
193
|
-
:logger => logger,
|
194
|
-
:close_proc => :close
|
195
|
-
) do
|
196
|
-
Doozer::Client.new(doozer_config)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
# Fetch the all registry information from Doozer and sets the internal registry
|
201
|
-
# Also starts the monitoring thread to keep the registry up to date
|
202
|
-
def self.start
|
203
|
-
# Populate internal registry from doozer server
|
204
|
-
# Holds a lock in this process on the service_registry so that only
|
205
|
-
# this thread will pre-populate the local copy of the registry
|
206
|
-
registry = ThreadSafe::Hash.new
|
207
|
-
revision = nil
|
208
|
-
doozer_pool.with_connection do |doozer|
|
209
|
-
revision = doozer.current_revision
|
210
|
-
doozer.walk(DOOZER_SERVICES_PATH, revision).each do |node|
|
211
|
-
service_info_change(registry, node.path, node.value)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
# Start monitoring thread to keep the registry up to date
|
215
|
-
@@monitor_thread = Thread.new { watch_registry(revision + 1) }
|
216
|
-
|
217
|
-
# Cleanup when process exits
|
218
|
-
at_exit do
|
219
|
-
if @@monitor_thread
|
220
|
-
@@monitor_thread.kill
|
221
|
-
@@monitor_thread.join
|
222
|
-
@@monitor_thread = nil
|
223
|
-
end
|
224
|
-
doozer_pool.close
|
225
|
-
end
|
226
|
-
registry
|
227
|
-
end
|
228
|
-
|
229
|
-
# Waits for any updates from Doozer and updates the internal service registry
|
230
|
-
def self.watch_registry(revision)
|
231
|
-
logger.info "Start monitoring #{DOOZER_SERVICES_PATH}"
|
232
|
-
# This thread must use its own dedicated doozer connection
|
233
|
-
doozer = Doozer::Client.new(doozer_config)
|
234
|
-
|
235
|
-
# Watch for any changes
|
236
|
-
doozer.watch(DOOZER_SERVICES_PATH, revision) do |node|
|
237
|
-
service_info_change(service_registry, node.path, node.value)
|
238
|
-
logger.trace "Updated registry", service_registry
|
239
|
-
end
|
240
|
-
logger.info "Stopping monitoring thread normally"
|
241
|
-
rescue Exception => exc
|
242
|
-
logger.error "Exception in monitoring thread", exc
|
243
|
-
ensure
|
244
|
-
doozer.close if doozer
|
245
|
-
logger.info "Stopped monitoring for changes in the doozer registry"
|
246
|
-
end
|
247
|
-
|
248
|
-
# Service information changed in doozer, so update internal registry
|
249
|
-
def self.service_info_change(registry, path, value)
|
250
|
-
# path from doozer: "/services/TutorialService/1/Development/127.0.0.1/9000"
|
251
|
-
e = path.split('/')
|
252
|
-
|
253
|
-
# Key: [String] 'name/version/region'
|
254
|
-
key = "#{e[2]}/#{e[3]}/#{e[4]}"
|
255
|
-
hostname, port = e[5], e[6]
|
256
|
-
|
257
|
-
if value.strip.size > 0
|
258
|
-
entry = MultiJson.load(value)
|
259
|
-
if entry['Registered']
|
260
|
-
add_server(registry, key, hostname, port)
|
261
|
-
else
|
262
|
-
# Service just de-registered
|
263
|
-
remove_server(registry, key, hostname, port, false)
|
264
|
-
end
|
265
|
-
else
|
266
|
-
# Service has stopped and needs to be removed
|
267
|
-
remove_server(registry, key, hostname, port, true)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
# Invoke any registered callbacks for the specific server
|
272
|
-
def self.server_removed(server)
|
273
|
-
if callbacks = @@on_server_removed_callbacks.delete(server)
|
274
|
-
callbacks.each do |block|
|
275
|
-
begin
|
276
|
-
logger.info "Calling callback for server: #{server}"
|
277
|
-
block.call(server)
|
278
|
-
rescue Exception => exc
|
279
|
-
logger.error("Exception during a callback for server: #{server}", exc)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
# :score: [Integer] Score
|
286
|
-
# :servers: [Array<String>] 'host:port', 'host:port'
|
287
|
-
ServerInfo = Struct.new(:score, :servers )
|
288
|
-
|
289
|
-
# Format of the internal services registry
|
290
|
-
# key: [String] "<name>/<version>/<region>"
|
291
|
-
# value: [ServiceInfo, ServiceInfo]
|
292
|
-
# Sorted by highest score first
|
293
|
-
|
294
|
-
# Add the host to the registry based on it's score
|
295
|
-
def self.add_server(registry, key, hostname, port)
|
296
|
-
server = "#{hostname}:#{port}"
|
297
|
-
logger.debug "#monitor Add/Update Service: #{key} => #{server.inspect}"
|
298
|
-
|
299
|
-
server_infos = (registry[key] ||= ThreadSafe::Array.new)
|
300
|
-
|
301
|
-
# If already present, then nothing to do
|
302
|
-
server_info = server_infos.find{|si| si.server == server}
|
303
|
-
return server_info if server_info
|
304
|
-
|
305
|
-
# Look for the same score with a different server
|
306
|
-
score = score_for_server(hostname)
|
307
|
-
if server_info = server_infos.find{|si| si.score == score}
|
308
|
-
server_info.servers << server
|
309
|
-
return server_info
|
310
|
-
end
|
311
|
-
|
312
|
-
# New score
|
313
|
-
servers = ThreadSafe::Array.new
|
314
|
-
servers << server
|
315
|
-
server_info = ServerInfo.new(score, servers)
|
316
|
-
|
317
|
-
# Insert into Array in order of score
|
318
|
-
if index = server_infos.find_index {|si| si.score <= score}
|
319
|
-
server_infos.insert(index, server_info)
|
320
|
-
else
|
321
|
-
server_infos << server_info
|
322
|
-
end
|
323
|
-
server_info
|
324
|
-
end
|
325
|
-
|
326
|
-
# Remove the host from the registry based
|
327
|
-
# Returns the server instance if it was removed
|
328
|
-
def self.remove_server(registry, key, hostname, port, notify)
|
329
|
-
server = "#{hostname}:#{port}"
|
330
|
-
logger.debug "Remove Service: #{key} => #{server.inspect}"
|
331
|
-
server_info = nil
|
332
|
-
if server_infos = registry[key]
|
333
|
-
server_infos.each do |si|
|
334
|
-
if si.servers.delete(server)
|
335
|
-
server_info = si
|
336
|
-
break
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
# Found server
|
341
|
-
if server_info
|
342
|
-
# Cleanup if no more servers in server list
|
343
|
-
server_infos.delete(server_info) if server_info.servers.size == 0
|
344
|
-
|
345
|
-
# Cleanup if no more server infos
|
346
|
-
registry.delete(key) if server_infos.size == 0
|
347
|
-
|
348
|
-
server_removed(server) if notify
|
349
|
-
end
|
350
|
-
end
|
351
|
-
server_info
|
352
|
-
end
|
353
|
-
|
354
|
-
# Check doozer for servers matching supplied criteria
|
355
|
-
# Code unused, consider deleting
|
356
|
-
def self.remote_servers_for(name, version='*', region='Development')
|
357
|
-
if version != '*'
|
358
|
-
registered_implementers(name, version, region).map do |host|
|
359
|
-
service = host['Config']['ServiceAddr']
|
360
|
-
"#{service['IPAddress']}:#{service['Port']}"
|
361
|
-
end
|
362
|
-
else
|
363
|
-
# Find the highest version of any particular service
|
364
|
-
versions = {}
|
365
|
-
registered_implementers(name, version, region).each do |host|
|
366
|
-
service = host['Config']['ServiceAddr']
|
367
|
-
(versions[version.to_i] ||= []) << "#{service['IPAddress']}:#{service['Port']}"
|
368
|
-
end
|
369
|
-
# Return the servers implementing the highest version number
|
370
|
-
versions.sort.last.last
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
end
|
375
|
-
end
|
data/test/doozer_client_test.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# Allow test to be run in-place without requiring a gem install
|
2
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'test/unit'
|
6
|
-
require 'shoulda'
|
7
|
-
require 'ruby_skynet/doozer/client'
|
8
|
-
|
9
|
-
# NOTE:
|
10
|
-
# This test assumes that doozerd is running locally on the default port of 8046
|
11
|
-
|
12
|
-
# Unit Test for RubySkynet::Doozer::Client
|
13
|
-
class DoozerClientTest < Test::Unit::TestCase
|
14
|
-
context RubySkynet::Doozer::Client do
|
15
|
-
|
16
|
-
context "without server" do
|
17
|
-
should "raise exception when cannot reach doozer server after 5 retries" do
|
18
|
-
exception = assert_raise ResilientSocket::ConnectionFailure do
|
19
|
-
RubySkynet::Doozer::Client.new(
|
20
|
-
# Bad server address to test exception is raised
|
21
|
-
:server => 'localhost:9999',
|
22
|
-
:connect_retry_interval => 0.1,
|
23
|
-
:connect_retry_count => 5)
|
24
|
-
end
|
25
|
-
assert_match /After 5 connection attempts to host 'localhost:9999': Errno::ECONNREFUSED/, exception.message
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
context "with client connection" do
|
31
|
-
setup do
|
32
|
-
@client = RubySkynet::Doozer::Client.new(:server => 'localhost:8046')
|
33
|
-
end
|
34
|
-
|
35
|
-
def teardown
|
36
|
-
if @client
|
37
|
-
@client.close
|
38
|
-
@client.delete('/test/foo')
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
should "return current revision" do
|
43
|
-
assert @client.current_revision >= 0
|
44
|
-
end
|
45
|
-
|
46
|
-
should "successfully set and get data" do
|
47
|
-
new_revision = @client.set('/test/foo', 'value')
|
48
|
-
result = @client.get('/test/foo')
|
49
|
-
assert_equal 'value', result.value
|
50
|
-
assert_equal new_revision, result.rev
|
51
|
-
end
|
52
|
-
|
53
|
-
should "successfully set and get data using array operators" do
|
54
|
-
@client['/test/foo'] = 'value2'
|
55
|
-
result = @client['/test/foo']
|
56
|
-
assert_equal 'value2', result
|
57
|
-
end
|
58
|
-
|
59
|
-
should "fetch directories in a path" do
|
60
|
-
@path = '/'
|
61
|
-
count = 0
|
62
|
-
until @client.directory(@path, count).nil?
|
63
|
-
count += 1
|
64
|
-
end
|
65
|
-
assert count > 0
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
data/test/registry_test.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
# Allow test to be run in-place without requiring a gem install
|
2
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'test/unit'
|
6
|
-
require 'shoulda'
|
7
|
-
require 'mocha/setup'
|
8
|
-
require 'ruby_skynet'
|
9
|
-
|
10
|
-
# Register an appender if one is not already registered
|
11
|
-
if SemanticLogger::Logger.appenders.size == 0
|
12
|
-
SemanticLogger::Logger.default_level = :trace
|
13
|
-
SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
|
14
|
-
end
|
15
|
-
|
16
|
-
# Unit Test
|
17
|
-
class RegistryTest < Test::Unit::TestCase
|
18
|
-
context 'RubySkynet::Service' do
|
19
|
-
|
20
|
-
setup do
|
21
|
-
@service_name = 'MyRegistryService'
|
22
|
-
@version = 5
|
23
|
-
@region = 'RegistryTest'
|
24
|
-
@hostname = '127.0.0.1'
|
25
|
-
@port = 2100
|
26
|
-
@service_key = "/services/#{@service_name}/#{@version}/#{@region}/#{@hostname}/#{@port}"
|
27
|
-
end
|
28
|
-
|
29
|
-
context "without a registered service" do
|
30
|
-
should "not be in doozer" do
|
31
|
-
RubySkynet::Registry.send(:doozer_pool).with_connection do |doozer|
|
32
|
-
assert_equal '', doozer[@service_key]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
context "with a registered service" do
|
38
|
-
setup do
|
39
|
-
RubySkynet::Registry.register_service(@service_name, @version, @region, @hostname, @port)
|
40
|
-
# Allow time for doozer callback that service was registered
|
41
|
-
sleep 0.1
|
42
|
-
end
|
43
|
-
|
44
|
-
teardown do
|
45
|
-
RubySkynet::Registry.deregister_service(@service_name, @version, @region, @hostname, @port)
|
46
|
-
# Allow time for doozer callback that service was deregistered
|
47
|
-
sleep 0.1
|
48
|
-
# No servers should be in the local registry
|
49
|
-
assert_equal nil, RubySkynet::Registry.servers_for(@service_name, @version, @region)
|
50
|
-
end
|
51
|
-
|
52
|
-
should "find server using exact match" do
|
53
|
-
assert servers = RubySkynet::Registry.servers_for(@service_name, @version, @region)
|
54
|
-
assert_equal 1, servers.size
|
55
|
-
assert_equal "#{@hostname}:#{@port}", servers.first
|
56
|
-
end
|
57
|
-
|
58
|
-
should "find server using * version match" do
|
59
|
-
assert servers = RubySkynet::Registry.servers_for(@service_name, '*', @region)
|
60
|
-
assert_equal 1, servers.size
|
61
|
-
assert_equal "#{@hostname}:#{@port}", servers.first
|
62
|
-
end
|
63
|
-
|
64
|
-
should "return nil when service not found" do
|
65
|
-
assert_equal nil, RubySkynet::Registry.servers_for('MissingService', @version, @region)
|
66
|
-
end
|
67
|
-
|
68
|
-
should "return nil when version not found" do
|
69
|
-
assert_equal nil, RubySkynet::Registry.servers_for(@service_name, @version+1, @region)
|
70
|
-
end
|
71
|
-
|
72
|
-
should "return nil when region not found" do
|
73
|
-
assert_equal nil, RubySkynet::Registry.servers_for(@service_name, @version, 'OtherRegion')
|
74
|
-
end
|
75
|
-
|
76
|
-
should "be in doozer" do
|
77
|
-
RubySkynet::Registry.send(:doozer_pool).with_connection do |doozer|
|
78
|
-
assert_equal true, doozer[@service_key].length > 20
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context "scoring" do
|
84
|
-
[
|
85
|
-
['192.168.11.0', 4 ],
|
86
|
-
['192.168.11.10', 3 ],
|
87
|
-
['192.168.10.0', 2 ],
|
88
|
-
['192.5.10.0', 1 ],
|
89
|
-
['10.0.11.0', 0 ],
|
90
|
-
].each do |test|
|
91
|
-
should "handle score #{test[1]}" do
|
92
|
-
RubySkynet.stubs(:local_ip_address).returns("192.168.11.0")
|
93
|
-
assert_equal test[1], RubySkynet::Registry.score_for_server(test[0]), "Local: #{RubySkynet::Common.local_ip_address} Server: #{test[0]} Score: #{test[1]}"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
end
|