ruby_skynet 0.6.0 → 0.7.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: 5e4070e64ce70f32032c82eee9e6af0eaa94626c
4
- data.tar.gz: 62ff2d291f403ac51406e17ead44a3f5feacd120
3
+ metadata.gz: 09c9a8e2a436c89fd46211dc103f0b55946fbfc2
4
+ data.tar.gz: e2683cdb8fae60e831c7793fca87e4f1ae573095
5
5
  SHA512:
6
- metadata.gz: 66559b704a0e6f1f73967e555d23c6f3eb975c58059324cb9f06944b4eff65ae22105ce1a28f4e7533d9cdb9a84d3f20de391dce860c2aa0a58bc935a28fbf88
7
- data.tar.gz: 17d54811347c21ff8c20a174923ce96469e05ed56c9603abef0d1a3374eda8a80e1536cb3f35cbc07746ccfae7b9dac9afb126eb7630e900024fea863ae26687
6
+ metadata.gz: 87a5e433d14d3c986c44472f0c19baeebd54a87362e071478d046238217470072fae4712af21ada8b16e771c326c44aa5a7b69ac96b124a0f3bab7e7994f2226
7
+ data.tar.gz: 5baff9cf4822187512543ef599f7e6842a5dab2a95744da5a55461a9d711c820f738018b8783672b8f3da12d1903a66c70bfc955395217d2df83db8f8ac5fb15
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ group :test do
5
5
  end
6
6
 
7
7
  gem "rake"
8
- gem "semantic_logger"
8
+ gem "semantic_logger", ">= 2.1"
9
9
  gem "resilient_socket"
10
10
  # Doozer Client
11
11
  gem "ruby_doozer"
data/Gemfile.lock CHANGED
@@ -21,7 +21,7 @@ GEM
21
21
  rake (10.0.3)
22
22
  resilient_socket (0.4.0)
23
23
  semantic_logger
24
- ruby_doozer (0.4.0)
24
+ ruby_doozer (0.5.0)
25
25
  gene_pool
26
26
  resilient_socket
27
27
  ruby_protobuf
