ruby_skynet 0.8.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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