istox_gruf 2.7.1
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 +7 -0
- data/CHANGELOG.md +246 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/README.md +544 -0
- data/bin/gruf +29 -0
- data/lib/gruf.rb +50 -0
- data/lib/gruf/cli/executor.rb +99 -0
- data/lib/gruf/client.rb +217 -0
- data/lib/gruf/client/error.rb +66 -0
- data/lib/gruf/client/error_factory.rb +105 -0
- data/lib/gruf/configuration.rb +137 -0
- data/lib/gruf/controllers/base.rb +102 -0
- data/lib/gruf/controllers/request.rb +121 -0
- data/lib/gruf/controllers/service_binder.rb +117 -0
- data/lib/gruf/error.rb +230 -0
- data/lib/gruf/errors/debug_info.rb +56 -0
- data/lib/gruf/errors/field.rb +56 -0
- data/lib/gruf/errors/helpers.rb +44 -0
- data/lib/gruf/hooks/base.rb +34 -0
- data/lib/gruf/hooks/executor.rb +47 -0
- data/lib/gruf/hooks/registry.rb +159 -0
- data/lib/gruf/instrumentable_grpc_server.rb +64 -0
- data/lib/gruf/integrations/rails/railtie.rb +10 -0
- data/lib/gruf/interceptors/active_record/connection_reset.rb +48 -0
- data/lib/gruf/interceptors/authentication/basic.rb +87 -0
- data/lib/gruf/interceptors/base.rb +53 -0
- data/lib/gruf/interceptors/client_interceptor.rb +125 -0
- data/lib/gruf/interceptors/context.rb +56 -0
- data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +61 -0
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +41 -0
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +43 -0
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +48 -0
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +225 -0
- data/lib/gruf/interceptors/instrumentation/statsd.rb +82 -0
- data/lib/gruf/interceptors/registry.rb +161 -0
- data/lib/gruf/interceptors/server_interceptor.rb +34 -0
- data/lib/gruf/interceptors/timer.rb +85 -0
- data/lib/gruf/loggable.rb +30 -0
- data/lib/gruf/logging.rb +53 -0
- data/lib/gruf/outbound/request_context.rb +71 -0
- data/lib/gruf/response.rb +71 -0
- data/lib/gruf/serializers/errors/base.rb +57 -0
- data/lib/gruf/serializers/errors/json.rb +43 -0
- data/lib/gruf/server.rb +294 -0
- data/lib/gruf/synchronized_client.rb +97 -0
- data/lib/gruf/timer.rb +78 -0
- data/lib/gruf/version.rb +20 -0
- metadata +203 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
6
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
7
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
11
|
+
# Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
14
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
15
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
|
+
#
|
18
|
+
module Gruf
|
19
|
+
class Client < SimpleDelegator
|
20
|
+
##
|
21
|
+
# Translates exceptions into Gruf::Client::Errors
|
22
|
+
#
|
23
|
+
class ErrorFactory
|
24
|
+
##
|
25
|
+
# @param [Class] default_class
|
26
|
+
# @param [Class] deserializer_class
|
27
|
+
# @param [String|Symbol] metadata_key
|
28
|
+
#
|
29
|
+
def initialize(
|
30
|
+
default_class: nil,
|
31
|
+
deserializer_class: nil,
|
32
|
+
metadata_key: nil
|
33
|
+
)
|
34
|
+
@default_class = default_class || Gruf::Client::Errors::Internal
|
35
|
+
@metadata_key = (metadata_key || Gruf.error_metadata_key).to_s
|
36
|
+
@deserializer_class = deserializer_class || default_serializer
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Determine the proper error class to raise given the incoming exception. This will attempt to coalesce the
|
41
|
+
# exception object into the appropriate Gruf::Client::Errors subclass, or fallback to the default class if none
|
42
|
+
# is found (or it is a StandardError or higher-level error). It will leave alone Signals instead of attempting to
|
43
|
+
# coalesce them.
|
44
|
+
#
|
45
|
+
# @param [Exception] exception
|
46
|
+
# @return [Gruf::Client::Errors::Base|SignalException]
|
47
|
+
#
|
48
|
+
def from_exception(exception)
|
49
|
+
# passthrough on Signals, we don't want to mess with these
|
50
|
+
return exception if exception.is_a?(SignalException)
|
51
|
+
|
52
|
+
exception_class = determine_class(exception)
|
53
|
+
if exception.is_a?(GRPC::BadStatus)
|
54
|
+
# if it's a GRPC::BadStatus code, let's check for any trailing error metadata and decode it
|
55
|
+
exception_class.new(deserialize(exception))
|
56
|
+
else
|
57
|
+
# otherwise, let's just capture the error and build the wrapper class
|
58
|
+
exception_class.new(exception)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
##
|
65
|
+
# Deserialize any trailing metadata error payload from the exception
|
66
|
+
#
|
67
|
+
# @param [Gruf::Client::Errors::Base]
|
68
|
+
# @return [String]
|
69
|
+
#
|
70
|
+
def deserialize(exception)
|
71
|
+
if exception.respond_to?(:metadata)
|
72
|
+
key = exception.metadata.key?(@metadata_key.to_s) ? @metadata_key.to_s : @metadata_key.to_sym
|
73
|
+
return @deserializer_class.new(exception.metadata[key]).deserialize if exception.metadata.key?(key)
|
74
|
+
end
|
75
|
+
|
76
|
+
exception
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# @param [Exception] exception
|
81
|
+
# @return [Gruf::Client::Errors::Base]
|
82
|
+
#
|
83
|
+
def determine_class(exception)
|
84
|
+
error_class = Gruf::Client::Errors.const_get(exception.class.name.demodulize)
|
85
|
+
|
86
|
+
# Ruby module inheritance will have StandardError, ScriptError, etc still get to this point
|
87
|
+
# So we need to explicitly check for ancestry here
|
88
|
+
return @default_class unless error_class.ancestors.include?(Gruf::Client::Errors::Base)
|
89
|
+
|
90
|
+
error_class
|
91
|
+
rescue NameError => _e
|
92
|
+
@default_class
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# @return [Gruf::Serializers::Errors::Base]
|
97
|
+
#
|
98
|
+
def default_serializer
|
99
|
+
return Gruf::Serializers::Errors::Json unless Gruf.error_serializer
|
100
|
+
|
101
|
+
Gruf.error_serializer.is_a?(Class) ? Gruf.error_serializer : Gruf.error_serializer.to_s.constantize
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
6
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
7
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
11
|
+
# Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
14
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
15
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
|
+
#
|
18
|
+
module Gruf
|
19
|
+
##
|
20
|
+
# Represents configuration settings for the system
|
21
|
+
#
|
22
|
+
module Configuration
|
23
|
+
VALID_CONFIG_KEYS = {
|
24
|
+
root_path: '',
|
25
|
+
server_binding_url: '0.0.0.0:9001',
|
26
|
+
server_options: {},
|
27
|
+
interceptors: nil,
|
28
|
+
hooks: nil,
|
29
|
+
default_client_host: '',
|
30
|
+
use_ssl: false,
|
31
|
+
ssl_crt_file: '',
|
32
|
+
ssl_key_file: '',
|
33
|
+
controllers_path: '',
|
34
|
+
services: [],
|
35
|
+
logger: nil,
|
36
|
+
grpc_logger: nil,
|
37
|
+
error_metadata_key: :'error-internal-bin',
|
38
|
+
error_serializer: nil,
|
39
|
+
append_server_errors_to_trailing_metadata: true,
|
40
|
+
use_default_interceptors: true,
|
41
|
+
backtrace_on_error: false,
|
42
|
+
backtrace_limit: 10,
|
43
|
+
use_exception_message: true,
|
44
|
+
internal_error_message: 'Internal Server Error',
|
45
|
+
event_listener_proc: nil,
|
46
|
+
synchronized_client_internal_cache_expiry: 60,
|
47
|
+
rpc_server_options: {
|
48
|
+
pool_size: GRPC::RpcServer::DEFAULT_POOL_SIZE,
|
49
|
+
max_waiting_requests: GRPC::RpcServer::DEFAULT_MAX_WAITING_REQUESTS,
|
50
|
+
poll_period: GRPC::RpcServer::DEFAULT_POLL_PERIOD,
|
51
|
+
pool_keep_alive: GRPC::Pool::DEFAULT_KEEP_ALIVE,
|
52
|
+
connect_md_proc: nil,
|
53
|
+
server_args: {}
|
54
|
+
}.freeze
|
55
|
+
}.freeze
|
56
|
+
|
57
|
+
attr_accessor(* VALID_CONFIG_KEYS.keys)
|
58
|
+
|
59
|
+
##
|
60
|
+
# Whenever this is extended into a class, setup the defaults
|
61
|
+
#
|
62
|
+
def self.extended(base)
|
63
|
+
if defined?(Rails)
|
64
|
+
Gruf::Integrations::Rails::Railtie.config.before_initialize { base.reset }
|
65
|
+
else
|
66
|
+
base.reset
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Yield self for ruby-style initialization
|
72
|
+
#
|
73
|
+
# @yields [Gruf::Configuration] The configuration object for gruf
|
74
|
+
# @return [Gruf::Configuration] The configuration object for gruf
|
75
|
+
#
|
76
|
+
def configure
|
77
|
+
yield self
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Return the current configuration options as a Hash
|
82
|
+
#
|
83
|
+
# @return [Hash] The configuration for gruf, represented as a Hash
|
84
|
+
#
|
85
|
+
def options
|
86
|
+
opts = {}
|
87
|
+
VALID_CONFIG_KEYS.each_key do |k|
|
88
|
+
opts.merge!(k => send(k))
|
89
|
+
end
|
90
|
+
opts
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Set the default configuration onto the extended class
|
95
|
+
#
|
96
|
+
# @return [Hash] options The reset options hash
|
97
|
+
#
|
98
|
+
def reset
|
99
|
+
VALID_CONFIG_KEYS.each do |k, v|
|
100
|
+
send((k.to_s + '='), v)
|
101
|
+
end
|
102
|
+
self.interceptors = Gruf::Interceptors::Registry.new
|
103
|
+
self.hooks = Gruf::Hooks::Registry.new
|
104
|
+
self.root_path = Rails.root.to_s.chomp('/') if defined?(Rails)
|
105
|
+
if defined?(Rails) && Rails.logger
|
106
|
+
self.logger = Rails.logger
|
107
|
+
else
|
108
|
+
require 'logger'
|
109
|
+
self.logger = ::Logger.new(STDOUT)
|
110
|
+
end
|
111
|
+
self.grpc_logger = logger if grpc_logger.nil?
|
112
|
+
self.ssl_crt_file = "#{root_path}config/ssl/#{environment}.crt"
|
113
|
+
self.ssl_key_file = "#{root_path}config/ssl/#{environment}.key"
|
114
|
+
self.controllers_path = root_path.to_s.empty? ? 'app/rpc' : "#{root_path}/app/rpc"
|
115
|
+
if use_default_interceptors
|
116
|
+
interceptors.use(Gruf::Interceptors::ActiveRecord::ConnectionReset)
|
117
|
+
interceptors.use(Gruf::Interceptors::Instrumentation::OutputMetadataTimer)
|
118
|
+
end
|
119
|
+
options
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
##
|
125
|
+
# Automatically determine environment
|
126
|
+
#
|
127
|
+
# @return [String] The current Ruby environment
|
128
|
+
#
|
129
|
+
def environment
|
130
|
+
if defined?(Rails)
|
131
|
+
Rails.env.to_s
|
132
|
+
else
|
133
|
+
(ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development').to_s
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
6
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
7
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
11
|
+
# Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
14
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
15
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
|
+
#
|
18
|
+
require_relative 'request'
|
19
|
+
require_relative 'service_binder'
|
20
|
+
|
21
|
+
module Gruf
|
22
|
+
module Controllers
|
23
|
+
##
|
24
|
+
# Base controller object for Gruf gRPC requests
|
25
|
+
#
|
26
|
+
class Base
|
27
|
+
include Gruf::Errors::Helpers
|
28
|
+
|
29
|
+
# @var [Gruf::Controller::Request] request
|
30
|
+
attr_reader :request
|
31
|
+
# @var [Gruf::Error] error
|
32
|
+
attr_reader :error
|
33
|
+
|
34
|
+
class << self
|
35
|
+
# @var [GRPC::GenericService] bound_service
|
36
|
+
attr_reader :bound_service
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Initialize the controller within the given request context
|
41
|
+
#
|
42
|
+
# @param [Symbol] method_key The gRPC method that this controller relates to
|
43
|
+
# @param [GRPC::GenericService] service The gRPC service stub for this controller
|
44
|
+
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor for this service method
|
45
|
+
# @param [GRPC::ActiveCall] active_call The gRPC ActiveCall object
|
46
|
+
# @param [Google::Protobuf::MessageExts] message The incoming protobuf request message
|
47
|
+
#
|
48
|
+
def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
|
49
|
+
@request = Request.new(
|
50
|
+
method_key: method_key,
|
51
|
+
service: service,
|
52
|
+
rpc_desc: rpc_desc,
|
53
|
+
active_call: active_call,
|
54
|
+
message: message
|
55
|
+
)
|
56
|
+
@error = Gruf::Error.new
|
57
|
+
@interceptors = Gruf.interceptors.prepare(@request, @error)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Bind the controller to the given service and add it to the service registry
|
62
|
+
#
|
63
|
+
# @param [GRPC::GenericService] service The name of the service to bind this controller to
|
64
|
+
#
|
65
|
+
def self.bind(service)
|
66
|
+
service_class = service.name.constantize
|
67
|
+
Gruf.services << service_class
|
68
|
+
@bound_service = service_class
|
69
|
+
ServiceBinder.new(service_class).bind!(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Call a method on this controller.
|
74
|
+
# Override this in a subclass to modify the behavior around processing a method
|
75
|
+
#
|
76
|
+
# @param [Symbol] method_key The name of the gRPC service method being called as a Symbol
|
77
|
+
# @param [block] &block The passed block for executing the method
|
78
|
+
#
|
79
|
+
def process_action(method_key, &block)
|
80
|
+
send(method_key, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Call a method on this controller
|
85
|
+
#
|
86
|
+
# @param [Symbol] method_key The name of the gRPC service method being called as a Symbol
|
87
|
+
# @param [block] &block The passed block for executing the method
|
88
|
+
#
|
89
|
+
def call(method_key, &block)
|
90
|
+
Interceptors::Context.new(@interceptors).intercept! do
|
91
|
+
process_action(method_key, &block)
|
92
|
+
end
|
93
|
+
rescue GRPC::BadStatus
|
94
|
+
raise # passthrough, to be caught by Gruf::Interceptors::Timer
|
95
|
+
rescue GRPC::Core::CallError, StandardError => e # CallError is not a StandardError
|
96
|
+
set_debug_info(e.message, e.backtrace) if Gruf.backtrace_on_error
|
97
|
+
error_message = Gruf.use_exception_message ? e.message : Gruf.internal_error_message
|
98
|
+
fail!(:internal, :unknown, error_message)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
6
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
7
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
11
|
+
# Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
14
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
15
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
|
+
#
|
18
|
+
module Gruf
|
19
|
+
module Controllers
|
20
|
+
##
|
21
|
+
# Encapsulates a request for a controller
|
22
|
+
#
|
23
|
+
class Request
|
24
|
+
# @var [Object] message
|
25
|
+
attr_reader :message
|
26
|
+
# @var [GRPC::ActiveCall] active_call
|
27
|
+
attr_reader :active_call
|
28
|
+
# @var [Symbol] method_key
|
29
|
+
attr_reader :method_key
|
30
|
+
# @var [Gruf::Controllers::Request::Type] type
|
31
|
+
attr_reader :type
|
32
|
+
# @var [Class] service
|
33
|
+
attr_reader :service
|
34
|
+
|
35
|
+
delegate :metadata, to: :active_call
|
36
|
+
delegate :messages, :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :type
|
37
|
+
|
38
|
+
##
|
39
|
+
# Abstract representation of a gRPC request type
|
40
|
+
#
|
41
|
+
class Type
|
42
|
+
delegate :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :@rpc_desc
|
43
|
+
|
44
|
+
##
|
45
|
+
# Initialize a new request type object
|
46
|
+
#
|
47
|
+
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor for the request type
|
48
|
+
#
|
49
|
+
def initialize(rpc_desc)
|
50
|
+
@rpc_desc = rpc_desc
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Initialize an inbound controller request object
|
56
|
+
#
|
57
|
+
# @param [Symbol] method_key The method symbol of the RPC method being executed
|
58
|
+
# @param [Class] service The class of the service being executed against
|
59
|
+
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor of the call
|
60
|
+
# @param [GRPC::ActiveCall] active_call The restricted view of the call
|
61
|
+
# @param [Object] message The protobuf message (or messages) of the request
|
62
|
+
#
|
63
|
+
def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
|
64
|
+
@method_key = method_key
|
65
|
+
@service = service
|
66
|
+
@active_call = active_call
|
67
|
+
@message = message
|
68
|
+
@rpc_desc = rpc_desc
|
69
|
+
@type = Type.new(rpc_desc)
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Returns the service name as a translated name separated by periods. Strips
|
74
|
+
# the superfluous "Service" suffix from the name
|
75
|
+
#
|
76
|
+
# @return [String] The mapped service key
|
77
|
+
#
|
78
|
+
def service_key
|
79
|
+
@service.name.underscore.tr('/', '.').gsub('.service', '')
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# @return [Class] The class of the response message
|
84
|
+
#
|
85
|
+
def response_class
|
86
|
+
@rpc_desc.output
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# @return [Class] The class of the request message
|
91
|
+
#
|
92
|
+
def request_class
|
93
|
+
@rpc_desc.input
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Parse the method signature into a service.method name format
|
98
|
+
#
|
99
|
+
# @return [String] The parsed service method name
|
100
|
+
#
|
101
|
+
def method_name
|
102
|
+
"#{service_key}.#{method_key}"
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Return all messages for this request, properly handling different request types
|
107
|
+
#
|
108
|
+
# @return Enumerable<Object> All messages for this request
|
109
|
+
#
|
110
|
+
def messages
|
111
|
+
if client_streamer?
|
112
|
+
message.call { |msg| yield msg }
|
113
|
+
elsif bidi_streamer?
|
114
|
+
message
|
115
|
+
else
|
116
|
+
[message]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|