ruby_skynet 1.3.0.alpha3 → 2.0.0.rc1

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: 6740cfd40beae05bf039e9bd5fa02281cf6a5e8a
4
- data.tar.gz: 4fe0295d46526174f6756a505982a9e67d6cd127
3
+ metadata.gz: bf65f91389e27d97e04be4be8a1ef49700bb245b
4
+ data.tar.gz: 6b26fea72828375f49fff798c931744951747698
5
5
  SHA512:
6
- metadata.gz: f49f801c0796148c2269a6a82db40980f8bbf6542bffd7bd9b448aebda4497c7a316a4d7a7a9ba512898234221bcb51e634ddd91d67d631ea7ed751b9f35fd22
7
- data.tar.gz: 1420af0774b7404a1fdc227ff64d64300d214f4b505b17cacba14d56ddde5147a46259fd1067d15dc18940c785caba230552742a8ac0636eb893b0665d03829f
6
+ metadata.gz: 20a409544353b4634fde2fb83595e0998ef808383591ad08692bf5422d6bbf07995e1bf781b5a698ceeb7d1e1ec18d840eb8ef98b9f6939d27273a8c9324574c
7
+ data.tar.gz: 8b049acd60bc68157ee6c632d7f44273fa366199c6bacbd6a0ef703c02d56190f1a1cec7471957452c453d07fd99a426efdba7842e6ca51383dc2abcaff6150a
@@ -2,10 +2,8 @@ require 'semantic_logger'
2
2
  require 'ruby_skynet/exceptions'
3
3
  require 'ruby_skynet/version'
4
4
  require 'ruby_skynet/ruby_skynet'
5
- require 'ruby_skynet/zookeeper'
6
5
 
7
6
  module RubySkynet
8
- autoload :Base, 'ruby_skynet/base'
9
7
  autoload :Common, 'ruby_skynet/common'
10
8
  autoload :Connection, 'ruby_skynet/connection'
11
9
  autoload :Client, 'ruby_skynet/client'
@@ -31,18 +29,14 @@ module RubySkynet
31
29
  begin
32
30
  require 'ruby_doozer'
33
31
  require 'ruby_skynet/doozer/service_registry'
34
-
35
- # Shortcuts to loaded Registry classes
36
- ServiceRegistry = RubySkynet::Doozer::ServiceRegistry
37
- CachedRegistry = Doozer::CachedRegistry
38
- Registry = Doozer::Registry
39
32
  rescue LoadError
40
- require 'ruby_skynet/static_service_registry'
41
-
42
- # Use Static Service Registry
43
- ServiceRegistry = RubySkynet::StaticServiceRegistry
33
+ raise LoadError, "Load either the 'zookeeper' or 'ruby_doozer' gem prior to loading RubySkynet. 'zookeeper' is preferred"
44
34
  end
45
35
 
36
+ # Shortcuts to loaded Registry classes
37
+ ServiceRegistry = RubySkynet::Doozer::ServiceRegistry
38
+ CachedRegistry = Doozer::CachedRegistry
39
+ Registry = Doozer::Registry
46
40
  end
47
41
  end
48
42
 
@@ -8,8 +8,9 @@ require 'bson'
8
8
  #
9
9
  module RubySkynet
10
10
  class Client
11
- include Base
11
+ include Common
12
12
 
13
+ # Allows this instance of the client to use different versions or regions.
13
14
  attr_reader :skynet_name, :skynet_version, :skynet_region
14
15
 
15
16
  # Version of the Skynet service to use
@@ -83,14 +84,20 @@ module RubySkynet
83
84
  # Skynet requires BSON RPC Calls to have the following format:
84
85
  # https://github.com/skynetservices/skynet/blob/master/protocol.md
85
86
  request_id = BSON::ObjectId.new.to_s
86
-
87
- # Obtain list of servers implementing this service in order of priority
88
- servers = ::RubySkynet.service_registry.servers_for(skynet_name, skynet_version, skynet_region)
89
-
90
87
  logger.tagged request_id do
