ruby_skynet 0.5.0 → 0.6.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.
- 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
|