ruby_skynet 0.8.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 016858cd256536862a6f4942021dc1b013cbaacc
4
- data.tar.gz: 4cb428343484df4c14c5576579e02eb01c1bc215
3
+ metadata.gz: 71af05d7950d049061c39abe50a23dd1fe02a51d
4
+ data.tar.gz: b312ef155c2aacea545f434d4d9e38348bc94ac5
5
5
  SHA512:
6
- metadata.gz: 5255162acd54ef3e7123c4034b4495c8d4be16cce0c9e044e08ffe1f40a34367c3940dfa6f8421b4ac7025394eae3ede543967e46f06316fd424bd23b948ccc7
7
- data.tar.gz: 8e468e69a39448f6fc0ab61f0fca2cb99740c0d568e4f4950e545bb75b40758f9ab2218ec9a014346aa2eff843a84495e2f609ee4b0857d7fadad9e18afd79bc
6
+ metadata.gz: 240897f81ded9f668da49ed7280b378bbe92d17e819e9c795a47affd7e6996a972d61168f4b9c104b8a21b4a01937523d5104661590ab82005de8fa1f39e6c38
7
+ data.tar.gz: 423409dbf2038a5723438004d451a28b4493edd85eadbf6cd239a0190c11b508ac56eb36be29872be28c2c6b057c31f7e2ba099912153b5cebd0384daf46a517
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  group :test do
4
4
  gem "shoulda"
@@ -9,11 +9,13 @@ gem "semantic_logger", ">= 2.1"
9
9
  gem "resilient_socket"
10
10
  # Doozer Client
11
11
  gem "ruby_doozer"
12
+ # Zookeeper Client
13
+ gem "zookeeper"
12
14
  # Thread Safe Hash and Array
13
15
  gem "thread_safe"
14
16
  # Connection pool
15
17
  gem "gene_pool"
16
- # For looking up Service entries in Doozer
18
+ # For looking up Service entries in Service Registry
17
19
  gem "multi_json"
18
20
  # Wire format when communicating with services
19
21
  gem "bson"
data/Gemfile.lock CHANGED
@@ -1,19 +1,19 @@
1
1
  GEM
2
- remote: http://rubygems.org/
2
+ remote: https://rubygems.org/
3
3
  specs:
4
- activesupport (3.2.13)
5
- i18n (= 0.6.1)
6
- multi_json (~> 1.0)
7
- atomic (1.1.9)
8
- atomic (1.1.9-java)
9
- bson (1.8.6)
10
- bson (1.8.6-java)
11
- bson_ext (1.8.6)
12
- bson (~> 1.8.6)
4
+ activesupport (4.0.0)
5
+ i18n (~> 0.6, >= 0.6.4)
6
+ minitest (~> 4.2)
7
+ multi_json (~> 1.3)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 0.3.37)
10
+ atomic (1.1.10-java)
11
+ bson (1.9.0-java)
13
12
  gene_pool (1.3.0)
14
- i18n (0.6.1)
15
- multi_json (1.7.6)
16
- rake (10.0.4)
13
+ i18n (0.6.4)
14
+ minitest (4.7.5)
15
+ multi_json (1.7.7)
16
+ rake (10.1.0)
17
17
  resilient_socket (0.5.0)
18
18
  semantic_logger (>= 2.1)
19
19
  ruby_doozer (0.7.1)
@@ -30,16 +30,21 @@ GEM
30
30
  shoulda (3.5.0)
31
31
  shoulda-context (~> 1.0, >= 1.0.1)
32
32
  shoulda-matchers (>= 1.4.1, < 3.0)
33
- shoulda-context (1.1.2)
34
- shoulda-matchers (2.1.0)
33
+ shoulda-context (1.1.4)
34
+ shoulda-matchers (2.2.0)
35
35
  activesupport (>= 3.0.0)
36
+ slyphon-log4j (1.2.15)
37
+ slyphon-zookeeper_jar (3.3.5-java)
36
38
  sync_attr (1.0.0)
37
39
  thread_safe (0.1.0)
38
40
  atomic
