ruby_skynet 1.3.0.alpha3 → 2.0.0.rc1

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: 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