gruf 2.8.1 → 2.11.0

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
  SHA256:
3
- metadata.gz: 9118663c1224b49c07fe40743b6766121b1be507301e4ca64f2f3e7ef18a5b25
4
- data.tar.gz: 2025ab3f6f93b8c13bdb983e869a003415d3933340e94f15eb866d65826f954b
3
+ metadata.gz: d00ffbd4089fa41fd29adb1848564ee695725576045f447255173ebb170df586
4
+ data.tar.gz: 55c8ca35a37cae3e5c03bec59c1073fe40e3ed919586cb33bdfd83dad7da2b54
5
5
  SHA512:
6
- metadata.gz: ffd6e423548aeb8785e7063618875298b9f13570e8e1fc6b5cf24d2426059d4e98c9d3414f179a4fd071d6b4263f279666c38ca2439dfa0e7937cc2dfa79af84
7
- data.tar.gz: 5ee7fbe4964edbda7b90192ff5432a3d61897d08896a84676ae19d5c105aab6287c48f6c02368a10c0e75d9eaa1e784f8748564cc86dc2c7bf0762106b27b4fe
6
+ metadata.gz: 44acc6b979feb388fc7fee273848d36b8bb4db4228d7fab6b678ab2ed69b90742e927705c1982643f23a4170be8e8918a1cab96beb146071f191871f39c54bcc
7
+ data.tar.gz: cf79b333165e7eb458a44c9f09b8069135ff7c2fa7041193abbdd0af7fcf5ff20dd2e45ffeec94d036aa7822f2c8fffd3f3c969a2d41fcf3fbd17f1181c8ebe4
data/CHANGELOG.md CHANGED
@@ -2,6 +2,41 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
2
2
 
3
3
  ### Pending release
4
4
 