91
88
  logger.benchmark_info "Called Skynet Service: #{skynet_name}.#{method_name}" do
92
- Connection.with_connection(servers, connection_params) do |connection|
93
- connection.rpc_call(request_id, skynet_name, method_name, parameters)
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
94
101
  end
95
102
  end
96
103
  end
@@ -104,7 +111,7 @@ module RubySkynet
104
111
  #
105
112
  # Define the method if the call was successful and no other thread has
106
113
  # already created the method
107
- if result[:exception].nil? && !self.class.method_defined?(method)
114
+ if !result.nil? && result[:exception].nil? && !self.class.method_defined?(method)
108
115
  self.class.send(:define_method, method) {|*args| call(method, *args)}
109
116
  end
110
117
  result
@@ -1,28 +1,28 @@
1
- require 'bson'
1
+ require 'stringio'
2
2
  require 'socket'
3
+ require 'semantic_logger'
4
+ require 'bson'
3
5
 
4
6
  module RubySkynet
5
7
  module Common
6
8
 
9
+ BINARY_ENCODING = Encoding.find("binary")
10
+
7
11
  # Returns a BSON document read from the socket.
8
12
  # Returns nil if the operation times out or if a network
9
13
  # connection failure occurs
10
14
  def self.read_bson_document(socket)
11
- bytebuf = BSON::ByteBuffer.new
12
15
  # Read 4 byte size of following BSON document
13
- bytes = socket.read(4)
14
-
15
- # No more data
16
- return unless bytes
16
+ if bytes = socket.read(4)
17
+ bytes.force_encoding(BINARY_ENCODING)
18
+ # Read BSON document
19
+ sz = bytes.unpack("V")[0]
20
+ raise "Invalid Data received from server:#{bytes.inspect}" unless sz
17
21
 
18
- # Read BSON document
19
- sz = bytes.unpack("V")[0]
20
- raise "Invalid Data received from server:#{bytes.inspect}" unless sz
21
-
22
- bytebuf.append!(bytes)
23
- bytebuf.append!(socket.read(sz - 4))
24
- raise "Socket is not returning #{sz} requested bytes. #{bytebuf.length} bytes returned" unless sz == bytebuf.length
25
- return BSON.deserialize(bytebuf)
22
+ bytes << socket.read(sz - 4)
23
+ raise "Socket is not returning #{sz} requested bytes. #{bytes.length} bytes returned" unless sz == bytes.length
24
+ Hash.from_bson(StringIO.new(bytes))
25
+ end
26
26
  end
27
27
 
28
28
  # Returns the local ip address being used by this machine to talk to the
@@ -31,5 +31,45 @@ module RubySkynet
31
31
  @@local_ip_address ||= ::UDPSocket.open {|s| s.connect(remote_ip, 1); s.addr.last }
32
32
  end
33
33
 
34
+ def self.included(base)
35
+ base.extend ClassMethods
36
+ base.class_eval do
37
+ include SemanticLogger::Loggable
38
+ end
39
+ end
40
+
41
+ module ClassMethods
42
+ # Name of this service to Register with Skynet
43
+ # Default: class name
44
+ def skynet_name
45
+ @skynet_name ||= name.gsub('::', '.')
46
+ end
47
+
48
+ def skynet_name=(skynet_name)
49
+ @skynet_name = skynet_name
50
+ end
51
+
52
+ # Version of this service to register with Skynet
53
+ # Default: nil
54
+ def skynet_version
55
+ @skynet_version ||= nil
56
+ end
57
+
58
+ def skynet_version=(skynet_version)
59
+ @skynet_version = skynet_version
60
+ end
61
+
62
+ # Region within which this service is defined
63
+ # Default: RubySkynet.region
64
+ def skynet_region
65
+ @skynet_region || ::RubySkynet.region
66
+ end
67
+
68
+ def skynet_region=(skynet_region)
69
+ @skynet_region = skynet_region
70
+ end
71
+
72
+ end
73
+
34
74
  end
35
75
  end
@@ -1,4 +1,5 @@
1
1
  require 'bson'
