ruby_skynet 2.0.0.rc1 → 2.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: bf65f91389e27d97e04be4be8a1ef49700bb245b
4
- data.tar.gz: 6b26fea72828375f49fff798c931744951747698
3
+ metadata.gz: f4b7ec3477060f1215627b808ee1f2962a4ad4ae
4
+ data.tar.gz: 4cf98cc577399f3d0521a84f5207322e436b4f3e
5
5
  SHA512:
6
- metadata.gz: 20a409544353b4634fde2fb83595e0998ef808383591ad08692bf5422d6bbf07995e1bf781b5a698ceeb7d1e1ec18d840eb8ef98b9f6939d27273a8c9324574c
7
- data.tar.gz: 8b049acd60bc68157ee6c632d7f44273fa366199c6bacbd6a0ef703c02d56190f1a1cec7471957452c453d07fd99a426efdba7842e6ca51383dc2abcaff6150a
6
+ metadata.gz: f6bc41df87ffbfae9c881ed44ba4932d5b46e79674c41db3e154cf357675e22ececd338856c2e2e7ab0db83f05484b83f3f067db76c9ac58b5b26925bbb5c1b3
7
+ data.tar.gz: 4f0356b9dae935ec70cef7b6db4ee7c98203f317a4c057814c42fcbeb7cf36a100cbaf7ccff214b0d1a5658ac590271542092fe7f4a6dc6543b06ecd0ce8e1cf
data/README.md CHANGED
@@ -37,7 +37,7 @@ class EchoService
37
37
  end
38
38
 
39
39
  # Start the server
