Class: Protobuf::Rpc::Service
- Inherits:
-
Object
- Object
- Protobuf::Rpc::Service
- Includes:
- Logger::LogMethods
- Defined in:
- lib/protobuf/rpc/service.rb
Constant Summary collapse
- DEFAULT_LOCATION =
{ :host => '127.0.0.1', :port => 9399 }
- NON_RPC_METHODS =
You MUST add the method name to this list if you are adding instance methods below, otherwise stuff will definitely break
%w( rpcs call_rpc on_rpc_failed rpc_failed request response method_missing async_responder on_send_response send_response log_signature )
Instance Attribute Summary collapse
-
#async_responder ⇒ Object
Returns the value of attribute async_responder.
Class Method Summary collapse
-
.client(options = {}) ⇒ Object
Create a new client for the given service.
-
.configure(config = {}) ⇒ Object
Allows service-level configuration of location.
-
.host ⇒ Object
The host location of the service.
-
.located_at(location) ⇒ Object
Shorthand call to configure, passing a string formatted as hostname:port e.g.
-
.locations ⇒ Object
Shorthand for @locations class instance var.
-
.method_added(old) ⇒ Object
Override methods being added to the class If the method isn't already a private instance method, or it doesn't start with rpc_, or it isn't in the reserved method list (NON_RPC_METHODS), We want to remap the method such that we can wrap it in before and after behavior, most notably calling call_rpc against the method.
-
.port ⇒ Object
The port of the service on the destination server.
-
.rpc(method, request_type, response_type) ⇒ Object
Generated service classes should call this method on themselves to add rpc methods to the stack with a given request and response type.
-
.rpcs ⇒ Object
Shorthand for @rpcs class instance var.
Instance Method Summary collapse
- #log_signature ⇒ Object
-
#method_missing(m, *params) ⇒ Object
If a method comes through that hasn't been found, and it is defined in the rpcs method list, we know that the rpc stub has been created, but no implementing method provides the functionality, so throw an appropriate error, otherwise go to super.
-
#on_rpc_failed(&rpc_failure_cb) ⇒ Object
Callback register for the server when a service method calls rpc_failed.
-
#on_send_response(&responder) ⇒ Object
Callback register for the server to be notified when it is appropriate to generate a response to the client.
-
#rpc_failed(message = "RPC Failed while executing service method #{@current_method}") ⇒ Object
Automatically fail a service method.
-
#rpcs ⇒ Object
Convenience wrapper around the rpc method list for a given class.
-
#send_response ⇒ Object
Tell the server to generate response and send it to the client.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(m, *params) ⇒ Object
If a method comes through that hasn't been found, and it is defined in the rpcs method list, we know that the rpc stub has been created, but no implementing method provides the functionality, so throw an appropriate error, otherwise go to super
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/protobuf/rpc/service.rb', line 127 def method_missing m, *params if rpcs.key?(m) exc = MethodNotFound.new "#{self}##{m} was defined as a valid rpc method, but was not implemented." log_error exc. raise exc else log_error "-------------- [#{log_signature}] %s#%s not rpc method, passing to super" % [self.class.name, m.to_s] super m, params end end |
Instance Attribute Details
#async_responder ⇒ Object
Returns the value of attribute async_responder.
15 16 17 |
# File 'lib/protobuf/rpc/service.rb', line 15 def async_responder @async_responder end |
Class Method Details
.client(options = {}) ⇒ Object
Create a new client for the given service. See Client#initialize and ClientConnection::DEFAULT_OPTIONS for all available options.
68 69 70 71 72 73 74 75 76 |
# File 'lib/protobuf/rpc/service.rb', line 68 def client(={}) configure Client.new({ :service => self, :async => false, :host => self.host, :port => self.port }.merge()) end |
.configure(config = {}) ⇒ Object
Allows service-level configuration of location. Useful for system-startup configuration of a service so that any Clients using the Service.client sugar will not have to configure the location each time.
83 84 85 86 87 |
# File 'lib/protobuf/rpc/service.rb', line 83 def configure(config={}) locations[self] ||= {} locations[self][:host] = config[:host] if config.key?(:host) locations[self][:port] = config[:port] if config.key?(:port) end |
.host ⇒ Object
The host location of the service
100 101 102 103 |
# File 'lib/protobuf/rpc/service.rb', line 100 def host configure locations[self][:host] || DEFAULT_LOCATION[:host] end |
.located_at(location) ⇒ Object
Shorthand call to configure, passing a string formatted as hostname:port e.g. 127.0.0.1:9933 e.g. localhost:0
93 94 95 96 97 |
# File 'lib/protobuf/rpc/service.rb', line 93 def located_at(location) return if location.nil? or location.downcase.strip !~ /[a-z0-9.]+:\d+/ host, port = location.downcase.strip.split ':' configure :host => host, :port => port.to_i end |
.locations ⇒ Object
Shorthand for @locations class instance var
112 113 114 |
# File 'lib/protobuf/rpc/service.rb', line 112 def locations @locations ||= {} end |
.method_added(old) ⇒ Object
Override methods being added to the class If the method isn't already a private instance method, or it doesn't start with rpc_, or it isn't in the reserved method list (NON_RPC_METHODS), We want to remap the method such that we can wrap it in before and after behavior, most notably calling call_rpc against the method. See call_rpc for more info.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/protobuf/rpc/service.rb', line 36 def method_added(old) new_method = :"rpc_#{old}" return if private_instance_methods.include?(new_method) or old =~ /^rpc_/ or NON_RPC_METHODS.include?(old.to_s) alias_method new_method, old private new_method define_method(old) do |pb_request| call_rpc(old.to_sym, pb_request) end rescue ArgumentError => e # Wrap a known issue where an instance method was defined in the class without # it being ignored with NON_RPC_METHODS. raise ArgumentError, "#{e.} (Note: This could mean that you need to add the method #{old} to the NON_RPC_METHODS list)" end |
.port ⇒ Object
The port of the service on the destination server
106 107 108 109 |
# File 'lib/protobuf/rpc/service.rb', line 106 def port configure locations[self][:port] || DEFAULT_LOCATION[:port] end |
.rpc(method, request_type, response_type) ⇒ Object
Generated service classes should call this method on themselves to add rpc methods to the stack with a given request and response type
54 55 56 57 |
# File 'lib/protobuf/rpc/service.rb', line 54 def rpc(method, request_type, response_type) rpcs[self] ||= {} rpcs[self][method] = RpcMethod.new self, method, request_type, response_type end |
.rpcs ⇒ Object
Shorthand for @rpcs class instance var
60 61 62 |
# File 'lib/protobuf/rpc/service.rb', line 60 def rpcs @rpcs ||= {} end |
Instance Method Details
#log_signature ⇒ Object
118 119 120 |
# File 'lib/protobuf/rpc/service.rb', line 118 def log_signature @log_signature ||= "service-#{self.class}" end |
#on_rpc_failed(&rpc_failure_cb) ⇒ Object
Callback register for the server when a service method calls rpc_failed. Called by Service#rpc_failed.
145 146 147 |
# File 'lib/protobuf/rpc/service.rb', line 145 def on_rpc_failed(&rpc_failure_cb) @rpc_failure_cb = rpc_failure_cb end |
#on_send_response(&responder) ⇒ Object
Callback register for the server to be notified when it is appropriate to generate a response to the client. Used in conjunciton with Service#send_response.
165 166 167 |
# File 'lib/protobuf/rpc/service.rb', line 165 def on_send_response(&responder) @responder = responder end |
#rpc_failed(message = "RPC Failed while executing service method #{@current_method}") ⇒ Object
Automatically fail a service method. NOTE: This shortcuts the @async_responder paradigm. There is not any way to get around this currently (and I'm not sure you should want to).
153 154 155 156 157 158 159 |
# File 'lib/protobuf/rpc/service.rb', line 153 def rpc_failed(="RPC Failed while executing service method #{@current_method}") = 'Unable to invoke rpc_failed, no failure callback is setup.' log_and_raise_error() if @rpc_failure_cb.nil? error = .is_a?(String) ? RpcFailed.new() : log_warn "[#{log_signature}] RPC Failed: %s" % error. @rpc_failure_cb.call(error) end |
#rpcs ⇒ Object
Convenience wrapper around the rpc method list for a given class
139 140 141 |
# File 'lib/protobuf/rpc/service.rb', line 139 def rpcs self.class.rpcs[self.class] end |
#send_response ⇒ Object
Tell the server to generate response and send it to the client.
NOTE: If @async_responder is set to true, this MUST be called by the implementing service method, otherwise the connection will timeout since no data will be sent.
175 176 177 178 179 |
# File 'lib/protobuf/rpc/service.rb', line 175 def send_response = "Unable to send response, responder is nil. It appears you aren't inside of an RPC request/response cycle." log_and_raise_error() if @responder.nil? @responder.call(@response) end |