gruf 2.8.1 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -3
- data/README.md +2 -2
- data/gruf.gemspec +28 -9
- data/lib/gruf/cli/executor.rb +1 -1
- data/lib/gruf/client/error.rb +4 -1
- data/lib/gruf/client.rb +30 -5
- data/lib/gruf/configuration.rb +99 -17
- data/lib/gruf/controllers/base.rb +8 -3
- data/lib/gruf/controllers/request.rb +20 -12
- data/lib/gruf/controllers/service_binder.rb +1 -1
- data/lib/gruf/error.rb +17 -9
- data/lib/gruf/errors/debug_info.rb +4 -2
- data/lib/gruf/errors/field.rb +6 -3
- data/lib/gruf/hooks/executor.rb +1 -1
- data/lib/gruf/interceptors/base.rb +6 -3
- data/lib/gruf/interceptors/client_interceptor.rb +8 -16
- data/lib/gruf/interceptors/context.rb +4 -4
- data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +2 -4
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +12 -14
- data/lib/gruf/interceptors/instrumentation/statsd.rb +2 -4
- data/lib/gruf/interceptors/timer.rb +8 -1
- data/lib/gruf/outbound/request_context.rb +12 -7
- data/lib/gruf/response.rb +12 -6
- data/lib/gruf/serializers/errors/base.rb +2 -1
- data/lib/gruf/server.rb +6 -4
- data/lib/gruf/synchronized_client.rb +2 -0
- data/lib/gruf/timer.rb +7 -2
- data/lib/gruf/version.rb +1 -1
- data/lib/gruf.rb +1 -1
- metadata +229 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d00ffbd4089fa41fd29adb1848564ee695725576045f447255173ebb170df586
|
4
|
+
data.tar.gz: 55c8ca35a37cae3e5c03bec59c1073fe40e3ed919586cb33bdfd83dad7da2b54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
183
|
+
- Guard against nil params in logger blocklist
|
149
184
|
|
150
185
|
### 1.2.3
|
151
186
|
|
152
|
-
- Support nested
|
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,
|
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/
|
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-
|
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
|
-
|
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
|
33
|
+
spec.executables << 'gruf'
|
34
34
|
spec.require_paths = ['lib']
|
35
35
|
|
36
|
-
spec.required_ruby_version = '
|
36
|
+
spec.required_ruby_version = '>= 2.6', '< 3.1'
|
37
37
|
|
38
|
-
spec.
|
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 '
|
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 '
|
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
|
data/lib/gruf/cli/executor.rb
CHANGED
@@ -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(
|
41
|
+
@logger = logger || Gruf.logger || ::Logger.new($stderr)
|
42
42
|
end
|
43
43
|
|
44
44
|
##
|
data/lib/gruf/client/error.rb
CHANGED
@@ -23,7 +23,8 @@ module Gruf
|
|
23
23
|
# GRPC::BadStatus error
|
24
24
|
#
|
25
25
|
class Error < StandardError
|
26
|
-
#
|
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
|
-
#
|
41
|
+
# @!attribute [r] base_klass
|
42
|
+
# @return [Class] The base, friendly name of the service being requested
|
42
43
|
attr_reader :base_klass
|
43
|
-
#
|
44
|
+
# @!attribute [r] service_klass
|
45
|
+
# @return [Class] The class name of the gRPC service being requested
|
44
46
|
attr_reader :service_klass
|
45
|
-
#
|
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]
|
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
|
data/lib/gruf/configuration.rb
CHANGED
@@ -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(
|
158
|
+
send("#{k}=", v)
|
102
159
|
end
|
103
|
-
self.
|
104
|
-
|
105
|
-
self.
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
#
|
29
|
+
# @!attribute [r] request
|
30
|
+
# @return [Gruf::Controller::Request] The incoming request
|
30
31
|
attr_reader :request
|
31
|
-
#
|
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
|
-
#
|
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
|
-
#
|
24
|
+
# @!attribute [r] message
|
25
|
+
# @return [Object] The protobuf message in the request
|
25
26
|
attr_reader :message
|
26
|
-
#
|
27
|
+
# @!attribute [r] active_call
|
28
|
+
# @return [GRPC::ActiveCall] The active call object used for this request
|
27
29
|
attr_reader :active_call
|
28
|
-
#
|
30
|
+
# @!attribute [r] method_key
|
31
|
+
# @return [Symbol] The method name being requested
|
29
32
|
attr_reader :method_key
|
30
|
-
#
|
33
|
+
# @!attribute [r] type
|
34
|
+
# @return [Gruf::Controllers::Request::Type] The type of request
|
31
35
|
attr_reader :type
|
32
|
-
#
|
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
|
-
|
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
|
-
#
|
62
|
+
# @!attribute code
|
63
|
+
# @return [Symbol] The given internal gRPC code for the error
|
63
64
|
attr_accessor :code
|
64
|
-
#
|
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
|
-
#
|
69
|
+
# @!attribute message
|
70
|
+
# @return [String] The error message returned by the server
|
67
71
|
attr_accessor :message
|
68
|
-
#
|
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
|
-
#
|
71
|
-
#
|
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
|
-
#
|
79
|
+
# @!attribute [w] grpc_error
|
80
|
+
# @return [GRPC::BadStatus] The gRPC BadStatus error object that was generated
|
74
81
|
attr_writer :grpc_error
|
75
|
-
#
|
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.
|
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
|
-
#
|
24
|
+
# @!attribute [r] detail
|
25
|
+
# @return [String] The detail message of the exception
|
25
26
|
attr_reader :detail
|
26
|
-
#
|
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
|
##
|
data/lib/gruf/errors/field.rb
CHANGED
@@ -21,11 +21,14 @@ module Gruf
|
|
21
21
|
# Represents a field-specific error
|
22
22
|
#
|
23
23
|
class Field
|
24
|
-
#
|
24
|
+
# @!attribute [r] field_name
|
25
|
+
# @return [Symbol] The name of the field as a Symbol
|
25
26
|
attr_reader :field_name
|
26
|
-
#
|
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
|
-
#
|
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
|
##
|
data/lib/gruf/hooks/executor.rb
CHANGED
@@ -21,11 +21,14 @@ module Gruf
|
|
21
21
|
# Base class for interception requests
|
22
22
|
#
|
23
23
|
class Base
|
24
|
-
#
|
24
|
+
# @!attribute [r] request
|
25
|
+
# @return [Gruf::Controllers::Request] request
|
25
26
|
attr_reader :request
|
26
|
-
#
|
27
|
+
# @!attribute [r] error
|
28
|
+
# @return [Gruf::Error] error
|
27
29
|
attr_reader :error
|
28
|
-
#
|
30
|
+
# @!attribute [r] options
|
31
|
+
# @return [Hash] options
|
29
32
|
attr_reader :options
|
30
33
|
|
31
34
|
##
|