2
+ require 'gene_pool'
2
3
  require 'thread_safe'
3
4
  require 'resilient_socket'
4
5
  require 'sync_attr'
@@ -16,6 +17,20 @@ module RubySkynet
16
17
  # Returns the underlying socket being used by a Connection instance
17
18
  attr_reader :socket
18
19
 
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
+
19
34
  # Returns a new RubySkynet connection to the server
20
35
  #
21
36
  # Parameters:
@@ -35,8 +50,8 @@ module RubySkynet
35
50
  # :connect_retry_interval [Float]
36
51
  # Number of seconds between connection retry attempts after the first failed attempt
37
52
  # Default: 0.5
38
- def initialize(servers, params = {})
39
- params = params.dup
53
+ def initialize(server, params = {})
54
+ self.logger = SemanticLogger["#{self.class.name} [#{server}]"]
40
55
 
41
56
  # User configurable options
42
57
  params[:read_timeout] ||= 60
@@ -76,12 +91,12 @@ module RubySkynet
76
91
  client_handshake = { 'clientid' => client_id }
77
92
  logger.debug "Sending Client Handshake"
78
93
  logger.trace 'Client Handshake', client_handshake
79
- socket.write(BSON.serialize(client_handshake).to_s)
94
+ socket.write(client_handshake.to_bson)
80
95
  end
81
96
 
82
97
  # To prevent strange issues if user incorrectly supplies server names
83
- params.delete(:server)
84
- params[:servers] = servers
98
+ params.delete(:servers)
99
+ params[:server] = server
85
100
 
86
101
  @socket = ResilientSocket::TCPClient.new(params)
87
102
  end
@@ -116,12 +131,12 @@ module RubySkynet
116
131
 
117
132
  logger.debug "Sending Header"
118
133
  logger.trace 'Header', header
119
- socket.write(BSON.serialize(header).to_s)
134
+ socket.write(header.to_bson)
120
135
 
121
136
  # The parameters are placed in the request object in BSON serialized form
