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 +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
|
-
[](https://circleci.com/gh/bigcommerce/gruf/tree/main) [](https://badge.fury.io/rb/gruf) [](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
|
##
|