40
- RubySkynet::Server.start
40
+ server = RubySkynet::Server.new
41
41
  ```
42
42
 
43
43
  Client to call the above Service
@@ -29,14 +29,18 @@ module RubySkynet
29
29
  begin
30
30
  require 'ruby_doozer'
31
31
  require 'ruby_skynet/doozer/service_registry'
32
+
33
+ # Shortcuts to loaded Registry classes
34
+ ServiceRegistry = RubySkynet::Doozer::ServiceRegistry
35
+ CachedRegistry = Doozer::CachedRegistry
36
+ Registry = Doozer::Registry
32
37
  rescue LoadError
33
- raise LoadError, "Load either the 'zookeeper' or 'ruby_doozer' gem prior to loading RubySkynet. 'zookeeper' is preferred"
38
+ require 'ruby_skynet/static_service_registry'
39
+
40
+ # Use Static Service Registry
41
+ ServiceRegistry = RubySkynet::StaticServiceRegistry
34
42
  end
35
43
 
36
- # Shortcuts to loaded Registry classes
37
- ServiceRegistry = RubySkynet::Doozer::ServiceRegistry
38
- CachedRegistry = Doozer::CachedRegistry
39
- Registry = Doozer::Registry
40
44
  end
41
45
  end
42
46
 
@@ -84,20 +84,14 @@ module RubySkynet
84
84
  # Skynet requires BSON RPC Calls to have the following format:
85
85
  # https://github.com/skynetservices/skynet/blob/master/protocol.md
86
86
  request_id = BSON::ObjectId.new.to_s
87
+
88
+ # Obtain list of servers implementing this service in order of priority
89
+ servers = ::RubySkynet.service_registry.servers_for(skynet_name, skynet_version, skynet_region)
90
+
87
91
  logger.tagged request_id do
88
92
  logger.benchmark_info "Called Skynet Service: #{skynet_name}.#{method_name}" do
89
- retries = 0
90
- # If it cannot connect to a server, try a different server
91
- begin
92
- Connection.with_connection(::RubySkynet.service_registry.server_for(skynet_name, skynet_version, skynet_region), connection_params) do |connection|
93
- connection.rpc_call(request_id, skynet_name, method_name, parameters)
94
- end
95
- rescue ResilientSocket::ConnectionFailure => exc
96
- if (retries < 3) && exc.cause.is_a?(Errno::ECONNREFUSED)
97
- retries += 1
98
- retry
99
- end
100
- # TODO rescue ServiceUnavailable retry x times until the service becomes available
93
+ Connection.with_connection(servers, connection_params) do |connection|
94
+ connection.rpc_call(request_id, skynet_name, method_name, parameters)
101
95
  end
102
96
  end
103
97
  end
@@ -1,5 +1,4 @@
1
1
  require 'bson'
2
- require 'gene_pool'
3
2
  require 'thread_safe'
4
3
  require 'resilient_socket'
5
4
  require 'sync_attr'
@@ -17,20 +16,6 @@ module RubySkynet
17
16
  # Returns the underlying socket being used by a Connection instance
18
17
  attr_reader :socket
19
18
 
20
- # Default Pool configuration
21
- sync_cattr_accessor :pool_config do
22
- {
23
- :pool_size => 30, # Maximum number of connections to any one server
24
- :warn_timeout => 2, # Log a warning if no connections are available after the :warn_timeout seconds
25
- :timeout => 10, # Raise a Timeout exception if no connections are available after the :timeout seconds
26
- :idle_timeout => 600, # Renew a connection if it has been idle for this period of time
27
- }
28
- end
29
-
30
- # For each server there is a connection pool keyed on the
31
- # server address: 'host:port'
32
- @@connection_pools = ThreadSafe::Hash.new
33
-
34
19
  # Returns a new RubySkynet connection to the server
35
20
  #
36
21
  # Parameters:
@@ -50,8 +35,8 @@ module RubySkynet
50
35
  # :connect_retry_interval [Float]
51
36
  # Number of seconds between connection retry attempts after the first failed attempt
52
37
  # Default: 0.5
53
- def initialize(server, params = {})
54
- self.logger = SemanticLogger["#{self.class.name} [#{server}]"]
38
+ def initialize(servers, params = {})
39
+ params = params.dup
55
40
 
56
41
  # User configurable options
57
42
  params[:read_timeout] ||= 60
@@ -95,8 +80,8 @@ module RubySkynet
95
80
  end
96
81
 
97
82
  # To prevent strange issues if user incorrectly supplies server names
98
- params.delete(:servers)
99
- params[:server] = server
83
+ params.delete(:server)
84
+ params[:servers] = servers
100
85
 
101
86
  @socket = ResilientSocket::TCPClient.new(params)
102
87
  end
@@ -209,44 +194,19 @@ module RubySkynet
209
194
 
210
195
  # Execute the supplied block with a connection from the pool
211
196
  def self.with_connection(server, params={}, &block)
212
- (@@connection_pools[server] ||= new_connection_pool(server, params)).with_connection(&block)
197
+ conn = nil
198
+ begin
199
+ conn = new(server, params)
200
+ block.call(conn)
201
+ ensure
202
+ conn.close if conn
203
+ end
213
204
  end
214
205
 
215
206
  def close
216
207
  @socket.close if @socket
217
208
  end
218
209
 
219
- ########################
220
- protected
221
-
222
- # Returns a new connection pool for the specified server
223
- def self.new_connection_pool(server, params={})
224
- # Connection pool configuration options
225
- config = pool_config.dup
226
-
227
- logger = SemanticLogger::Logger.new("#{self.class.name} [#{server}]")
228
-
229
- # Method to call to close idle connections
230
- config[:close_proc] = :close
231
- config[:logger] = logger
232
-
233
- pool = GenePool.new(pool_config) do
234
- new(server, params)
235
- end
236
-
237
- # Cleanup corresponding connection pool when a server terminates
238
- RubySkynet.service_registry.on_server_removed(server) do
239
- pool = @@connection_pools.delete(server)
240
- # Cannot close all the connections since they could still be in use
241
- pool.remove_idle(0) if pool
242
- #pool.close if pool
243
- logger.debug "Connection pool released"
244
- end
245
-
246
- pool
247
- end
248
-
249
210
  end
250
-
251
211
  end
252
212
 
@@ -1,6 +1,5 @@
1
1
  require 'semantic_logger'
2
2
  require 'thread_safe'
3
- require 'gene_pool'
4
3
  require 'resolv'
5
4
 
6
5
  #
@@ -62,18 +61,6 @@ module RubySkynet
62
61
  @registry.delete("#{name}/#{version}/#{region}/#{hostname}/#{port}")
63
62
  end
64
63
 
65
- # Return a server that implements the specified service
66
- def server_for(name, version='*', region=RubySkynet.region)
67
- if servers = servers_for(name, version, region)
68
- # Randomly select one of the servers offering the service
69
- servers[rand(servers.size)]
70
- else
71
- msg = "No servers available for service: #{name} with version: #{version} in region: #{region}"
72
- logger.warn msg
73
- raise ServiceUnavailable.new(msg)
74
- end
75
- end
76
-
77
64
  # Returns [Array<String>] a list of servers implementing the requested service
78
65
  def servers_for(name, version='*', region=RubySkynet.region)
79
66
  if version == '*'
@@ -86,9 +73,11 @@ module RubySkynet
86
73
  end
87
74
  end
88
75
  end
89
- if server_infos = @cache["#{name}/#{version}/#{region}"]
76
+ servers = if server_infos = @cache["#{name}/#{version}/#{region}"]
90
77
  server_infos.first.servers
91
78
  end
79
+ raise ServiceUnavailable.new("No servers available for service: #{name} with version: #{version} in region: #{region}") unless servers
80
+ servers
92
81
  end
93
82
 
94
83
  # Invokes registered callbacks when a specific server is shutdown or terminates
@@ -17,12 +17,14 @@ module RubySkynet #:nodoc:
17
17
 
18
18
  # Load RubySkynet Configuration once rails has started
19
19
  initializer 'ruby_skynet.initialize' do
20
- config_file = Rails.root.join("config", "ruby_skynet.yml")
21
- if config_file.file?
22
- ::RubySkynet.configure!(config_file, Rails.env)
23
- else
24
- puts "\nRuby Skynet config not found."
25
- puts "To generate one for the first time: rails generate ruby_skynet:config\n\n"
20
+ unless ::RubySkynet.configured?
21
+ config_file = Rails.root.join("config", "ruby_skynet.yml")
22
+ if config_file.file?
23
+ ::RubySkynet.configure!(config_file, Rails.env)
24
+ else
25
+ puts "\nRuby Skynet config not found."
26
+ puts "To generate one for the first time: rails generate ruby_skynet:config\n\n"
27
+ end
26
28
  end
27
29
  end
28
30
 
@@ -1,6 +1,6 @@
1
1
  namespace :ruby_skynet do
2
2
 
3
- desc "Start the Ruby Skynet Server.\n Rails Example: rake ruby_skynet:server\n Without Rails: SKYNET_ENV=production SKYNET_CONFIG=config/ruby_skynet rake ruby_skynet:server"
3
+ desc "Start the Ruby Skynet Server.\n Rails Example: rake ruby_skynet:server\n Without Rails: SKYNET_ENV=production SKYNET_CONFIG=config/ruby_skynet.yml rake ruby_skynet:server"
4
4
  task :server => :environment do
5
5
  # Configuration is automatically loaded when running under Rails
6
6
  # so skip it here under Rails
@@ -52,7 +52,7 @@ module RubySkynet
52
52
  # By default it connects to a local ZooKeeper instance
53
53
  # Use .configure! to supply a configuration file with any other settings
54
54
  sync_cattr_reader :service_registry do
55
- ServiceRegistry.new
55
+ ServiceRegistry.new(registry: {})
56
56
  end
57
57
 
58
58
  # Returns the current Registry Config information
@@ -60,7 +60,7 @@ module RubySkynet
60
60
  # By default it connects to a local ZooKeeper instance
61
61
  # Use .configure! to supply a configuration file with any other settings
62
62
  def self.registry_config
63
- @@config.dup if @@config && defined?(@@config)
63
+ @@config.dup if @@config
64
64
  end
65
65
 
66
66
  # Set the services registry
@@ -92,7 +92,7 @@ module RubySkynet
92
92
  RubySkynet.server_port = config.delete(:server_port) || 2000
93
93
  RubySkynet.local_ip_address = config.delete(:local_ip_address) || Common::local_ip_address
94
94
 
95
- # Extract just the zookeeper or doozer configuration element
95
+ # Extract the registry configuration element
96
96
  RubySkynet.service_registry = ServiceRegistry.new(
97
97
  :registry => config.delete(:registry)
98
98
  )
@@ -100,4 +100,8 @@ module RubySkynet
100
100
  config.each_pair {|k,v| warn "Ignoring unknown RubySkynet config option #{k} => #{v}"}
101
101
  end
102
102
 
103
+ # Returns [Boolean] whether the RubySkynet.configure! method has already been called
104
+ def self.configured?
105
+ !@@config.nil?
106
+ end
103
107
  end
@@ -0,0 +1,75 @@
1
+ require 'semantic_logger'
2
+ require 'thread_safe'
3
+
4
+ #
5
+ # RubySkynet Sevices Registry
6
+ #
7
+ # Loads a list of all services and which servers they are available on from a
8
+ # static YAML file
9
+ #
10
+ # Format of the YAML file
11
+ # key: [String] "<name>/<version>/<region>"
12
+ # value: [Array<String>] 'host:port', 'host:port'
13
+ #
14
+ module RubySkynet
15
+ class StaticServiceRegistry
16
+ include SemanticLogger::Loggable
17
+
18
+ # Create a service registry
19
+ def initialize(params = {})
20
+ @services = params[:registry]
21
+ raise "Missing :registry in config that must list the availables services" unless @services
22
+ end
23
+
24
+ # Returns the Service Registry as a Hash
25
+ def to_h
26
+ @services.dup
27
+ end
28
+
29
+ # Register the supplied service at this Skynet Server host and Port
30
+ # Returns the UUID for the service that was created
31
+ def register_service(name, version, region, hostname, port)
32
+ server = "#{hostname}:#{port}"
33
+ key = "#{name}/#{version}/#{region}"
34
+ (@services[key] ||= []) << server
35
+ key
36
+ end
37
+
38
+ # Deregister the supplied service from the Registry
39
+ def deregister_service(name, version, region, hostname, port)
40
+ server = "#{hostname}:#{port}"
41
+ key = "#{name}/#{version}/#{region}"
42
+ if servers = @services[key]
43
+ servers.delete_if {|s| s == server}
44
+ @services.delete(key) if servers.count == 0
45
+ end
46
+ key
47
+ end
48
+
49
+ # Returns [Array<String>] a list of servers implementing the requested service
50
+ def servers_for(name, version='*', region=RubySkynet.region)
51
+ if version == '*'
52
+ # Find the highest version for the named service in this region
53
+ version = -1
54
+ @services.keys.each do |key|
55
+ if match = key.match(/#{name}\/(\d+)\/#{region}/)
56
+ ver = match[1].to_i
57
+ version = ver if ver > version
58
+ end
59
+ end
60
+ end
61
+ servers = @services["#{name}/#{version}/#{region}"]
62
+ raise ServiceUnavailable.new("No servers available for service: #{name} with version: #{version} in region: #{region}") unless servers
63
+ servers
64
+ end
65
+
66
+ # Invokes registered callbacks when a specific server is shutdown or terminates
67
+ # Not when a server de-registers itself
68
+ # The callback will only be called once and will need to be re-registered
69
+ # after being called if future callbacks are required for that server
70
+ def on_server_removed(server, &block)
71
+ #nop
72
+ end
73
+
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
1
  module RubySkynet #:nodoc
2
- VERSION = "2.0.0.rc1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,6 +1,5 @@
1
1
  require 'semantic_logger'
2
2
  require 'thread_safe'
3
- require 'gene_pool'
4
3
  require 'resolv'
5
4
 
6
5
  #
@@ -76,18 +75,6 @@ module RubySkynet
76
75
  uuid
77
76
  end
78
77
 
79
- # Return a server that implements the specified service
80
- def server_for(name, version='*', region=RubySkynet.region)
81
- if servers = servers_for(name, version, region)
82
- # Randomly select one of the servers offering the service
83
- servers[rand(servers.size)]
84
- else
85
- msg = "No servers available for service: #{name} with version: #{version} in region: #{region}"
86
- logger.warn msg
87
- raise ServiceUnavailable.new(msg)
88
- end
89
- end
90
-
91
78
  # Returns [Array<String>] a list of servers implementing the requested service
92
79
  def servers_for(name, version='*', region=RubySkynet.region)
93
80
  if version == '*'
@@ -100,9 +87,11 @@ module RubySkynet
100
87
  end
101
88
  end
102
89
  end
103
- if server_infos = @cache["#{name}/#{version}/#{region}"]
90
+ servers = if server_infos = @cache["#{name}/#{version}/#{region}"]
104
91
  server_infos.first.servers
105
92
  end
93
+ raise ServiceUnavailable.new("No servers available for service: #{name} with version: #{version} in region: #{region}") unless servers
94
+ servers
106
95
  end
107
96
 
108
97
  # Invokes registered callbacks when a specific server is shutdown or terminates
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_skynet
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-14 00:00:00.000000000 Z
11
+ date: 2014-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: semantic_logger
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.0
19
+ version: 2.6.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.0
26
+ version: 2.6.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: resilient_socket
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.5.0
41
- - !ruby/object:Gem::Dependency
42
- name: gene_pool
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: 1.3.0
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '>='
53
- - !ruby/object:Gem::Version
54
- version: 1.3.0
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: sync_attr
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -70,14 +56,14 @@ dependencies:
70
56
  name: bson
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - ~>
59
+ - - '>='
74
60
  - !ruby/object:Gem::Version
75
61
  version: 2.0.0.rc3
76
62
  type: :runtime
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - ~>
66
+ - - '>='
81
67
  - !ruby/object:Gem::Version
82
68
  version: 2.0.0.rc3
83
69
  - !ruby/object:Gem::Dependency
@@ -113,6 +99,7 @@ files:
113
99
  - lib/ruby_skynet/ruby_skynet.rb
114
100
  - lib/ruby_skynet/server.rb
115
101
  - lib/ruby_skynet/service.rb
102
+ - lib/ruby_skynet/static_service_registry.rb
116
103
  - lib/ruby_skynet/version.rb
117
104
  - lib/ruby_skynet/zookeeper/cached_registry.rb
118
105
  - lib/ruby_skynet/zookeeper/extensions/java_base.rb
@@ -141,12 +128,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
128
  version: '0'
142
129
  required_rubygems_version: !ruby/object:Gem::Requirement
143
130
  requirements:
144
- - - '>'
131
+ - - '>='
145
132
  - !ruby/object:Gem::Version
146
- version: 1.3.1
133
+ version: '0'
147
134
  requirements: []
148
135
  rubyforge_project:
149
- rubygems_version: 2.0.3
136
+ rubygems_version: 2.1.11
150
137
  signing_key:
151
138
  specification_version: 4
152
139
  summary: Skynet Ruby Client