122
137
  request = {
123
138
  'clientid' => socket.user_data[:client_id],
124
- 'in' => BSON::Binary.new(BSON.serialize(parameters).to_s),
139
+ 'in' => BSON::Binary.new(parameters.to_bson),
125
140
  'method' => method_name.to_s,
126
141
  'requestinfo' => {
127
142
  'requestid' => request_id,
@@ -137,7 +152,7 @@ module RubySkynet
137
152
  logger.debug "Sending Request"
138
153
  logger.trace 'Request', request
139
154
  logger.trace 'Parameters:', parameters
140
- socket.write(BSON.serialize(request).to_s)
155
+ socket.write(request.to_bson)
141
156
 
142
157
  # Since Send does not affect state on the server we can also retry reads
143
158
  if idempotent
@@ -186,7 +201,7 @@ module RubySkynet
186
201
 
187
202
  # Return Value
188
203
  # The return value is inside the response object, it's a byte array of it's own and needs to be deserialized
189
- result = BSON.deserialize(response['out'])
204
+ result = Hash.from_bson(StringIO.new(response['out'].data))
190
205
  logger.trace 'Return Value', result
191
206
  result
192
207
  end
@@ -194,19 +209,44 @@ module RubySkynet
194
209
 
195
210
  # Execute the supplied block with a connection from the pool
196
211
  def self.with_connection(server, params={}, &block)
197
- conn = nil
198
- begin
199
- conn = new(server, params)
200
- block.call(conn)
201
- ensure
202
- conn.close if conn
203
- end
212
+ (@@connection_pools[server] ||= new_connection_pool(server, params)).with_connection(&block)
204
213
  end
205
214
 
206
215
  def close
207
216
  @socket.close if @socket
208
217
  end
209
218
 
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
+
210
249
  end
250
+
211
251
  end
212
252
 
@@ -1,5 +1,6 @@
1
1
  require 'semantic_logger'
2
2
  require 'thread_safe'
3
+ require 'gene_pool'
3
4
  require 'resolv'
4
5
 
5
6
  #
@@ -61,6 +62,18 @@ module RubySkynet
61
62
  @registry.delete("#{name}/#{version}/#{region}/#{hostname}/#{port}")
62
63
  end
63
64
 
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
+
64
77
  # Returns [Array<String>] a list of servers implementing the requested service
65
78
  def servers_for(name, version='*', region=RubySkynet.region)
66
79
  if version == '*'
@@ -73,11 +86,9 @@ module RubySkynet
73
86
  end
74
87
  end
75
88
  end
76
- servers = if server_infos = @cache["#{name}/#{version}/#{region}"]
89
+ if server_infos = @cache["#{name}/#{version}/#{region}"]
77
90
  server_infos.first.servers
78
91
  end
79
- raise ServiceUnavailable.new("No servers available for service: #{name} with version: #{version} in region: #{region}") unless servers
80
- servers
81
92
  end
82
93
 
83
94
  # Invokes registered callbacks when a specific server is shutdown or terminates
@@ -6,28 +6,25 @@ namespace :ruby_skynet do
6
6
  # so skip it here under Rails
7
7
  unless defined?(Rails)
8
8
  # Environment to use in config file
9
+ # Defaults to Rails.env
9
10
  environment = ENV['SKYNET_ENV']
10
11
 
11
12
  # Environment to use in config file
13
+ # Defaults to config/ruby_skynet.yml
12
14
  cfg_file = ENV['SKYNET_CONFIG']
13
15
 
14
16
  # Load the configuration file
15
17
  RubySkynet.configure!(cfg_file, environment)
16
18
  end
17
19
 
18
- # Connect to services registry
19
- RubySkynet.services
20
-
21
- RubySkynet::Server.load_services
22
-
20
+ server = nil
23
21
  begin
24
- # Start the server
25
- RubySkynet::Server.start
26
- RubySkynet::Server.wait_until_server_stops
22
+ server = RubySkynet::Server.new
23
+ server.register_services_in_path
24
+ server.wait_until_server_stops
27
25
  ensure
28
- RubySkynet::Server.stop
26
+ server.close if server
29
27
  end
30
-
31
28
  end
32
29
 
33
30
  end
@@ -2,6 +2,7 @@ require 'sync_attr'
2
2
 
3
3
  module RubySkynet
4
4
  include SyncAttr
5
+ @@config = nil
5
6
 
6
7
  # Returns the default region for all Ruby Skynet Clients and Services
7
8
  def self.region
@@ -51,7 +52,7 @@ module RubySkynet
51
52
  # By default it connects to a local ZooKeeper instance
52
53
  # Use .configure! to supply a configuration file with any other settings
53
54
  sync_cattr_reader :service_registry do
54
- ServiceRegistry.new(registry: {})
55
+ ServiceRegistry.new
55
56
  end
56
57
 
57
58
  # Returns the current Registry Config information
@@ -69,11 +70,6 @@ module RubySkynet
69
70
  @@service_registry = service_registry
70
71
  end
71
72
 
72
- # DEPRECATED - Use RubySkynet.service_registry
73
- def self.services
74
- @@service_registry
75
- end
76
-
77
73
  # Load the Configuration information from a YAML file
78
74
  # filename:
79
75
  # Name of file to read.
@@ -104,7 +100,4 @@ module RubySkynet
104
100
  config.each_pair {|k,v| warn "Ignoring unknown RubySkynet config option #{k} => #{v}"}
105
101
  end
106
102
 
107
- # Initialize internal class variable
108
- @@config = nil
109
-
110
103
  end
@@ -9,73 +9,8 @@ module RubySkynet
9
9
  class Server
10
10
  include SemanticLogger::Loggable
11
11
 
12
- @@server = nil
13
- @@services = ThreadSafe::Hash.new
14
-
15
- # Start a single instance of the server
16
- def self.start(start_port = nil, ip_address = nil)
17
- @@server ||= new(start_port, ip_address)
18
-
19
- # Stop the skynet server on shutdown
20
- # To ensure services are de-registered in the service registry
21
- at_exit do
22
- ::RubySkynet::Server.stop
23
- end
24
- end
25
-
26
- # Stop the single instance of the server
27
- def self.stop
28
- @@server.finalize if @@server
29
- @@server = nil
30
- end
31
-
32
- # Is the single instance of the server running
33
- def self.running?
34
- (@@server != nil) && @@server.running?
35
- end
36
-
37
- # Wait forever until the running server stops
38
- def self.wait_until_server_stops
39
- (@@server != nil) && @@server.wait_until_server_stops
40
- end
41
-
42
- # Services currently loaded and available at this server when running
43
- def self.services
44
- @@services
45
- end
46
-
47
- # Registers a Service Class as being available at this host and port
48
- def self.register_service(klass)
49
- raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:skynet_name) && klass.respond_to?(:skynet_version) && klass.respond_to?(:skynet_region)
50
-
51
- previous_klass = @@services[klass.skynet_name]
52
- if previous_klass && (previous_klass.name != klass.name)
53
- logger.warn("Service with name: #{klass.skynet_name} is already registered to a different implementation:#{previous_klass.name}")
54
- end
55
- @@services[klass.skynet_name] = klass
56
- @@server.register_service(klass) if @@server
57
- end
58
-
59
- # De-register service
60
- def self.deregister_service(klass)
61
- raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:skynet_name) && klass.respond_to?(:skynet_version) && klass.respond_to?(:skynet_region)
62
-
63
- @@server.deregister_service(klass) if @@server
64
- @@services.delete(klass.skynet_name)
65
- end
66
-
67
- # Load and register all services found in the supplied path and it's sub-directories
68
- def self.load_services
69
- RubySkynet::Server.logger.benchmark_info "Loaded Skynet Services" do
70
- # Load services
71
- Dir.glob("#{RubySkynet.services_path}/**/*.rb").each do |path|
72
- load path
73
- end
74
- end
75
- end
76
-
77
12
  # The actual port the server is running at