5
+ ### 2.11.0
6
+
7
+ - Restrict grpc gem to <= 1.41.0 due to regressions in grpc 1.42.x
8
+ - Fallback to stdout logger at INFO if no logger is setup
9
+ - Better handling of namespace collisions with Rails
10
+ - Add `GRPC_SERVER_HOST` and `GRPC_SERVER_PORT` for ENV configuration of the server host+port
11
+ - Add `GRPC_BACKTRACE_ON_ERROR` as available ENV configuration
12
+ - Add default ENV-based configuration of the GRPC server pool
13
+ - `GRPC_SERVER_POOL_SIZE` - sets the size of the GRPC server pool
14
+ - `GRPC_SERVER_POOL_KEEP_ALIVE` - keep alive time for threads spawned by the server pool
15
+ - `GRPC_SERVER_POLL_PERIOD` - period in seconds to poll for workers in the gRPC server pool
16
+ - Improve Yardoc support across the library
17
+ - Added attribute-based documentation for Gruf configuration options
18
+ - Add mfa required for gemspec metadata
19
+
20
+ ### 2.10.0
21
+
22
+ - Drop support for Ruby 2.4/2.5 to align with Ruby EOL schedule, supporting 2.6+ only
23
+ - Allow for float/TimeSpec timeout values on clients
24
+
25
+ ### 2.9.1
26
+
27
+ - Allow for float/TimeSpec timeout values on clients (backport from 2.10.0)
28
+
29
+ ### 2.9.0
30
+
31
+ - Change to racially neutral terminology across library
32
+ - blacklist->blocklist
33
+ - master->main branch
34
+ - Explicitly declare development dependencies in gemspec
35
+ - Add script/e2e test for full e2e test in regression suite
36
+ - Explicitly declare [json gem](https://rubygems.org/gems/json) dependency
37
+ - Update to Rubocop 1.4, add in rubocop-rspec for spec tests
38
+ - Add Ruby 2.7, 3.0 support
39
+
5
40
  ### 2.8.1
6
41
 
7
42
  - Fix issue with --suppress-default-interceptors not working [#95]
@@ -145,11 +180,11 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
145
180
  ### 1.2.4
146
181
 
147
182
  - Loosen explicit Protobuf dependency now that 3.4.0.2 is released
148
- - Guard against nil params in logger blacklist
183
+ - Guard against nil params in logger blocklist
149
184
 
150
185
  ### 1.2.3
151
186
 
152
- - Support nested blacklist parameters in path.to.key format
187
+ - Support nested blocklist parameters in path.to.key format
153
188
 
154
189
  ### 1.2.2
155
190
 
@@ -171,7 +206,7 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
171
206
  - Add configuration to set the error message when an uncaught exception is
172
207
  handled by gruf.
173
208
  - Add a request logging hook for Rails-style request logging, with optional
174
- parameter logging, blacklists, and formatter support
209
+ parameter logging, blocklists, and formatter support
175
210
  - Optimizations around Symbol casting within service calls
176
211
 
177
212
  ### 1.1.0
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # gruf - gRPC Ruby Framework
2
2
 
3
- [![CircleCI](https://circleci.com/gh/bigcommerce/gruf/tree/master.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf/tree/master) [![Gem Version](https://badge.fury.io/rb/gruf.svg)](https://badge.fury.io/rb/gruf) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf.svg?branch=master)](https://inch-ci.org/github/bigcommerce/gruf?branch=master)
3
+ [![CircleCI](https://circleci.com/gh/bigcommerce/gruf/tree/main.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf/tree/main) [![Gem Version](https://badge.fury.io/rb/gruf.svg)](https://badge.fury.io/rb/gruf) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf.svg?branch=main)](https://inch-ci.org/github/bigcommerce/gruf?branch=main)
4
4
 
5
5
  gruf is a Ruby framework that wraps the [gRPC Ruby library](https://github.com/grpc/grpc/tree/master/src/ruby) to
6
6
  provide a more streamlined integration into Ruby and Ruby on Rails applications.
@@ -17,7 +17,7 @@ up fast and efficiently at scale. Some of its features include:
17
17
  still preserving gRPC BadStatus codes
18
18
  * Server and client execution timings in responses
19
19
 
20
- gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.2-2.6.
20
+ gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.2-3.0.
21
21
  gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any Ruby framework
22
22
  (such as [Grape](https://github.com/ruby-grape/grape) or [dry-rb](https://dry-rb.org/), for instance).
23
23
 
data/gruf.gemspec CHANGED
@@ -15,7 +15,7 @@
15
15
  # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
16
  # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
17
  #
18
- $:.push File.expand_path("../lib", __FILE__)
18
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
19
19
  require 'gruf/version'
20
20
 
21
21
  Gem::Specification.new do |spec|
@@ -30,19 +30,38 @@ Gem::Specification.new do |spec|
30
30
  spec.homepage = 'https://github.com/bigcommerce/gruf'
31
31
 
32
32
  spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'gruf.gemspec']
33
- spec.executables << 'gruf'
33
+ spec.executables << 'gruf'
34
34
  spec.require_paths = ['lib']
35
35
 
36
- spec.required_ruby_version = '~> 2.4'
36
+ spec.required_ruby_version = '>= 2.6', '< 3.1'
37
37
 
38
- spec.add_development_dependency 'bundler', '~> 1.11'
38
+ spec.metadata['rubygems_mfa_required'] = 'true'
39
+
40
+ spec.add_development_dependency 'bundler-audit', '>= 0.6'
41
+ # rubocop:disable Gemspec/RubyVersionGlobalsUsage
42
+ spec.add_development_dependency(
43
+ 'factory_bot',
44
+ (Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5') ? '>= 6.1' : '~> 5.2')
45
+ )
46
+ # rubocop:enable Gemspec/RubyVersionGlobalsUsage
47
+ spec.add_development_dependency 'ffaker', '>= 2.15'
48
+ spec.add_development_dependency 'pry', '~> 0.12'
49
+ spec.add_development_dependency 'pry-byebug', '>= 3.9'
39
50
  spec.add_development_dependency 'rake', '>= 10.0'
40
- spec.add_development_dependency 'pry', '~> 0.11'
51
+ spec.add_development_dependency 'rspec', '>= 3.8'
52
+ spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
53
+ spec.add_development_dependency 'rubocop', '>= 1.0'
54
+ spec.add_development_dependency 'rubocop-performance', '>= 0.0.1'
55
+ spec.add_development_dependency 'rubocop-rspec', '>= 2.0'
56
+ spec.add_development_dependency 'rubocop-thread_safety', '>= 0.3'
57
+ spec.add_development_dependency 'simplecov', '>= 0.16'
41
58
 
42
- spec.add_runtime_dependency 'grpc', '~> 1.10'
43
- spec.add_runtime_dependency 'grpc-tools', '~> 1.10'
44
59
  spec.add_runtime_dependency 'activesupport', '> 4'
45
-
46
60
  spec.add_runtime_dependency 'concurrent-ruby', '> 1'
47
- spec.add_runtime_dependency 'slop', '~> 4.6'
61
+ spec.add_runtime_dependency 'e2mmap', '>= 0.1'
62
+ spec.add_runtime_dependency 'grpc', '~> 1.10', '<= 1.41.0'
63
+ spec.add_runtime_dependency 'grpc-tools', '~> 1.10', '<= 1.41.0'
64
+ spec.add_runtime_dependency 'json', '>= 2.3'
65
+ spec.add_runtime_dependency 'slop', '>= 4.6'
66
+ spec.add_runtime_dependency 'thwait', '>= 0.1'
48
67
  end
@@ -38,7 +38,7 @@ module Gruf
38
38
  @services = services || Gruf.services
39
39
  @hook_executor = hook_executor || Gruf::Hooks::Executor.new(hooks: Gruf.hooks&.prepare)
40
40
  @server = server || Gruf::Server.new(Gruf.server_options)
41
- @logger = logger || Gruf.logger || ::Logger.new(STDERR)
41
+ @logger = logger || Gruf.logger || ::Logger.new($stderr)
42
42
  end
43
43
 
44
44
  ##
@@ -23,7 +23,8 @@ module Gruf
23
23
  # GRPC::BadStatus error
24
24
  #
25
25
  class Error < StandardError
26
- # @return [Object] error The deserialized error
26
+ # @!attribute [r] error
27
+ # @return [Object] error The deserialized error
27
28
  attr_reader :error
28
29
 
29
30
  ##
@@ -33,6 +34,7 @@ module Gruf
33
34
  #
34
35
  def initialize(error)
35
36
  @error = error
37
+ super
36
38
  end
37
39
  end
38
40
 
@@ -57,6 +59,7 @@ module Gruf
57
59
  class FailedPrecondition < Error; end
58
60
  class Internal < Error; end
59
61
  class PermissionDenied < Error; end
62
+ class ResourceExhausted < Error; end
60
63
  class Unauthenticated < Error; end
61
64
  class Unavailable < Error; end
62
65
  class Unimplemented < Error; end
data/lib/gruf/client.rb CHANGED
@@ -38,11 +38,14 @@ module Gruf
38
38
  class Client < SimpleDelegator
39
39
  include Gruf::Loggable
40
40
 
41
- # @return [Class] The base, friendly name of the service being requested
41
+ # @!attribute [r] base_klass
42
+ # @return [Class] The base, friendly name of the service being requested
42
43
  attr_reader :base_klass
43
- # @return [Class] The class name of the gRPC service being requested
44
+ # @!attribute [r] service_klass
45
+ # @return [Class] The class name of the gRPC service being requested
44
46
  attr_reader :service_klass
45
- # @return [Hash] A hash of options for the client
47
+ # @!attribute [r] opts
48
+ # @return [Hash] A hash of options for the client
46
49
  attr_reader :opts
47
50
 
48
51
  ##
@@ -62,8 +65,8 @@ module Gruf
62
65
  @opts[:hostname] = @opts.fetch(:hostname, Gruf.default_client_host)
63
66
  @opts[:channel_credentials] = @opts.fetch(:channel_credentials, Gruf.default_channel_credentials)
64
67
  @error_factory = Gruf::Client::ErrorFactory.new
65
- client_options[:timeout] = client_options[:timeout].to_i if client_options.key?(:timeout)
66
- client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials, client_options)
68
+ client_options[:timeout] = parse_timeout(client_options[:timeout]) if client_options.key?(:timeout)
69
+ client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials, **client_options)
67
70
  super(client)
68
71
  end
69
72
 
@@ -216,5 +219,27 @@ module Gruf
216
219
  Gruf::Serializers::Errors::Json
217
220
  end
218
221
  end
222
+
223
+ ##
224
+ # Handle various timeout values and prevent improper value setting
225
+ #
226
+ # @see GRPC::Core::TimeConsts#from_relative_time
227
+ # @param [mixed] timeout
228
+ # @return [Float]
229
+ # @return [GRPC::Core::TimeSpec]
230
+ #
231
+ def parse_timeout(timeout)
232
+ if timeout.nil?
233
+ GRPC::Core::TimeConsts::ZERO
234
+ elsif timeout.is_a?(GRPC::Core::TimeSpec)
235
+ timeout
236
+ elsif timeout.is_a?(Numeric) # rubocop:disable Lint/DuplicateBranch
237
+ timeout
238
+ elsif timeout.respond_to?(:to_f)
239
+ timeout.to_f
240
+ else
241
+ raise ArgumentError, 'timeout is not a valid value: does not respond to to_f'
242
+ end
243
+ end
219
244
  end
220
245
  end
@@ -20,6 +20,63 @@ module Gruf
20
20
  # Represents configuration settings for the system
21
21
  #
22
22
  module Configuration
23
+ # @!attribute root_path
24
+ # @return [String] The root path for your application
25
+ # @!attribute server_binding_url
26
+ # @return [String] The full hostname:port that the gRPC server should bind to
27
+ # @!attribute server_options
28
+ # @return [Hash] A hash of options to pass to the server instance
29
+ # @!attribute interceptors
30
+ # @return [::Gruf::Interceptors::Registry] A registry of Gruf server interceptors
31
+ # @!attribute hooks
32
+ # @return [::Gruf::Hooks::Registry] A registry of Gruf hooks for the server
33
+ # @!attribute default_channel_credentials
34
+ # @return [NilClass]
35
+ # @return [Symbol]
36
+ # @return [Hash]
37
+ # @!attribute default_client_host
38
+ # @return [String] The default host for all new Gruf::Client objects to use as their target host
39
+ # @!attribute use_ssl
40
+ # @return [Boolean] If true, will setup the server to use TLS
41
+ # @!attribute ssl_crt_file
42
+ # @return [String] If use_ssl is true, the relative path from the root_path to the CRT file for the server
43
+ # @!attribute ssl_key_file
44
+ # @return [String] If use_ssl is true, the relative path from the root_path to the key file for the server
45
+ # @!attribute controllers_path
46
+ # @return [String] The relative path from root_path to locate Gruf Controllers in
47
+ # @!attribute services
48
+ # @return [Array<Class>] An array of services to serve with this Gruf server
49
+ # @!attribute logger
50
+ # @return [Logger] The logger class for Gruf-based logging
51
+ # @!attribute grpc_logger
52
+ # @return [Logger] The logger to use with GRPC's core logger (which logs plaintext). It is recommended to set
53
+ # this to an STDOUT logger and use a logging pipeline that can translate plaintext logs given GRPC's
54
+ # unformatted logging.
55
+ # @!attribute error_metadata_key
56
+ # @return [Symbol] The metadata key to use for error messages sent back in trailing metadata.
57
+ # @!attribute error_serializer
58
+ # @return [NilClass|::Gruf::Serializers::Errors::Base] The error serializer to use for error messages sent
59
+ # back in trailing metadata. Defaults to the base JSON serializer.
60
+ # @!attribute append_server_errors_to_trailing_metadata
61
+ # @return [Boolean] If true, will append all server error information into the trailing metadata in the response
62
+ # from the server
63
+ # @!attribute use_default_interceptors
64
+ # @return [Boolean] If true, will use the default ActiveRecord and Timer interceptors for servers
65
+ # @!attribute backtrace_on_error
66
+ # @return [Boolean] If true, will return the backtrace on any errors in servers in the trailing metadata
67
+ # @!attribute backtrace_limit
68
+ # @return [Integer] The limit of lines to use in backtraces returned
69
+ # @!attribute use_exception_message
70
+ # @return [String] If true, will pass the actual exception message from the error in a server
71
+ # @!attribute internal_error_message
72
+ # @return [String] If use_exception_message is false, this message will be used instead as a replacement
73
+ # @!attribute event_listener_proc
74
+ # @return [NilClass]
75
+ # @return [Proc] If set, this will be used during GRPC events (such as pool exhaustions)
76
+ # @!attribute synchronized_client_internal_cache_expiry
77
+ # @return [Integer] Internal cache expiry period (in seconds) for the SynchronizedClient
78
+ # @!attribute rpc_server_options
79
+ # @return [Hash] A hash of RPC options for GRPC server configuration
23
80
  VALID_CONFIG_KEYS = {
24
81
  root_path: '',
25
82
  server_binding_url: '0.0.0.0:9001',
@@ -61,8 +118,8 @@ module Gruf
61
118
  # Whenever this is extended into a class, setup the defaults
62
119
  #
63
120
  def self.extended(base)
64
- if defined?(Rails)
65
- Gruf::Integrations::Rails::Railtie.config.before_initialize { base.reset }
121
+ if defined?(::Rails)
122
+ ::Gruf::Integrations::Rails::Railtie.config.before_initialize { base.reset }
66
123
  else
67
124
  base.reset
68
125
  end
@@ -98,24 +155,30 @@ module Gruf
98
155
  #
99
156
  def reset
100
157
  VALID_CONFIG_KEYS.each do |k, v|
101
- send((k.to_s + '='), v)
158
+ send("#{k}=", v)
102
159
  end
103
- self.interceptors = Gruf::Interceptors::Registry.new
104
- self.hooks = Gruf::Hooks::Registry.new
105
- self.root_path = Rails.root.to_s.chomp('/') if defined?(Rails)
106
- if defined?(Rails) && Rails.logger
107
- self.logger = Rails.logger
108
- else
109
- require 'logger'
110
- self.logger = ::Logger.new(STDOUT)
111
- end
112
- self.grpc_logger = logger if grpc_logger.nil?
160
+ self.server_binding_url = "#{::ENV.fetch('GRPC_SERVER_HOST',
161
+ '0.0.0.0')}:#{::ENV.fetch('GRPC_SERVER_PORT', 9_001)}"
162
+ self.interceptors = ::Gruf::Interceptors::Registry.new
163
+ self.hooks = ::Gruf::Hooks::Registry.new
164
+ self.root_path = ::Rails.root.to_s.chomp('/') if defined?(::Rails)
165
+ determine_loggers
113
166
  self.ssl_crt_file = "#{root_path}config/ssl/#{environment}.crt"
114
167
  self.ssl_key_file = "#{root_path}config/ssl/#{environment}.key"
115
168
  self.controllers_path = root_path.to_s.empty? ? 'app/rpc' : "#{root_path}/app/rpc"
169
+ self.backtrace_on_error = ::ENV.fetch('GRPC_BACKTRACE_ON_ERROR', 0).to_i.positive?
170
+ self.rpc_server_options = {
171
+ max_waiting_requests: ::ENV.fetch('GRPC_SERVER_MAX_WAITING_REQUESTS',
172
+ GRPC::RpcServer::DEFAULT_MAX_WAITING_REQUESTS).to_i,
173
+ pool_size: ::ENV.fetch('GRPC_SERVER_POOL_SIZE', GRPC::RpcServer::DEFAULT_POOL_SIZE).to_i,
174
+ pool_keep_alive: ::ENV.fetch('GRPC_SERVER_POOL_KEEP_ALIVE', GRPC::Pool::DEFAULT_KEEP_ALIVE),
175
+ poll_period: ::ENV.fetch('GRPC_SERVER_POLL_PERIOD', GRPC::RpcServer::DEFAULT_POLL_PERIOD),
176
+ connect_md_proc: nil,
177
+ server_args: {}
178
+ }
116
179
  if use_default_interceptors
117
- interceptors.use(Gruf::Interceptors::ActiveRecord::ConnectionReset)
118
- interceptors.use(Gruf::Interceptors::Instrumentation::OutputMetadataTimer)
180
+ interceptors.use(::Gruf::Interceptors::ActiveRecord::ConnectionReset)
181
+ interceptors.use(::Gruf::Interceptors::Instrumentation::OutputMetadataTimer)
119
182
  end
120
183
  options
121
184
  end
@@ -128,11 +191,30 @@ module Gruf
128
191
  # @return [String] The current Ruby environment
129
192
  #
130
193
  def environment
131
- if defined?(Rails)
132
- Rails.env.to_s
194
+ if defined?(::Rails)
195
+ ::Rails.env.to_s
133
196
  else
134
197
  (ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development').to_s
135
198
  end
136
199
  end
200
+
201
+ ##
202
+ # Dynamically determine the appropriate logger
203
+ #
204
+ def determine_loggers
205
+ if defined?(::Rails) && ::Rails.logger
206
+ self.logger = ::Rails.logger
207
+ else
208
+ require 'logger'
209
+ self.logger = ::Logger.new($stdout)
210
+ log_level = ::ENV.fetch('LOG_LEVEL', 'info').to_s.upcase
211
+ begin
212
+ logger.level = ::Logger::Severity.const_get(log_level)
213
+ rescue NameError => _e
214
+ logger.level = ::Logger::Severity::INFO
215
+ end
216
+ end
217
+ self.grpc_logger = logger if grpc_logger.nil?
218
+ end
137
219
  end
138
220
  end
@@ -26,13 +26,16 @@ module Gruf
26
26
  class Base
27
27
  include Gruf::Errors::Helpers
28
28
 
29
- # @var [Gruf::Controller::Request] request
29
+ # @!attribute [r] request
30
+ # @return [Gruf::Controller::Request] The incoming request
30
31
  attr_reader :request
31
- # @var [Gruf::Error] error
32
+ # @!attribute [r] error
33
+ # @return [Gruf::Error] The current error on the controller
32
34
  attr_reader :error
33
35
 
34
36
  class << self
35
- # @var [GRPC::GenericService] bound_service
37
+ # @!attribute [r] bound_service
38
+ # @return [GRPC::GenericService] bound_service The bound gRPC service class
36
39
  attr_reader :bound_service
37
40
  end
38
41
 
@@ -65,7 +68,9 @@ module Gruf
65
68
  def self.bind(service)
66
69
  service_class = service.name.constantize
67
70
  Gruf.services << service_class
71
+ # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
68
72
  @bound_service = service_class
73
+ # rubocop:enable ThreadSafety/InstanceVariableInClassMethod
69
74
  ServiceBinder.new(service_class).bind!(self)
70
75
  end
71
76
 
@@ -21,15 +21,20 @@ module Gruf
21
21
  # Encapsulates a request for a controller
22
22
  #
23
23
  class Request
24
- # @var [Object] message
24
+ # @!attribute [r] message
25
+ # @return [Object] The protobuf message in the request
25
26
  attr_reader :message
26
- # @var [GRPC::ActiveCall] active_call
27
+ # @!attribute [r] active_call
28
+ # @return [GRPC::ActiveCall] The active call object used for this request
27
29
  attr_reader :active_call
28
- # @var [Symbol] method_key
30
+ # @!attribute [r] method_key
31
+ # @return [Symbol] The method name being requested
29
32
  attr_reader :method_key
30
- # @var [Gruf::Controllers::Request::Type] type
33
+ # @!attribute [r] type
34
+ # @return [Gruf::Controllers::Request::Type] The type of request
31
35
  attr_reader :type
32
- # @var [Class] service
36
+ # @!attribute [r] service
37
+ # @return [Class] The GRPC service class for this request
33
38
  attr_reader :service
34
39
 
35
40
  delegate :metadata, to: :active_call
@@ -58,7 +63,7 @@ module Gruf
58
63
  # @param [Class] service The class of the service being executed against
59
64
  # @param [GRPC::RpcDesc] rpc_desc The RPC descriptor of the call
60
65
  # @param [GRPC::ActiveCall] active_call The restricted view of the call
61
- # @param [Object] message The protobuf message (or messages) of the request
66
+ # @param [Object|Google::Protobuf::MessageExts] message The protobuf message (or messages) of the request
62
67
  #
63
68
  def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
64
69
  @method_key = method_key
@@ -76,7 +81,7 @@ module Gruf
76
81
  # @return [String] The mapped service key
77
82
  #
78
83
  def service_key
79
- @service.name.underscore.tr('/', '.').gsub('.service', '')
84
+ @service.name.to_s.underscore.tr('/', '.').gsub('.service', '')
80
85
  end
81
86
 
82
87
  ##
@@ -99,21 +104,24 @@ module Gruf
99
104
  # @return [String] The parsed service method name
100
105
  #
101
106
  def method_name
102
- "#{service_key}.#{method_key}"
107
+ "#{service_key}.#{@method_key}"
103
108
  end
104
109
 
105
110
  ##
106
111
  # Return all messages for this request, properly handling different request types
107
112
  #
108
- # @return Enumerable<Object> All messages for this request
113
+ # @return [Enumerable<Object>] All messages for this request
114
+ # @return [Object] If a bidi streamed request, will return the message object
109
115
  #
110
116
  def messages
111
117
  if client_streamer?
112
- message.call { |msg| yield msg }
118
+ # rubocop:disable Style/ExplicitBlockArgument
119
+ @message.call { |msg| yield msg }
120
+ # rubocop:enable Style/ExplicitBlockArgument
113
121
  elsif bidi_streamer?
114
- message
122
+ @message
115
123
  else
116
- [message]
124
+ [@message]
117
125
  end
118
126
  end
119
127
  end
@@ -38,7 +38,7 @@ module Gruf
38
38
  ##
39
39
  # Bind all methods on the service to the passed controller
40
40
  #
41
- # @param [Gruf::Controllers::Base] controller
41
+ # @param [Class<Gruf::Controllers::Base>] controller
42
42
  #
43
43
  def bind!(controller)
44
44
  rpc_methods.each { |name, desc| bind_method(controller, name, desc) }
data/lib/gruf/error.rb CHANGED
@@ -59,20 +59,28 @@ module Gruf
59
59
  METADATA_SIZE_EXCEEDED_CODE = 'metadata_size_exceeded'
60
60
  METADATA_SIZE_EXCEEDED_MSG = 'Metadata too long, risks exceeding http2 trailing metadata limit.'
61
61
 
62
- # @return [Symbol] The given internal gRPC code for the error
62
+ # @!attribute code
63
+ # @return [Symbol] The given internal gRPC code for the error
63
64
  attr_accessor :code
64
- # @return [Symbol] An arbitrary application code that can be used for logical processing of the error by the client
65
+ # @!attribute app_code
66
+ # @return [Symbol] An arbitrary application code that can be used for logical processing of the error
67
+ # by the client
65
68
  attr_accessor :app_code
66
- # @return [String] The error message returned by the server
69
+ # @!attribute message
70
+ # @return [String] The error message returned by the server
67
71
  attr_accessor :message
68
- # @return [Array] An array of field errors that can be returned by the server
72
+ # @!attribute field_errors
73
+ # @return [Array] An array of field errors that can be returned by the server
69
74
  attr_accessor :field_errors
70
- # @return [Errors::DebugInfo] A object containing debugging information, such as a stack trace and exception name,
71
- # that can be used to debug an given error response. This is sent by the server over the trailing metadata.
75
+ # @!attribute debug_info
76
+ # @return [Errors::DebugInfo] A object containing debugging information, such as a stack trace and exception name,
77
+ # that can be used to debug an given error response. This is sent by the server over the trailing metadata.
72
78
  attr_accessor :debug_info
73
- # @return [GRPC::BadStatus] The gRPC BadStatus error object that was generated
79
+ # @!attribute [w] grpc_error
80
+ # @return [GRPC::BadStatus] The gRPC BadStatus error object that was generated
74
81
  attr_writer :grpc_error
75
- # @return [Hash] The trailing metadata that was attached to the error
82
+ # @!attribute [r] metadata
83
+ # @return [Hash] The trailing metadata that was attached to the error
76
84
  attr_reader :metadata
77
85
 
78
86
  ##
@@ -126,7 +134,7 @@ module Gruf
126
134
  # @return [Hash] The newly set metadata
127
135
  #
128
136
  def metadata=(metadata)
129
- @metadata = metadata.map { |k, str| [k, str.to_s] }.to_h
137
+ @metadata = metadata.transform_values(&:to_s)
130
138
  end
131
139
 
132
140
  ##
@@ -21,9 +21,11 @@ module Gruf
21
21
  # Represents debugging information for an exception that occurred in a gRPC service
22
22
  #
23
23
  class DebugInfo
24
- # @return [String] The detail message of the exception
24
+ # @!attribute [r] detail
25
+ # @return [String] The detail message of the exception
25
26
  attr_reader :detail
26
- # @return [Array<String>] The stack trace generated by the exception as an array of strings
27
+ # @!attribute [r] stack_trace
28
+ # @return [Array<String>] The stack trace generated by the exception as an array of strings
27
29
  attr_reader :stack_trace
28
30
 
29
31
  ##
@@ -21,11 +21,14 @@ module Gruf
21
21
  # Represents a field-specific error
22
22
  #
23
23
  class Field
24
- # @return [Symbol] The name of the field as a Symbol
24
+ # @!attribute [r] field_name
25
+ # @return [Symbol] The name of the field as a Symbol
25
26
  attr_reader :field_name
26
- # @return [Symbol] The application error code for the field, e.g. :job_not_found
27
+ # @!attribute [r] error_code
28
+ # @return [Symbol] The application error code for the field, e.g. :job_not_found
27
29
  attr_reader :error_code
28
- # @return [String] The error message for the field, e.g. "Job with ID 123 not found"
30
+ # @!attribute [r] message
31
+ # @return [String] The error message for the field, e.g. "Job with ID 123 not found"
29
32
  attr_reader :message
30
33
 
31
34
  ##
@@ -39,7 +39,7 @@ module Gruf
39
39
  @hooks.each do |hook|
40
40
  next unless hook.respond_to?(name)
41
41
 
42
- hook.send(name, arguments)
42
+ hook.send(name, **arguments)
43
43
  end
44
44
  end
45
45
  end
@@ -21,11 +21,14 @@ module Gruf
21
21
  # Base class for interception requests
22
22
  #
23
23
  class Base
24
- # @var [Gruf::Controllers::Request] request
24
+ # @!attribute [r] request
25
+ # @return [Gruf::Controllers::Request] request
25
26
  attr_reader :request
26
- # @var [Gruf::Error] error
27
+ # @!attribute [r] error
28
+ # @return [Gruf::Error] error
27
29
  attr_reader :error
28
- # @var [Hash] options
30
+ # @!attribute [r] options
31
+ # @return [Hash] options
29
32
  attr_reader :options
30
33
 
31
34
  ##