lib/ruby_skynet/client.rb in ruby_skynet-0.6.0 vs lib/ruby_skynet/client.rb in ruby_skynet-0.7.0
- old
+ new
@@ -6,40 +6,67 @@
# RPC calls to Skynet
# Skynet Service autodiscovery
#
module RubySkynet
class Client
+ include Base
+
+ attr_reader :skynet_name, :skynet_version, :skynet_region
+
+ # Version of the Skynet service to use
+ # By default it will connect to the latest version
+ # Default: '*'
+ def self.skynet_version
+ @skynet_version ||= '*'
+ end
+
# Returns a new RubySkynet Client for the named service
#
# Calls to an instance of the Client are thread-safe and can be called
# concurrently from multiple threads at the same time
#
# Parameters:
# :skynet_name
+ # Only required when creating instance of RubySkynet::Client directly
+ # Otherwise it defaults to the name of the class
# Name of the service to look for and connect to on Skynet
#
- # :version
+ # :skynet_version
# Optional version number of the service in Skynet
# Default: '*' being the latest version of the service
#
- # :region
+ # :skynet_region
# Optional region for this service in Skynet
- # Default: 'Development'
+ # Default: RubySkynet.region
#
- # Example
+ # Example using Client class
#
# require 'ruby_skynet'
- # SemanticLogger.default_level = :trace
- # SemanticLogger.appenders << SemanticLogger::Appender::File(STDOUT)
+ # SemanticLogger.default_level = :info
+ # SemanticLogger.add_appender(STDOUT)
#
+ # class EchoService < RubySkynet::Client
+ # end
+ #
+ # echo_service = EchoService.new
+ # p echo_service.echo(:value => 5)
+ #
+ # Example using Ruby Client directly
+ #
+ # require 'ruby_skynet'
+ # SemanticLogger.default_level = :info
+ # SemanticLogger.add_appender(STDOUT)
+ #
# tutorial_service = RubySkynet::Client.new('TutorialService')
# p tutorial_service.call('Add', :value => 5)
- def initialize(skynet_name, version='*', region='Development')
- @skynet_name = skynet_name
- @logger = SemanticLogger::Logger.new("#{self.class.name}: #{skynet_name}/#{version}/#{region}")
- @version = version
- @region = region
+ def initialize(skynet_name=self.class.skynet_name, skynet_version=self.class.skynet_version, skynet_region=self.class.skynet_region)
+ @skynet_name = skynet_name
+ @skynet_version = skynet_version
+ @skynet_region = skynet_region
+ self.logger = SemanticLogger["#{self.class.name}: #{@skynet_name}/#{@skynet_version}/#{@skynet_region}"]
+
+ raise "skynet_name is mandatory when using RubySkynet::Client directly" if @skynet_name == RubySkynet::Client.name
end
# Performs a synchronous call to the Skynet Service
#
# Parameters:
@@ -54,26 +81,40 @@
# Raises RubySkynet::SkynetException
def call(method_name, parameters, connection_params={})
# Skynet requires BSON RPC Calls to have the following format:
# https://github.com/skynetservices/skynet/blob/master/protocol.md
request_id = BSON::ObjectId.new.to_s
- @logger.tagged request_id do
- @logger.benchmark_info "Called Skynet Service: #{@skynet_name}.#{method_name}" do
+ logger.tagged request_id do
+ logger.benchmark_info "Called Skynet Service: #{skynet_name}.#{method_name}" do
retries = 0
# If it cannot connect to a server, try a different server
begin
- Connection.with_connection(::RubySkynet.services.server_for(@skynet_name, @version, @region), connection_params) do |connection|
- connection.rpc_call(request_id, @skynet_name, method_name, parameters)
+ Connection.with_connection(::RubySkynet.services.server_for(skynet_name, skynet_version, skynet_region), connection_params) do |connection|
+ connection.rpc_call(request_id, skynet_name, method_name, parameters)
end
rescue ResilientSocket::ConnectionFailure => exc
if (retries < 3) && exc.cause.is_a?(Errno::ECONNREFUSED)
retries += 1
retry
end
# TODO rescue ServiceUnavailable retry x times until the service becomes available
end
end
end
+ end
+
+ # Implement methods that call the remote Service
+ def method_missing(method, *args, &block)
+ result = call(method, *args)
+
+ # #TODO if Service returns method undefined, call super
+ #
+ # Define the method if the call was successful and no other thread has
+ # already created the method
+ if result[:exception].nil? && !self.class.method_defined?(method)
+ self.class.send(:define_method, method) {|*args| call(method, *args)}
+ end
+ result
end
end
end