78
- attr_reader :hostname, :port
13
+ attr_reader :hostname, :port, :services
79
14
 
80
15
  # Start the server so that it can start taking RPC calls
81
16
  # Returns false if the server is already running
@@ -101,16 +36,16 @@ module RubySkynet
101
36
  # Start Server listener thread
102
37
  @listener_thread = Thread.new { run }
103
38
 
104
- # Register services hosted by this server
105
- self.class.services.each_value {|klass| register_service(klass)}
39
+ # Array[RubySkynet::Service] List of services registered with this server instance
40
+ @services = ThreadSafe::Hash.new
106
41
  end
107
42
 
108
- def finalize
43
+ def close
109
44
  @server.close if @server
110
45
  logger.info "Skynet Server Stopped"
111
46
 
112
47
  # Deregister services hosted by this server
113
- self.class.services.each_value do |klass|
48
+ @services.each_value do |klass|
114
49
  deregister_service(klass) rescue nil
115
50
  end
116
51
  logger.info "Skynet Services De-registered"
@@ -128,19 +63,59 @@ module RubySkynet
128
63
 
129
64
  # Registers a Service Class as being available at this server
130
65
  def register_service(klass)
66
+ raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:skynet_name) && klass.respond_to?(:skynet_version) && klass.respond_to?(:skynet_region)
67
+
68
+ previous_klass = @services[klass.skynet_name]
69
+ if previous_klass && (previous_klass.name != klass.name)
70
+ logger.warn("Service with name: #{klass.skynet_name} is already registered to a different implementation:#{previous_klass.name}")
71
+ end
72
+ @services[klass.skynet_name] = klass
73
+
131
74
  logger.info "Registering Service: #{klass.name} with name: #{klass.skynet_name}"
132
75
  ::RubySkynet.service_registry.register_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
133
76
  end
134
77
 
135
78
  # De-register service from this server
136
79
  def deregister_service(klass)