data/Rakefile CHANGED
@@ -24,11 +24,11 @@ task :gem do |t|
24
24
  spec.files = FileList["./**/*"].exclude(/\.gem$/, /\.log$/,/nbproject/).map{|f| f.sub(/^\.\//, '')}
25
25
  spec.license = "Apache License V2.0"
26
26
  spec.has_rdoc = true
27
- spec.add_dependency 'semantic_logger', '>= 2.0.0'
28
- spec.add_dependency 'resilient_socket', '>= 0.4.0'
27
+ spec.add_dependency 'semantic_logger', '>= 2.1.0'
28
+ spec.add_dependency 'resilient_socket', '>= 0.5.0'
29
29
  spec.add_dependency 'multi_json', '>= 1.6.1'
30
30
  spec.add_dependency 'bson', '>= 1.5.2'
31
- spec.add_dependency 'ruby_doozer', '>= 0.5.0'
31
+ spec.add_dependency 'ruby_doozer', '>= 0.6.0'
32
32
  spec.add_dependency 'gene_pool', '>= 1.3.0'
33
33
  end
34
34
  Gem::Package.build gemspec
@@ -3,8 +3,12 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
3
  require 'rubygems'
4
4
  require 'ruby_skynet'
5
5
 
6
- SemanticLogger::Logger.default_level = :trace
7
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('echo_client.log')
6
+ SemanticLogger.default_level = :info
7
+ SemanticLogger.add_appender(STDOUT)
8
8
 
9
- client = RubySkynet::Client.new('EchoService')
10
- p client.call('echo', :hello => 'world')
9
+ class Echo < RubySkynet::Client
10
+ self.skynet_name = "EchoService"
11
+ end
12
+
13
+ client = Echo.new
14
+ p client.echo(:hello => 'world')
@@ -3,18 +3,20 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
3
  require 'rubygems'
4
4
  require 'ruby_skynet'
5
5
 
6
- # Log trace information to a log file
7
- SemanticLogger::Logger.default_level = :trace
8
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('echo_server.log')
6
+ SemanticLogger.default_level = :info
7
+ SemanticLogger.add_appender(STDOUT)
9
8
 
10
9
  # Just echo back any parameters received when the echo method is called
11
10
  class EchoService
12
11
  include RubySkynet::Service
13
12
 
13
+ skynet_name = "JoeService"
14
+
14
15
  # Methods implemented by this service
15
16
  # Must take a Hash as input
16
17
  # Must Return a Hash response or nil for no response
17
18
  def echo(params)
19
+ params['echo'] = true
18
20
  params
19
21
  end
20
22
  end
@@ -25,4 +27,3 @@ RubySkynet::Server.start
25
27
  puts "Press enter to shutdown server"
26
28
  gets
27
29
 
28
- RubySkynet::Server.stop
@@ -7,24 +7,6 @@ module RubySkynet
7
7
  base.extend ClassMethods
8
8
  base.class_eval do
9
9
  include SemanticLogger::Loggable
10
- include InstanceMethods
11
- end
12
- end
13
-
14
- module InstanceMethods
15
- # Implement methods that call the remote Service
16
- def method_missing(method, *args, &block)
17
- result = ruby_skynet_client.call(method, *args)
18
- # Define the method if the call was successful and no-one else already
19
- # created the method
20
- if result[:exception].nil? && !self.class.method_defined?(method)
21
- self.class.send(:define_method, method) {|*args| ruby_skynet_client.call(method, *args)}
22
- end
23
- result
24
- end
25
-
26
- def ruby_skynet_client
27
- @ruby_skynet_client ||= RubySkynet::Client.new(self.class.skynet_name, self.class.skynet_version || '*', self.class.skynet_region)
28
10
  end
29
11
  end
30
12
 
@@ -8,6 +8,17 @@ require 'bson'
8
8
  #
9
9
  module RubySkynet
10
10
  class Client
11
+ include Base
12
+
13
+ attr_reader :skynet_name, :skynet_version, :skynet_region
14
+
15
+ # Version of the Skynet service to use
16
+ # By default it will connect to the latest version
17
+ # Default: '*'
18
+ def self.skynet_version
19
+ @skynet_version ||= '*'
20
+ end
21
+
11
22
  # Returns a new RubySkynet Client for the named service
12
23
  #
13
24
  # Calls to an instance of the Client are thread-safe and can be called
@@ -15,29 +26,45 @@ module RubySkynet
15
26
  #
16
27
  # Parameters:
17
28
  # :skynet_name
29
+ # Only required when creating instance of RubySkynet::Client directly
30
+ # Otherwise it defaults to the name of the class
18
31
  # Name of the service to look for and connect to on Skynet
19
32
  #
20
- # :version
33
+ # :skynet_version
21
34
  # Optional version number of the service in Skynet
22
35
  # Default: '*' being the latest version of the service
23
36
  #
24
- # :region
37
+ # :skynet_region
25
38
  # Optional region for this service in Skynet
26
- # Default: 'Development'
39
+ # Default: RubySkynet.region
40
+ #
41
+ # Example using Client class
42
+ #
43
+ # require 'ruby_skynet'
44
+ # SemanticLogger.default_level = :info
45
+ # SemanticLogger.add_appender(STDOUT)
27
46
  #
28
- # Example
47
+ # class EchoService < RubySkynet::Client
48
+ # end
49
+ #
50
+ # echo_service = EchoService.new
51
+ # p echo_service.echo(:value => 5)
52
+ #
53
+ # Example using Ruby Client directly
29
54
  #
30
55
  # require 'ruby_skynet'
31
- # SemanticLogger.default_level = :trace
32
- # SemanticLogger.appenders << SemanticLogger::Appender::File(STDOUT)
56
+ # SemanticLogger.default_level = :info
57
+ # SemanticLogger.add_appender(STDOUT)
33
58
  #
34
59
  # tutorial_service = RubySkynet::Client.new('TutorialService')
35
60
  # p tutorial_service.call('Add', :value => 5)
36
- def initialize(skynet_name, version='*', region='Development')
37
- @skynet_name = skynet_name
38
- @logger = SemanticLogger::Logger.new("#{self.class.name}: #{skynet_name}/#{version}/#{region}")
39
- @version = version
40
- @region = region
61
+ def initialize(skynet_name=self.class.skynet_name, skynet_version=self.class.skynet_version, skynet_region=self.class.skynet_region)
62
+ @skynet_name = skynet_name
63
+ @skynet_version = skynet_version
64
+ @skynet_region = skynet_region
65
+ self.logger = SemanticLogger["#{self.class.name}: #{@skynet_name}/#{@skynet_version}/#{@skynet_region}"]
66
+
67
+ raise "skynet_name is mandatory when using RubySkynet::Client directly" if @skynet_name == RubySkynet::Client.name
41
68
  end
42
69
 
43
70
  # Performs a synchronous call to the Skynet Service
@@ -56,13 +83,13 @@ module RubySkynet
56
83
  # Skynet requires BSON RPC Calls to have the following format:
57
84
  # https://github.com/skynetservices/skynet/blob/master/protocol.md
58
85
  request_id = BSON::ObjectId.new.to_s
59
- @logger.tagged request_id do
60
- @logger.benchmark_info "Called Skynet Service: #{@skynet_name}.#{method_name}" do
86
+ logger.tagged request_id do
87
+ logger.benchmark_info "Called Skynet Service: #{skynet_name}.#{method_name}" do
61
88
  retries = 0
62
89
  # If it cannot connect to a server, try a different server
63
90
  begin
64
- Connection.with_connection(::RubySkynet.services.server_for(@skynet_name, @version, @region), connection_params) do |connection|
65
- connection.rpc_call(request_id, @skynet_name, method_name, parameters)
91
+ Connection.with_connection(::RubySkynet.services.server_for(skynet_name, skynet_version, skynet_region), connection_params) do |connection|
92
+ connection.rpc_call(request_id, skynet_name, method_name, parameters)
66
93
  end
67
94
  rescue ResilientSocket::ConnectionFailure => exc
68
95
  if (retries < 3) && exc.cause.is_a?(Errno::ECONNREFUSED)
@@ -75,5 +102,19 @@ module RubySkynet
75
102
  end
76
103
  end
77
104
 
105
+ # Implement methods that call the remote Service
106
+ def method_missing(method, *args, &block)
107
+ result = call(method, *args)
108
+
109
+ # #TODO if Service returns method undefined, call super
110
+ #
111
+ # Define the method if the call was successful and no other thread has
112
+ # already created the method
113
+ if result[:exception].nil? && !self.class.method_defined?(method)
114
+ self.class.send(:define_method, method) {|*args| call(method, *args)}
115
+ end
116
+ result
117
+ end
118
+
78
119
  end
79
120
  end
@@ -12,6 +12,7 @@ require 'sync_attr'
12
12
  module RubySkynet
13
13
  class Connection
14
14
  include SyncAttr
15
+ include SemanticLogger::Loggable
15
16
 
16
17
  # Returns the underlying socket being used by a Connection instance
17
18
  attr_reader :socket
@@ -26,11 +27,6 @@ module RubySkynet
26
27
  }
27
28
  end
28
29
 
29
- # Logging instance for the connection pool
30
- sync_cattr_reader :logger do
31
- SemanticLogger::Logger.new(self)
32
- end
33
-
34
30
  # For each server there is a connection pool keyed on the
35
31
  # server address: 'host:port'
36
32
  @@connection_pools = ThreadSafe::Hash.new
@@ -55,7 +51,7 @@ module RubySkynet
55
51
  # Number of seconds between connection retry attempts after the first failed attempt
56
52
  # Default: 0.5
57
53
  def initialize(server, params = {})
58
- @logger = SemanticLogger::Logger.new("#{self.class.name}: #{server}")
54
+ self.logger = SemanticLogger["#{self.class.name} [#{server}]"]
59
55
 
60
56
  # User configurable options
61
57
  params[:read_timeout] ||= 60
@@ -71,7 +67,7 @@ module RubySkynet
71
67
  # Reset user_data on each connection
72
68
  socket.user_data = {
73
69
  :seq => 0,
74
- :logger => @logger
70
+ :logger => logger
75
71
  }
76
72
 
77
73
  # Receive Service Handshake
@@ -81,9 +77,9 @@ module RubySkynet
81
77
  #
82
78
  # ClientID string
83
79
  # ClientID is a UUID that is used by the client to identify itself in RPC requests.
84
- @logger.debug "Waiting for Service Handshake"
80
+ logger.debug "Waiting for Service Handshake"
85
81
  service_handshake = Common.read_bson_document(socket)
86
- @logger.trace 'Service Handshake', service_handshake
82
+ logger.trace 'Service Handshake', service_handshake
87
83
 
88
84
  # #TODO When a reconnect returns registered == false need to throw an exception
89
85
  # so that this host connection is not used
@@ -93,8 +89,8 @@ module RubySkynet
93
89
 
94
90
  # Send blank ClientHandshake
95
91
  client_handshake = { 'clientid' => client_id }
96
- @logger.debug "Sending Client Handshake"
97
- @logger.trace 'Client Handshake', client_handshake
92
+ logger.debug "Sending Client Handshake"
93
+ logger.trace 'Client Handshake', client_handshake
98
94
  socket.write(BSON.serialize(client_handshake).to_s)
99
95
  end
100
96
 
@@ -123,91 +119,92 @@ module RubySkynet
123
119
  # Raises RubySkynet::ProtocolError
124
120
  # Raises RubySkynet::SkynetException
125
121
  def rpc_call(request_id, skynet_name, method_name, parameters, idempotent=false)
126
- retry_count = 0
127
- header = nil
128
- response = nil
129
-
130
- socket.retry_on_connection_failure do |socket|
131
- header = {
132
- 'servicemethod' => "#{skynet_name}.Forward",
133
- 'seq' => socket.user_data[:seq]
134
- }
122
+ logger.benchmark_info "Called #{skynet_name}.#{method_name}" do
123
+ retry_count = 0
124
+ header = nil
125
+ response = nil
126
+ socket.retry_on_connection_failure do |socket|
127
+ header = {
128
+ 'servicemethod' => "#{skynet_name}.Forward",
129
+ 'seq' => socket.user_data[:seq]
130
+ }
135
131
 
136
- @logger.debug "Sending Header"
137
- @logger.trace 'Header', header
138
- socket.write(BSON.serialize(header).to_s)
139
-
140
- # The parameters are placed in the request object in BSON serialized form
141
- request = {
142
- 'clientid' => socket.user_data[:client_id],
143
- 'in' => BSON::Binary.new(BSON.serialize(parameters).to_s),
144
- 'method' => method_name.to_s,
145
- 'requestinfo' => {
146
- 'requestid' => request_id,
147
- # Increment retry count to indicate that the request may have been tried previously
148
- 'retrycount' => retry_count,
149
- # TODO: this should be forwarded along in case of services also
150
- # being a client and calling additional services. If empty it will
151
- # be stuffed with connecting address
152
- 'originaddress' => ''
132
+ logger.debug "Sending Header"
133
+ logger.trace 'Header', header
134
+ socket.write(BSON.serialize(header).to_s)
135
+
136
+ # The parameters are placed in the request object in BSON serialized form
137
+ request = {
138
+ 'clientid' => socket.user_data[:client_id],
139
+ 'in' => BSON::Binary.new(BSON.serialize(parameters).to_s),
140
+ 'method' => method_name.to_s,
141
+ 'requestinfo' => {
142
+ 'requestid' => request_id,
143
+ # Increment retry count to indicate that the request may have been tried previously
144
+ 'retrycount' => retry_count,
145
+ # TODO: this should be forwarded along in case of services also
146
+ # being a client and calling additional services. If empty it will
147
+ # be stuffed with connecting address
148
+ 'originaddress' => ''
149
+ }
153
150
  }
154
- }
155
151
 
156
- @logger.debug "Sending Request"
157
- @logger.trace 'Request', request
158
- @logger.trace 'Parameters:', parameters
159
- socket.write(BSON.serialize(request).to_s)
152
+ logger.debug "Sending Request"
153
+ logger.trace 'Request', request
154
+ logger.trace 'Parameters:', parameters
155
+ socket.write(BSON.serialize(request).to_s)
156
+
157
+ # Since Send does not affect state on the server we can also retry reads
158
+ if idempotent
159
+ logger.debug "Reading header from server"
160
+ header = Common.read_bson_document(socket)
161
+ logger.debug 'Response Header', header
162
+
163
+ # Read the BSON response document
164
+ logger.debug "Reading response from server"
165
+ response = Common.read_bson_document(socket)
166
+ logger.trace 'Response', response
167
+ end
168
+ end
160
169
 
161
- # Since Send does not affect state on the server we can also retry reads
162
- if idempotent
163
- @logger.debug "Reading header from server"
170
+ # Perform the read outside the retry block since a successful write
171
+ # means that the servers state may have been changed
172
+ unless idempotent
173
+ # Read header first as a separate BSON document
174
+ logger.debug "Reading header from server"
164
175
  header = Common.read_bson_document(socket)
165
- @logger.debug 'Response Header', header
176
+ logger.debug 'Response Header', header
166
177
 
167
178
  # Read the BSON response document
168
- @logger.debug "Reading response from server"
179
+ logger.debug "Reading response from server"
169
180
  response = Common.read_bson_document(socket)
170
- @logger.trace 'Response', response
181
+ logger.trace 'Response', response
171
182
  end
172
- end
173
183
 
174
- # Perform the read outside the retry block since a successful write
175
- # means that the servers state may have been changed
176
- unless idempotent
177
- # Read header first as a separate BSON document
178
- @logger.debug "Reading header from server"
179
- header = Common.read_bson_document(socket)
180
- @logger.debug 'Response Header', header
181
-
182
- # Read the BSON response document
183
- @logger.debug "Reading response from server"
184
- response = Common.read_bson_document(socket)
185
- @logger.trace 'Response', response
186
- end
187
-
188
- # Ensure the sequence number in the response header matches the
189
- # sequence number sent in the request
190
- seq_no = header['seq']
191
- if seq_no != socket.user_data[:seq]
192
- raise ProtocolError.new("Incorrect Response received, expected seq=#{socket.user_data[:seq]}, received: #{header.inspect}")
193
- end
184
+ # Ensure the sequence number in the response header matches the
185
+ # sequence number sent in the request
186
+ seq_no = header['seq']
187
+ if seq_no != socket.user_data[:seq]
188
+ raise ProtocolError.new("Incorrect Response received, expected seq=#{socket.user_data[:seq]}, received: #{header.inspect}")
189
+ end
194
190
 
195
- # Increment Sequence number only on successful response
196
- socket.user_data[:seq] += 1
191
+ # Increment Sequence number only on successful response
192
+ socket.user_data[:seq] += 1
197
193
 
198
- # If an error is returned from Skynet raise a Skynet exception
199
- error = header['error']
200
- raise SkynetException.new(error) if error.to_s.length > 0
194
+ # If an error is returned from Skynet raise a Skynet exception
195
+ error = header['error']
196
+ raise SkynetException.new(error) if error.to_s.length > 0
201
197
 
202
- # If an error is returned from the service raise a Service exception
203
- error = response['error']
204
- raise ServiceException.new(error) if error.to_s.length > 0
198
+ # If an error is returned from the service raise a Service exception
199
+ error = response['error']
200
+ raise ServiceException.new(error) if error.to_s.length > 0
205
201
 
206
- # Return Value
207
- # The return value is inside the response object, it's a byte array of it's own and needs to be deserialized
208
- result = BSON.deserialize(response['out'])
209
- @logger.trace 'Return Value', result
210
- result
202
+ # Return Value
203
+ # The return value is inside the response object, it's a byte array of it's own and needs to be deserialized
204
+ result = BSON.deserialize(response['out'])
205
+ logger.trace 'Return Value', result
206
+ result
207
+ end
211
208
  end
212
209
 
213
210
  # Execute the supplied block with a connection from the pool
@@ -227,10 +224,11 @@ module RubySkynet
227
224
  # Connection pool configuration options
228
225
  config = pool_config.dup
229
226
 
227
+ logger = SemanticLogger::Logger.new("#{self.class.name} [#{server}]")
228
+
230
229
  # Method to call to close idle connections
231
230
  config[:close_proc] = :close
232
231
  config[:logger] = logger
233
- config[:name] = "Connection pool for #{server}"
234
232
 
235
233
  pool = GenePool.new(pool_config) do
236
234
  new(server, params)
@@ -242,7 +240,7 @@ module RubySkynet
242
240
  # Cannot close all the connections since they could still be in use
243
241
  pool.remove_idle(0) if pool
244
242
  #pool.close if pool
245
- logger.debug "Connection pool for server:#{server} has been released"
243
+ logger.debug "Connection pool released"
246
244
  end
247
245
 
248
246
  pool
@@ -205,13 +205,13 @@ module RubySkynet
205
205
 
206
206
  # Registers a Service Class as being available at this server
207
207
  def register_service(klass)
208
- logger.debug "Registering Service: #{klass.name} with name: #{klass.skynet_name}"
208
+ logger.info "Registering Service: #{klass.name} with name: #{klass.skynet_name}"
209
209
  ::RubySkynet.services.register_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
210
210
  end
211
211
 
212
212
  # De-register service from this server
213
213
  def deregister_service(klass)
214
- logger.debug "De-registering Service: #{klass.name} with name: #{klass.skynet_name}"
214
+ logger.info "De-registering Service: #{klass.name} with name: #{klass.skynet_name}"
215
215
  ::RubySkynet.services.deregister_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
216
216
  end
217
217
 
@@ -99,7 +99,7 @@ module RubySkynet
99
99
  end
100
100
 
101
101
  # Return a server that implements the specified service
102
- def server_for(name, version='*', region='Development')
102
+ def server_for(name, version='*', region=RubySkynet.region)
103
103
  if servers = servers_for(name, version, region)
104
104
  # Randomly select one of the servers offering the service
105
105
  servers[rand(servers.size)]
@@ -111,7 +111,7 @@ module RubySkynet
111
111
  end
112
112
 
113
113
  # Returns [Array<String>] a list of servers implementing the requested service
114
- def servers_for(name, version='*', region='Development')
114
+ def servers_for(name, version='*', region=RubySkynet.region)
115
115
  if version == '*'
116
116
  # Find the highest version for the named service in this region
117
117
  version = -1
@@ -173,7 +173,6 @@ module RubySkynet
173
173
  # Add the host to the registry based on it's score
174
174
  def add_server(key, hostname, port)
175
175
  server = "#{hostname}:#{port}"
176
- logger.debug "#monitor Add/Update Service: #{key} => #{server.inspect}"
177
176
 
178
177
  server_infos = (@registry[key] ||= ThreadSafe::Array.new)
179
178
 
@@ -183,6 +182,7 @@ module RubySkynet
183
182
 
184
183
  # Look for the same score with a different server
185
184
  score = self.class.score_for_server(hostname, RubySkynet.local_ip_address)
185
+ logger.info "Service: #{key} now running at #{server} with score #{score}"
186
186
  if server_info = server_infos.find{|si| si.score == score}
187
187
  server_info.servers << server
188
188
  return server_info
@@ -206,7 +206,7 @@ module RubySkynet
206
206
  # Returns the server instance if it was removed
207
207
  def remove_server(key, hostname, port, notify)
208
208
  server = "#{hostname}:#{port}"
209
- logger.debug "Remove Service: #{key} => #{server.inspect}"
209
+ logger.info "Service: #{key} stopped running at #{server}"
210
210
  server_info = nil
211
211
  if server_infos = @registry[key]
212
212
  server_infos.each do |si|
@@ -235,7 +235,7 @@ module RubySkynet
235
235
  if @on_server_removed_callbacks && (callbacks = @on_server_removed_callbacks.delete(server))
236
236
  callbacks.each do |block|
237
237
  begin
238
- logger.info "Calling callback for server: #{server}"
238
+ logger.debug "Calling callback for server: #{server}"
239
239
  block.call(server)
240
240
  rescue Exception => exc
241
241
  logger.error("Exception during a callback for server: #{server}", exc)
@@ -1,3 +1,3 @@
1
1
  module RubySkynet #:nodoc
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
data/test/client_test.rb CHANGED
@@ -8,10 +8,8 @@ require 'shoulda'
8
8
  require 'ruby_skynet'
9
9
 
10
10
  # Register an appender if one is not already registered
11
- if SemanticLogger::Logger.appenders.size == 0
12
- SemanticLogger::Logger.default_level = :trace
13
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
14
- end
11
+ SemanticLogger.default_level = :trace
12
+ SemanticLogger.add_appender('test.log') if SemanticLogger.appenders.size == 0
15
13
 
16
14
  class ClientTestService
17
15
  include RubySkynet::Service
@@ -38,17 +36,21 @@ class ClientTestService
38
36
 
39
37
  end
40
38
 
39
+ # Test Client Class
40
+ class ClientTestServiceClient < RubySkynet::Client
41
+ end
42
+
41
43
  # Unit Test for ResilientSocket::TCPClient
42
44
  class ClientTest < Test::Unit::TestCase
43
45
  context RubySkynet::Client do
44
46
 
45
47
  context "without server" do
46
- should "raise exception when cannot reach server after 5 retries" do
48
+ should "raise exception when not registered" do
47
49
  exception = assert_raise RubySkynet::ServiceUnavailable do
48
- client = RubySkynet::Client.new('SomeService')
50
+ client = RubySkynet::Client.new('SomeService','*','ClientTest')
49
51
  client.call(:test, :hello => 'there')
50
52
  end
51
- assert_match /No servers available for service: SomeService with version: \* in region: Development/, exception.message
53
+ assert_match /No servers available for service: SomeService with version: \* in region: ClientTest/, exception.message
52
54
  end
53
55
 
54
56
  end
@@ -90,8 +92,29 @@ class ClientTest < Test::Unit::TestCase
90
92
  end
91
93
  assert_match /Timedout after #{@read_timeout} seconds trying to read/, exception.message
92
94
  end
95
+ end
96
+
97
+ context "using client class" do
98
+ setup do
99
+ @client = ClientTestServiceClient.new("ClientTestService")
100
+ end
101
+
102
+ should "successfully send and receive data" do
103
+ reply = @client.test1('some' => 'parameters')
104
+ assert_equal 'test1', reply['result']
105
+ end
93
106
 
107
+ should "timeout on receive" do
108
+ request = { 'duration' => @read_timeout + 0.5}
109
+
110
+ exception = assert_raise ResilientSocket::ReadTimeout do
111
+ # Read 4 bytes from server
112
+ @client.sleep(request, :read_timeout => @read_timeout)
113
+ end
114
+ assert_match /Timedout after #{@read_timeout} seconds trying to read/, exception.message
115
+ end
94
116
  end
117
+
95
118
  end
96
119
  end
97
120
  end
@@ -7,10 +7,8 @@ require 'shoulda'
7
7
  require 'ruby_skynet'
8
8
 
9
9
  # Register an appender if one is not already registered
10
- if SemanticLogger::Logger.appenders.size == 0
11
- SemanticLogger::Logger.default_level = :trace
12
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
13
- end
10
+ SemanticLogger.default_level = :trace
11
+ SemanticLogger.add_appender('test.log') if SemanticLogger.appenders.size == 0
14
12
 
15
13
  # Unit Test
16
14
  class ServiceRegistryTest < Test::Unit::TestCase
@@ -23,12 +21,17 @@ class ServiceRegistryTest < Test::Unit::TestCase
23
21
  @hostname = '127.0.0.1'
24
22
  @port = 2100
25
23
  @service_key = "/services/#{@service_name}/#{@version}/#{@region}/#{@hostname}/#{@port}"
24
+ RubySkynet.local_ip_address = @hostname
25
+ end
26
+
27
+ teardown do
28
+ RubySkynet.local_ip_address = nil
26
29
  end
27
30
 
28
31
  context "without a registered service" do
29
32
  should "not be in doozer" do
30
33
  RubySkynet.services.send(:doozer_pool).with_connection do |doozer|
31
- assert_equal '', doozer[@service_key]
34
+ assert_equal nil, doozer[@service_key]
32
35
  end
33
36
  end
34
37
  end
@@ -36,12 +39,14 @@ class ServiceRegistryTest < Test::Unit::TestCase
36
39
  context "with a registered service" do
37
40
  setup do
38
41
  RubySkynet.services.register_service(@service_name, @version, @region, @hostname, @port)
42
+ RubySkynet.services.register_service(@service_name, @version, @region+'BLAH', @hostname, @port)
39
43
  # Allow time for doozer callback that service was registered
40
44
  sleep 0.1
41
45
  end
42
46
 
43
47
  teardown do
44
48
  RubySkynet.services.deregister_service(@service_name, @version, @region, @hostname, @port)
49
+ RubySkynet.services.deregister_service(@service_name, @version, @region+'BLAH', @hostname, @port)
45
50
  # Allow time for doozer callback that service was deregistered
46
51
  sleep 0.1
47
52
  # No servers should be in the local registry
@@ -78,9 +83,10 @@ class ServiceRegistryTest < Test::Unit::TestCase
78
83
 
79
84
  should "using * version match" do
80
85
  assert servers = RubySkynet.services.servers_for(@service_name, '*', @region)
81
- assert_equal 3, servers.size, RubySkynet.services.to_h.to_s
82
- assert_equal "#{@hostname}:#{@port}", servers.first
83
- assert_equal "#{@hostname}:#{@port+3}", servers.last
86
+ assert_equal 3, servers.size, servers
87
+ assert_equal true, servers.include?("#{@hostname}:#{@port}"), servers
88
+ assert_equal true, servers.include?("#{@hostname}:#{@port+1}"), servers
89
+ assert_equal true, servers.include?("#{@hostname}:#{@port+3}"), servers
84
90
  end
85
91
  end
86
92
 
data/test/service_test.rb CHANGED
@@ -7,10 +7,8 @@ require 'shoulda'
7
7
  require 'ruby_skynet'
8
8
 
9
9
  # Register an appender if one is not already registered
10
- if SemanticLogger::Logger.appenders.size == 0
11
- SemanticLogger::Logger.default_level = :trace
12
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
13
- end
10
+ SemanticLogger.default_level = :trace
11
+ SemanticLogger.add_appender('test.log') if SemanticLogger.appenders.size == 0
14
12
 
15
13
  class TestService
16
14
  include RubySkynet::Service
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: 0.6.0
4
+ version: 0.7.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-04-01 00:00:00.000000000 Z
11
+ date: 2013-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: semantic_logger
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.0
19
+ version: 2.1.0
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.0.0
26
+ version: 2.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: resilient_socket
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '>='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.4.0
33
+ version: 0.5.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.4.0
40
+ version: 0.5.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: multi_json
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - '>='
74
74
  - !ruby/object:Gem::Version
75
- version: 0.5.0
75
+ version: 0.6.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '>='
81
81
  - !ruby/object:Gem::Version
82
- version: 0.5.0
82
+ version: 0.6.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: gene_pool
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -124,7 +124,6 @@ files:
124
124
  - lib/ruby_skynet/service_registry.rb
125
125
  - lib/ruby_skynet/version.rb
126
126
  - test.sh
127
- - test/base_test.rb
128
127
  - test/client_test.rb
129
128
  - test/service_registry_test.rb
130
129
  - test/service_test.rb
data/test/base_test.rb DELETED
@@ -1,89 +0,0 @@
1
- # Allow test to be run in-place without requiring a gem install
2
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
- $LOAD_PATH.unshift File.dirname(__FILE__)
4
-
5
- require 'rubygems'
6
- require 'test/unit'
7
- require 'shoulda'
8
- require 'ruby_skynet'
9
-
10
- # Register an appender if one is not already registered
11
- if SemanticLogger::Logger.appenders.size == 0
12
- SemanticLogger::Logger.default_level = :debug
13
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
14
- end
15
-
16
- # Service implementation
17
- class BaseTestService
18
- include RubySkynet::Service
19
-
20
- # Methods implemented by this service
21
- # Must take a Hash as input
22
- # Must Return a Hash response or nil for no response
23
- def test1(params)
24
- { 'result' => 'test1' }
25
- end
26
-
27
- def sleep(params)
28
- Kernel.sleep params['duration'] || 1
29
- { 'result' => 'sleep' }
30
- end
31
-
32
- def fail(params)
33
- if params['attempt'].to_i >= 2
34
- { 'result' => 'fail' }
35
- else
36
- nil
37
- end
38
- end
39
-
40
- end
41
-
42
- # Service Client
43
- class BaseTestServiceClient
44
- include RubySkynet::Base
45
-
46
- # Override Name registered in skynet to match server above
47
- self.skynet_name = 'BaseTestService'
48
- end
49
-
50
- # Unit Test
51
- class BaseTest < Test::Unit::TestCase
52
- context RubySkynet::Base do
53
-
54
- context "with server" do
55
- setup do
56
- RubySkynet.region = @region
57
- RubySkynet::Server.start
58
-
59
- @read_timeout = 3.0
60
- end
61
-
62
- teardown do
63
- RubySkynet::Server.stop
64
- end
65
-
66
- context "with client connection" do
67
- setup do
68
- @client = BaseTestServiceClient.new
69
- end
70
-
71
- should "successfully send and receive data" do
72
- reply = @client.test1('some' => 'parameters')
73
- assert_equal 'test1', reply['result']
74
- end
75
-
76
- should "timeout on receive" do
77
- request = { 'duration' => @read_timeout + 0.5}
78
-
79
- exception = assert_raise ResilientSocket::ReadTimeout do
80
- # Read 4 bytes from server
81
- @client.sleep(request, :read_timeout => @read_timeout)
82
- end
83
- assert_match /Timedout after #{@read_timeout} seconds trying to read/, exception.message
84
- end
85
-
86
- end
87
- end
88
- end
89
- end