41
+ tzinfo (0.3.37)
42
+ zookeeper (1.4.4-java)
43
+ slyphon-log4j (= 1.2.15)
44
+ slyphon-zookeeper_jar (= 3.3.5)
39
45
 
40
46
  PLATFORMS
41
47
  java
42
- ruby
43
48
 
44
49
  DEPENDENCIES
45
50
  bson
@@ -52,3 +57,4 @@ DEPENDENCIES
52
57
  semantic_logger (>= 2.1)
53
58
  shoulda
54
59
  thread_safe
60
+ zookeeper
data/README.md CHANGED
@@ -74,23 +74,27 @@ client = Echo.new
74
74
  p client.echo(:hello => 'world')
75
75
  ```
76
76
 
77
- ### Architecture
78
-
79
- ruby_skynet implements its own doozer client which has been tested against
80
- the doozer fork: https://github.com/4ad/doozerd.
81
- The doozer client uses the active [ruby_protobuf](https://github.com/macks/ruby-protobuf)
82
- project for marshaling data for communicating with doozer
83
-
84
77
  ### Dependencies
85
78
 
86
- - Ruby MRI 1.8.7 (or above), Ruby 1.9.3, Or JRuby 1.6.3 (or above)
79
+ - Ruby 1.8.7, Ruby 1.9.3, Ruby 2.0.0, or JRuby 1.6.3 (or higher)
87
80
  - [SemanticLogger](http://github.com/ClarityServices/semantic_logger)
88
81
  - [ResilientSocket](https://github.com/ClarityServices/resilient_socket)
89
- - [ruby_protobuf](https://github.com/macks/ruby-protobuf)
90
82
  - [multi_json](https://github.com/intridea/multi_json)
91
83
 
84
+ One of the following Service Registry Implementations
85
+ - ZooKeeper Ruby Client [zk](https://github.com/slyphon/zk)
86
+ - [ruby_doozer](http://github.com/skynetservices/ruby_doozer)
87
+
92
88
  ### Install
93
89
 
90
+ Installing for a ZooKeeper centralized service registry - Recommended
91
+
92
+ gem install zk
93
+ gem install ruby_skynet
94
+
95
+ OR, Installing for a Doozer centralized service registry
96
+
97
+ gem install ruby_doozer
94
98
  gem install ruby_skynet
95
99
 
96
100
  Development
data/Rakefile CHANGED
@@ -28,9 +28,8 @@ task :gem do |t|
28
28
  spec.add_dependency 'resilient_socket', '>= 0.5.0'
29
29
  spec.add_dependency 'bson', '>= 1.5.2'
30
30
  spec.add_dependency 'gene_pool', '>= 1.3.0'
31
+ spec.add_dependency 'zookeeper', '>= 1.4.4'
31
32
  spec.add_dependency 'sync_attr', '>= 1.0.0'
32
- spec.add_dependency 'ruby_doozer', '>= 0.7.0'
33
- spec.add_dependency 'gene_pool', '>= 1.3.0'
34
33
  end
35
34
  Gem::Package.build gemspec
36
35
  end
@@ -18,24 +18,20 @@
18
18
  # by remote Skynet clients
19
19
  # Note: Must be an IP address, not the hostname
20
20
  #
21
- # Doozer Configuration Parameters
22
- # :doozer
21
+ # Registry settings
22
+ # :registry
23
23
  # :servers [Array of String]
24
24
  # Array of URL's of doozer servers to connect to with port numbers
25
25
  # ['server1:2000', 'server2:2000']
26
26
  #
27
- # The second server will only be attempted once the first server
28
- # cannot be connected to or has timed out on connect
29
- # A read failure or timeout will not result in switching to the second
30
- # server, only a connection failure or during an automatic reconnect
27
+ # :connect_timeout [Float]
28
+ # Time in seconds to timeout when trying to connect to the server
31
29
  #
30
+ # Additional Doozer configuration options
32
31
  # :read_timeout [Float]
33
32
  # Time in seconds to timeout on read
34
33
  # Can be overridden by supplying a timeout in the read call
35
34
  #
36
- # :connect_timeout [Float]
37
- # Time in seconds to timeout when trying to connect to the server
38
- #
39
35
  # :connect_retry_count [Fixnum]
40
36
  # Number of times to retry connecting when a connection fails
41
37
  #
@@ -49,6 +45,10 @@
49
45
  # Select a server in the order supplied in the array, with the first
50
46
  # having the highest priority. The second server will only be connected
51
47
  # to if the first server is unreachable
48
+ # The second server will only be attempted once the first server
49
+ # cannot be connected to or has timed out on connect
50
+ # A read failure or timeout will not result in switching to the second
51
+ # server, only a connection failure or during an automatic reconnect
52
52
  # :random
53
53
  # Randomly select a server from the list every time a connection
54
54
  # is established, including during automatic connection recovery.
@@ -60,19 +60,23 @@
60
60
  defaults: &defaults
61
61
  :services_path: app/services
62
62
  :server_port: 2000
63
- :doozer:
63
+
64
+ # Registry Settings
65
+ :registry:
64
66
  :servers:
65
- - 127.0.0.1:8046
66
- :read_timeout: 5
67
- :connect_timeout: 3
68
- :connect_retry_count: 10
69
- :connect_retry_interval: 0.5
70
- :server_selector: :random
71
- # Doozer Connection Pool settings
72
- :pool_size: 10
73
- :pool_timeout: 30
74
- :pool_warn_timeout: 2
75
- :pool_idle_timeout: 600
67
+ - 127.0.0.1:2181
68
+ :connect_timeout: 3
69
+
70
+ # Additional Doozer configuration settings
71
+ # :read_timeout: 5
72
+ # :connect_retry_count: 10
73
+ # :connect_retry_interval: 0.5
74
+ # :server_selector: :random
75
+ # # Doozer Connection Pool settings
76
+ # :pool_size: 10
77
+ # :pool_timeout: 30
78
+ # :pool_warn_timeout: 2
79
+ # :pool_idle_timeout: 600
76
80
 
77
81
  development:
78
82
  <<: *defaults
@@ -88,7 +88,7 @@ module RubySkynet
88
88
  retries = 0
89
89
  # If it cannot connect to a server, try a different server
90
90
  begin
91
- Connection.with_connection(::RubySkynet.services.server_for(skynet_name, skynet_version, skynet_region), connection_params) do |connection|
91
+ Connection.with_connection(::RubySkynet.service_registry.server_for(skynet_name, skynet_version, skynet_region), connection_params) do |connection|
92
92
  connection.rpc_call(request_id, skynet_name, method_name, parameters)
93
93
  end
94
94
  rescue ResilientSocket::ConnectionFailure => exc
@@ -235,7 +235,7 @@ module RubySkynet
235
235
  end
236
236
 
237
237
  # Cleanup corresponding connection pool when a server terminates
238
- RubySkynet.services.on_server_removed(server) do
238
+ RubySkynet.service_registry.on_server_removed(server) do
239
239
  pool = @@connection_pools.delete(server)
240
240
  # Cannot close all the connections since they could still be in use
241
241
  pool.remove_idle(0) if pool
@@ -15,13 +15,18 @@ namespace :ruby_skynet do
15
15
  RubySkynet.configure!(cfg_file, environment)
16
16
  end
17
17
 
18
- # Connect to doozer
18
+ # Connect to services registry
19
19
  RubySkynet.services
20
20
 
21
21
  RubySkynet::Server.load_services
22
22
 
23
23
  # Start the server
24
24
  RubySkynet::Server.start
25
+
26
+ at_exit do
27
+ RubySkynet::Server.stop
28
+ end
29
+
25
30
  RubySkynet::Server.wait_until_server_stops
26
31
  end
27
32
 
@@ -0,0 +1,17 @@
1
+ # Define RubySkynet::Registry based on whether the ZooKeeper or Doozer gem is present
2
+ module RubySkynet
3
+ begin
4
+ require 'zookeeper'
5
+ require 'zookeeper/client'
6
+ # Monkey-patch so that the Zookeeper JRuby code can handle nil values in Zookeeper
7
+ require 'ruby_skynet/zookeeper/extensions/java_base' if defined?(::JRUBY_VERSION)
8
+ Registry = RubySkynet::Zookeeper::Registry
9
+ rescue LoadError
10
+ begin
11
+ require 'ruby_doozer'
12
+ rescue LoadError
13
+ raise LoadError, "Must gem install either 'zookeeper' or 'ruby_doozer'. 'zookeeper' is recommended"
14
+ end
15
+ Registry = Doozer::Registry
16
+ end
17
+ end
@@ -45,51 +45,28 @@ module RubySkynet
45
45
  @@local_ip_address = local_ip_address
46
46
  end
47
47
 
48
- # Returns the services registry consisting of service names
48
+ # Returns the services registry which holds the service names
49
49
  # and the hosts on which they are running
50
- sync_cattr_reader :services do
51
- ServiceRegistry.new(
52
- :root_path => "/services",
53
- :doozer => doozer_config
54
- )
50
+ #
51
+ # By default it connects to a local ZooKeeper instance
52
+ # Use .configure! to supply a configuration file with any other settings
53
+ sync_cattr_reader :service_registry do
54
+ ServiceRegistry.new(:root => '/services')
55
55
  end
56
56
 
57
- # Default doozer configuration
58
- # To replace this default, set the config as follows:
59
- # RubySkynet::Client.doozer_config = { .... }
60
- #
61
- # :servers [Array of String]
62
- # Array of URL's of doozer servers to connect to with port numbers
63
- # ['server1:2000', 'server2:2000']
64
- #
65
- # The second server will only be attempted once the first server
66
- # cannot be connected to or has timed out on connect
67
- # A read failure or timeout will not result in switching to the second
68
- # server, only a connection failure or during an automatic reconnect
69
- #
70
- # :read_timeout [Float]
71
- # Time in seconds to timeout on read
72
- # Can be overridden by supplying a timeout in the read call
73
- #
74
- # :connect_timeout [Float]
75
- # Time in seconds to timeout when trying to connect to the server
76
- #
77
- # :connect_retry_count [Fixnum]
78
- # Number of times to retry connecting when a connection fails
79
- #
80
- # :connect_retry_interval [Float]
81
- # Number of seconds between connection retry attempts after the first failed attempt
82
- sync_cattr_accessor :doozer_config do
83
- {
84
- :servers => ['127.0.0.1:8046'],
85
- :read_timeout => 5,
86
- :connect_timeout => 3,
87
- :connect_retry_interval => 1,
88
- :connect_retry_count => 30
89
- }
57
+ # Set the services registry
58
+ # It is recommended to call RubySkynet.configure! rather than calling this
59
+ # method directly
60
+ def self.service_registry=(service_registry)
61
+ @@service_registry = service_registry
90
62
  end
91
63
 
92
- # Load the Encryption Configuration from a YAML file
64
+ # DEPRECATED - Use RubySkynet.service_registry
65
+ def self.services
66
+ @@service_registry
67
+ end
68
+
69
+ # Load the Configuration information from a YAML file
93
70
  # filename:
94
71
  # Name of file to read.
95
72
  # Mandatory for non-Rails apps
@@ -101,16 +78,38 @@ module RubySkynet
101
78
  config_file = filename.nil? ? Rails.root.join('config', 'ruby_skynet.yml') : Pathname.new(filename)
102
79
  raise "ruby_skynet config not found. Create a config file at: config/ruby_skynet.yml" unless config_file.file?
103
80
 
104
- cfg = YAML.load(ERB.new(File.new(config_file).read).result)[environment || Rails.env]
105
- raise("Environment #{Rails.env} not defined in config/ruby_skynet.yml") unless cfg
81
+ config = YAML.load(ERB.new(File.new(config_file).read).result)[environment || Rails.env]
82
+ raise("Environment #{Rails.env} not defined in config/ruby_skynet.yml") unless config
83
+
84
+ @@config = config.dup
85
+
86
+ RubySkynet.region = config.delete(:region) || 'Development'
87
+ RubySkynet.services_path = config.delete(:services_path) || 'app/services'
88
+ RubySkynet.server_port = config.delete(:server_port) || 2000
89
+ RubySkynet.local_ip_address = config.delete(:local_ip_address) || Common::local_ip_address
106
90
 
107
- RubySkynet.region = cfg.delete(:region) if [:region]
108
- RubySkynet.services_path = cfg.delete(:services_path) if [:services_path]
109
- RubySkynet.server_port = cfg.delete(:server_port) if [:server_port]
110
- RubySkynet.local_ip_address = cfg.delete(:local_ip_address) if [:local_ip_address]
111
- RubySkynet.doozer_config = cfg.delete(:doozer) if [:doozer]
91
+ # Extract just the zookeeper or doozer configuration element
92
+ key = config[:zookeeper] ? :zookeeper : :doozer
93
+ RubySkynet.service_registry = ServiceRegistry.new(
94
+ :root => '/services',
95
+ key => config.delete(key)
96
+ )
97
+
98
+ config.each_pair {|k,v| RubySkynet::Server.logger.warn "Ignoring unknown RubySkynet config option #{k} => #{v}"}
99
+ end
112
100
 
113
- cfg.each_pair {|k,v| RubySkynet::Server.logger.warn "Ignoring unknown RubySkynet config option #{k} => #{v}"}
101
+ # Returns an instance of RubySkynet::Zookeeper::CachedRegistry or RubyDoozer::CachedRegistry
102
+ # based on which was loaded in RubySkynet.configure!
103
+ def self.new_cache_registry(root)
104
+ # Load config
105
+ service_registry
106
+
107
+ if zookeeper = @@config[:zookeeper]
108
+ RubySkynet::Zookeeper::CachedRegistry.new(:root => root, :zookeeper => zookeeper)
109
+ else
110
+ raise "How did we get here", @@config
111
+ Doozer::CachedRegistry.new(:root => root, :doozer => @@config[:doozer])
112
+ end
114
113
  end
115
114
 
116
115
  end
@@ -17,7 +17,7 @@ module RubySkynet
17
17
  @@server ||= new(start_port, ip_address)
18
18
 
19
19
  # Stop the skynet server on shutdown
20
- # To ensure services are de-registered in doozer
20
+ # To ensure services are de-registered in the service registry
21
21
  at_exit do
22
22
  ::RubySkynet::Server.stop
23
23
  end
@@ -126,6 +126,18 @@ module RubySkynet
126
126
  @listener_thread.join
127
127
  end
128
128
 
129
+ # Registers a Service Class as being available at this server
130
+ def register_service(klass)
131
+ logger.info "Registering Service: #{klass.name} with name: #{klass.skynet_name}"
132
+ ::RubySkynet.service_registry.register_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
133
+ end
134
+
135
+ # De-register service from this server
136
+ def deregister_service(klass)
137
+ logger.info "De-registering Service: #{klass.name} with name: #{klass.skynet_name}"
138
+ ::RubySkynet.service_registry.deregister_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
139
+ end
140
+
129
141
  ############################################################################
130
142
  protected
131
143
 
@@ -204,18 +216,6 @@ module RubySkynet
204
216
  logger.debug "Disconnected from the client"
205
217
  end
206
218
 
207
- # Registers a Service Class as being available at this server
208
- def register_service(klass)
209
- logger.info "Registering Service: #{klass.name} with name: #{klass.skynet_name}"
210
- ::RubySkynet.services.register_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
211
- end
212
-
213
- # De-register service from this server
214
- def deregister_service(klass)
215
- logger.info "De-registering Service: #{klass.name} with name: #{klass.skynet_name}"
216
- ::RubySkynet.services.deregister_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
217
- end
218
-
219
219
  # Called for each message received from the client
220
220
  # Returns a Hash that is sent back to the caller
221
221
  def on_message(skynet_name, method, params)
@@ -16,7 +16,7 @@ module RubySkynet
16
16
  include SemanticLogger::Loggable
17
17
  end
18
18
  # Register the service with the Server
19
- # The server will publish the server to Doozer when the server is running
19
+ # The server will publish the server to services registry when the server is running
20
20
  Server.register_service(base)
21
21
  end
22
22
 
@@ -1,8 +1,7 @@
1
- require 'sync_attr'
1
+ require 'semantic_logger'
2
2
  require 'thread_safe'
3
3
  require 'gene_pool'
4
4
  require 'resolv'
5
- require 'ruby_doozer'
6
5
 
7
6
  #
8
7
  # RubySkynet Sevices Registry
@@ -11,71 +10,37 @@ require 'ruby_doozer'
11
10
  # all services and which servers they are available on.
12
11
  #
13
12
  module RubySkynet
14
- class ServiceRegistry < RubyDoozer::Registry
15
- include SyncAttr
13
+ class ServiceRegistry
16
14
  include SemanticLogger::Loggable
17
15
 
18
- IPV4_REG_EXP = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
19
-
20
- # Returns [Integer] the score for the supplied ip_address
21
- # Score currently ranges from 0 to 4 with 4 being the best score
22
- # If the IP address does not match an IP v4 address a DNS lookup will
23
- # be performed
24
- def self.score_for_server(ip_address, local_ip_address)
25
- score = 0
26
- # Each matching element adds 1 to the score
27
- # 192.168. 0. 0
28
- # 1
29
- # 1
30
- # 1
31
- # 1
32
- server_match = IPV4_REG_EXP.match(ip_address) || IPV4_REG_EXP.match(Resolv::DNS.new.getaddress(ip_address).to_s)
33
- if server_match
34
- local_match = IPV4_REG_EXP.match(local_ip_address)
35
- score = 0
36
- (1..4).each do |i|
37
- break if local_match[i].to_i != server_match[i].to_i
38
- score += 1
39
- end
40
- end
41
- score
42
- end
43
-
44
16
  # Create a service registry
45
17
  # See: RubyDoozer::Registry for the parameters
46
18
  def initialize(params)
47
- super
48
-
49
19
  # Registry has the following format
50
20
  # Key: [String] 'name/version/region'
51
21
  # Value: [Array<String>] 'host:port', 'host:port'
52
- @registry = ThreadSafe::Hash.new
53
-
54
- path = "#{@root_path}/**"
55
- doozer_pool.with_connection do |doozer|
56
- @current_revision = doozer.current_revision
57
- # Fetch all the configuration information from Doozer and set the internal copy
58
- doozer.walk(path, @current_revision) do |path, value|
59
- service_info_changed(relative_key(path), value)
60
- end
61
- end
62
-
63
- # Start monitoring thread
64
- monitor_thread
22
+ @cache = ThreadSafe::Hash.new
65
23
 
24
+ # Supply block to load the current keys from the Registry
25
+ @registry = Registry.new(params) do |key, value|
26
+ service_info_changed(key, value)
27
+ end
66
28
  # Register Callbacks
67
- on_update {|path, value| service_info_changed(path, value) }
68
- on_delete {|path, value| service_info_changed(path) }
29
+ @registry.on_update {|path, value| service_info_changed(path, value) }
30
+ @registry.on_delete {|path| service_info_changed(path) }
31
+
32
+ # Zookeeper Registry also supports on_create
33
+ @registry.on_create {|path, value| service_info_changed(path, value) } if @registry.respond_to?(:on_create)
69
34
  end
70
35
 
71
36
  # Returns the Service Registry as a Hash
72
37
  def to_h
73
- @registry.dup
38
+ @cache.dup
74
39
  end
75
40
 
76
41
  # Register the supplied service at this Skynet Server host and Port
77
42
  def register_service(name, version, region, hostname, port)
78
- self["#{name}/#{version}/#{region}/#{hostname}/#{port}"] = {
43
+ @registry["#{name}/#{version}/#{region}/#{hostname}/#{port}"] = {
79
44
  "Config" => {
80
45
  "UUID" => "#{hostname}:#{port}-#{$$}-#{name}-#{version}",
81
46
  "Name" => name,
@@ -93,7 +58,7 @@ module RubySkynet
93
58
 
94
59
  # Deregister the supplied service from the Registry
95
60
  def deregister_service(name, version, region, hostname, port)
96
- delete("#{name}/#{version}/#{region}/#{hostname}/#{port}")
61
+ @registry.delete("#{name}/#{version}/#{region}/#{hostname}/#{port}")
97
62
  end
98
63
 
99
64
  # Return a server that implements the specified service
@@ -113,14 +78,14 @@ module RubySkynet
113
78
  if version == '*'
114
79
  # Find the highest version for the named service in this region
115
80
  version = -1
116
- @registry.keys.each do |key|
81
+ @cache.keys.each do |key|
117
82
  if match = key.match(/#{name}\/(\d+)\/#{region}/)
118
83
  ver = match[1].to_i
119
84
  version = ver if ver > version
120
85
  end
121
86
  end
122
87
  end
123
- if server_infos = @registry["#{name}/#{version}/#{region}"]
88
+ if server_infos = @cache["#{name}/#{version}/#{region}"]
124
89
  server_infos.first.servers
125
90
  end
126
91
  end
@@ -138,6 +103,7 @@ module RubySkynet
138
103
 
139
104
  # Service information changed in doozer, so update internal registry
140
105
  def service_info_changed(path, value=nil)
106
+ logger.info("service_info_changed: #{path}", value)
141
107
  # path: "TutorialService/1/Development/127.0.0.1/9000"
142
108
  e = path.split('/')
143
109
 
@@ -171,7 +137,7 @@ module RubySkynet
171
137
  def add_server(key, hostname, port)
172
138
  server = "#{hostname}:#{port}"
173
139
 
174
- server_infos = (@registry[key] ||= ThreadSafe::Array.new)
140
+ server_infos = (@cache[key] ||= ThreadSafe::Array.new)
175
141
 
176
142
  # If already present, then nothing to do
177
143
  server_info = server_infos.find{|si| si.servers.include?(server)}
@@ -205,7 +171,7 @@ module RubySkynet
205
171
  server = "#{hostname}:#{port}"
206
172
  logger.info "Service: #{key} stopped running at #{server}"
207
173
  server_info = nil
208
- if server_infos = @registry[key]
174
+ if server_infos = @cache[key]
209
175
  server_infos.each do |si|
210
176
  if si.servers.delete(server)
211
177
  server_info = si
@@ -219,7 +185,7 @@ module RubySkynet
219
185
  server_infos.delete(server_info) if server_info.servers.size == 0
220
186
 
221
187
  # Cleanup if no more server infos
222
- @registry.delete(key) if server_infos.size == 0
188
+ @cache.delete(key) if server_infos.size == 0
223
189
 
224
190
  server_removed(server) if notify
225
191
  end
@@ -241,5 +207,32 @@ module RubySkynet
241
207
  end
242
208
  end
243
209
 
210
+ IPV4_REG_EXP = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
211
+
212
+ # Returns [Integer] the score for the supplied ip_address
213
+ # Score currently ranges from 0 to 4 with 4 being the best score
214
+ # If the IP address does not match an IP v4 address a DNS lookup will
215
+ # be performed
216
+ def self.score_for_server(ip_address, local_ip_address)
217
+ ip_address = '127.0.0.1' if ip_address == 'localhost'
218
+ score = 0
219
+ # Each matching element adds 1 to the score
220
+ # 192.168. 0. 0
221
+ # 1
222
+ # 1
223
+ # 1
224
+ # 1
225
+ server_match = IPV4_REG_EXP.match(ip_address) || IPV4_REG_EXP.match(Resolv::DNS.new.getaddress(ip_address).to_s)
226
+ if server_match
227
+ local_match = IPV4_REG_EXP.match(local_ip_address)
228
+ score = 0
229
+ (1..4).each do |i|
230
+ break if local_match[i].to_i != server_match[i].to_i
231
+ score += 1
232
+ end
233
+ end
234
+ score
235
+ end
236
+
244
237
  end
245
238
  end
@@ -1,3 +1,3 @@
1
1
  module RubySkynet #:nodoc
2
- VERSION = "0.8.1"
2
+ VERSION = "1.0.0"
3
3
  end