80
+ raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:skynet_name) && klass.respond_to?(:skynet_version) && klass.respond_to?(:skynet_region)
81
+
137
82
  logger.info "De-registering Service: #{klass.name} with name: #{klass.skynet_name}"
138
83
  ::RubySkynet.service_registry.deregister_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
84
+ @services.delete(klass.skynet_name)
85
+ end
86
+
87
+ # Loads and registers all services found in the supplied path and it's sub-directories
88
+ # Returns [RubySkynet::Service] the list of Services registered
89
+ def register_services_in_path(path=RubySkynet.services_path)
90
+ logger.benchmark_info "Loaded Skynet Services" do
91
+ # Load services
92
+ klasses = []
93
+ Dir.glob("#{path}/**/*.rb").each do |filename|
94
+ partial = filename.sub(path,'').sub('.rb', '')
95
+ load filename
96
+ camelized = partial.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
97
+ begin
98
+ klass = constantize(camelized)
99
+ # Register the service
100
+ register_service(klass)
101
+ klasses << klass
102
+ rescue Exception => exc
103
+ p exc
104
+ raise "Expected to find class #{camelized} in file #{filename}"
105
+ end
106
+ end
107
+ klasses
108
+ end
139
109
  end
140
110
 
141
111
  ############################################################################
142
112
  protected
143
113
 
114
+ # Re-Register services hosted by this server in the registry
115
+ def re_register_services_in_registry
116
+ @services.each_value {|klass| register_service(klass)}
117
+ end
118
+
144
119
  def run
145
120
  logger.info("Starting listener on #{hostname}:#{port}")
146
121
  loop do
@@ -168,7 +143,7 @@ module RubySkynet
168
143
  'registered' => true,
169
144
  'clientid' => BSON::ObjectId.new.to_s
170
145
  }
171
- client.write(BSON.serialize(handshake).to_s)
146
+ client.write(handshake.to_bson)
172
147
  Common.read_bson_document(client)
173
148
 
174
149
  while(header = Common.read_bson_document(client)) do
@@ -185,7 +160,7 @@ module RubySkynet
185
160
  request = Common.read_bson_document(client)
186
161
  logger.trace 'Request', request
187
162
  break unless request
188
- params = BSON.deserialize(request['in'])
163
+ params = Hash.from_bson(StringIO.new(request['in'].data))
189
164
  logger.trace 'Parameters', params
190
165
 
191
166
  reply = begin
@@ -198,11 +173,11 @@ module RubySkynet
198
173
  if reply
199
174
  logger.debug "Sending Header"
200
175
  # For this test we just send back the received header
201
- client.write(BSON.serialize(header).to_s)
176
+ client.write(header.to_bson)
202
177
 
203
178
  logger.debug "Sending Reply"
204
179
  logger.trace 'Reply', reply
205
- client.write(BSON.serialize('out' => BSON::Binary.new(BSON.serialize(reply))).to_s)
180
+ client.write({'out' => BSON::Binary.new(reply.to_bson)}.to_bson)
206
181
  else
207
182
  logger.debug "Closing client since no reply is being sent back"
208
183
  break
@@ -221,7 +196,7 @@ module RubySkynet
221
196
  def on_message(skynet_name, method, params)
222
197
  logger.benchmark_info("Skynet Call: #{skynet_name}##{method}") do
223
198
  logger.trace "Method Call: #{method} with parameters:", params
224
- klass = Server.services[skynet_name]
199
+ klass = services[skynet_name]
225
200
  raise "Invalid Skynet RPC call, service: #{skynet_name} is not available at this server" unless klass
226
201
  # TODO Use pool of services
227
202
  service = klass.new
@@ -230,5 +205,17 @@ module RubySkynet
230
205
  end
231
206
  end
232
207
 
208
+ # Returns the supplied camel_cased string as it's class
209
+ def constantize(camel_cased_word)
210
+ names = camel_cased_word.split('::')
211
+ names.shift if names.empty? || names.first.empty?
212
+
213
+ constant = Object
214
+ names.each do |name|
215
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
216
+ end
217
+ constant
218
+ end
219
+
233
220
  end
234
221
  end