gruf 2.9.1 → 2.15.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 +4 -4
- data/CHANGELOG.md +61 -5
- data/README.md +3 -3
- data/gruf.gemspec +15 -7
- data/lib/gruf/autoloaders.rb +76 -0
- data/lib/gruf/cli/executor.rb +18 -1
- data/lib/gruf/client/error.rb +2 -29
- data/lib/gruf/client/errors.rb +48 -0
- data/lib/gruf/client.rb +7 -7
- data/lib/gruf/configuration.rb +109 -19
- data/lib/gruf/controllers/autoloader.rb +74 -0
- data/lib/gruf/controllers/base.rb +10 -8
- data/lib/gruf/controllers/request.rb +12 -6
- data/lib/gruf/controllers/service_binder.rb +68 -81
- data/lib/gruf/error.rb +16 -12
- data/lib/gruf/errors/debug_info.rb +4 -2
- data/lib/gruf/errors/field.rb +6 -3
- data/lib/gruf/{logging.rb → grpc_logger.rb} +0 -14
- data/lib/gruf/integrations/rails/railtie.rb +30 -0
- data/lib/gruf/interceptors/base.rb +6 -13
- data/lib/gruf/interceptors/context.rb +1 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +0 -3
- data/lib/gruf/interceptors/timer.rb +7 -3
- data/lib/gruf/logger.rb +32 -0
- 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 +33 -68
- data/lib/gruf/synchronized_client.rb +2 -0
- data/lib/gruf/timer.rb +6 -2
- data/lib/gruf/version.rb +1 -1
- data/lib/gruf.rb +17 -21
- metadata +37 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5186fbfc554b119075aff88683ee7f1661a884d96d9766e59664d10805bd4ab2
|
4
|
+
data.tar.gz: 68b995a644b15dc703595df4e35a25539e0edf77d5f5218bffa28253b60eedbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8328cccfcc712c21cb5a477939762524d774d3d45a0882217fe3b7d701cfda90e9dcd27af7ab4c4cbc73ca46d420d85e55be3712efc950590212658030217c40
|
7
|
+
data.tar.gz: 2cf04dce0c4e378edf56ab6b204293ce2b4dc660d2ac103ac55d99e893891ac3a76feb2e05dee4ac3371b47083fd8523441e7e2c87881bacd2511b016a1965b3
|
data/CHANGELOG.md
CHANGED
@@ -2,11 +2,67 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
2
2
|
|
3
3
|
### Pending release
|
4
4
|
|
5
|
-
### 2.
|
5
|
+
### 2.15.1
|
6
|
+
|
7
|
+
- Fix issue where GRPC_SERVER_POOL_KEEP_ALIVE and GRPC_SERVER_POLL_PERIOD when set via ENV are not cast to int
|
8
|
+
|
9
|
+
### 2.15.0
|
10
|
+
|
11
|
+
- NOTE: This changes the way that gruf controllers are autoloaded. See [UPGRADING.md] for more details.
|
12
|
+
- Autoload Gruf Controllers with zeitwerk, allowing for code reloading in development environments
|
13
|
+
- Add `GRUF_CONTROLLERS_PATH` ENV to allow ENV-based runtime configuration of path to gruf controller files
|
14
|
+
- Move `ServiceBinder` from instance to static class for performance improvements
|
15
|
+
- Use zeitwerk for autoloading
|
16
|
+
- Update gem metadata
|
17
|
+
- Update `Gruf:Configuration#environment` to use `ENV.fetch`
|
18
|
+
|
19
|
+
### 2.14.1
|
20
|
+
|
21
|
+
- Fix issue where the server object hits thread contention in certain race conditions
|
22
|
+
|
23
|
+
### 2.14.0
|
24
|
+
|
25
|
+
- Set default client host to 0.0.0.0:9001 (same as default server host)
|
26
|
+
- Add support for Ruby 3.1
|
27
|
+
|
28
|
+
### 2.13.1
|
29
|
+
|
30
|
+
- Fix issue with race condition in server starts where servers may fail to bind connections and never reach
|
31
|
+
serving state (fixes #147)
|
32
|
+
|
33
|
+
### 2.13.0
|
34
|
+
|
35
|
+
- Remove server mutex handling in deference to core grpc signal handling
|
36
|
+
- Relax grpc pin as upstream regression is fixed
|
37
|
+
|
38
|
+
### 2.12.0
|
39
|
+
|
40
|
+
- Fixed interceptor order to be FIFO as documented, instead of FILO (fixes #139)
|
41
|
+
|
42
|
+
### 2.11.0
|
43
|
+
|
44
|
+
- Restrict grpc gem to <= 1.41.0 due to regressions in grpc 1.42.x
|
45
|
+
- Fallback to stdout logger at INFO if no logger is setup
|
46
|
+
- Better handling of namespace collisions with Rails
|
47
|
+
- Add `GRPC_SERVER_HOST` and `GRPC_SERVER_PORT` for ENV configuration of the server host+port
|
48
|
+
- Add `GRPC_BACKTRACE_ON_ERROR` as available ENV configuration
|
49
|
+
- Add default ENV-based configuration of the GRPC server pool
|
50
|
+
- `GRPC_SERVER_POOL_SIZE` - sets the size of the GRPC server pool
|
51
|
+
- `GRPC_SERVER_POOL_KEEP_ALIVE` - keep alive time for threads spawned by the server pool
|
52
|
+
- `GRPC_SERVER_POLL_PERIOD` - period in seconds to poll for workers in the gRPC server pool
|
53
|
+
- Improve Yardoc support across the library
|
54
|
+
- Added attribute-based documentation for Gruf configuration options
|
55
|
+
- Add mfa required for gemspec metadata
|
56
|
+
|
57
|
+
### 2.10.0
|
6
58
|
|
7
59
|
- Drop support for Ruby 2.4/2.5 to align with Ruby EOL schedule, supporting 2.6+ only
|
8
60
|
- Allow for float/TimeSpec timeout values on clients
|
9
61
|
|
62
|
+
### 2.9.1
|
63
|
+
|
64
|
+
- Allow for float/TimeSpec timeout values on clients (backport from 2.10.0)
|
65
|
+
|
10
66
|
### 2.9.0
|
11
67
|
|
12
68
|
- Change to racially neutral terminology across library
|
@@ -25,7 +81,7 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
25
81
|
|
26
82
|
### 2.8.0
|
27
83
|
|
28
|
-
- Pass the controller request object into the request logging formatters [#92]
|
84
|
+
- Pass the controller request object into the request logging formatters [#92]
|
29
85
|
|
30
86
|
### 2.7.1
|
31
87
|
|
@@ -38,12 +94,12 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
38
94
|
### 2.6.1
|
39
95
|
|
40
96
|
- Add frozen_string_literal: true to files, update rubocop to 0.68
|
41
|
-
|
97
|
+
|
42
98
|
### 2.6.0
|
43
99
|
|
44
100
|
- Drop Ruby 2.2 support
|
45
|
-
- Abstract gruf controller's send to make it usable in filters
|
46
|
-
- Adjusts configuration reset into a Railtie for Rails systems to ensure proper OOE
|
101
|
+
- Abstract gruf controller's send to make it usable in filters
|
102
|
+
- Adjusts configuration reset into a Railtie for Rails systems to ensure proper OOE
|
47
103
|
- Bump rubocop to 0.64, address violations, update activesupport/concurrent-ruby dependencies to have a min version
|
48
104
|
|
49
105
|
### 2.5.2
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
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)
|
3
|
+
[](https://circleci.com/gh/bigcommerce/gruf/tree/main) [](https://badge.fury.io/rb/gruf) [](https://inch-ci.org/github/bigcommerce/gruf?branch=main) [](https://codeclimate.com/github/bigcommerce/gruf/maintainability) [](https://codeclimate.com/github/bigcommerce/gruf/test_coverage)
|
4
4
|
|
5
|
-
gruf is a Ruby framework that wraps the [gRPC Ruby library](https://github.com/grpc/grpc/tree/
|
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.
|
7
7
|
|
8
8
|
It provides an abstracted server and client for gRPC services, along with other tools to help get gRPC services in Ruby
|
@@ -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.
|
20
|
+
gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.6-3.1.
|
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,8 +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
|
-
|
19
|
-
require 'gruf/version'
|
18
|
+
require_relative 'lib/gruf/version'
|
20
19
|
|
21
20
|
Gem::Specification.new do |spec|
|
22
21
|
spec.name = 'gruf'
|
@@ -33,9 +32,17 @@ Gem::Specification.new do |spec|
|
|
33
32
|
spec.executables << 'gruf'
|
34
33
|
spec.require_paths = ['lib']
|
35
34
|
|
36
|
-
spec.required_ruby_version = '>= 2.
|
35
|
+
spec.required_ruby_version = '>= 2.6', '< 3.2'
|
36
|
+
|
37
|
+
spec.metadata = {
|
38
|
+
'bug_tracker_uri' => 'https://github.com/bigcommerce/gruf/issues',
|
39
|
+
'changelog_uri' => 'https://github.com/bigcommerce/gruf/CHANGELOG.md',
|
40
|
+
'homepage_uri' => 'https://github.com/bigcommerce/gruf',
|
41
|
+
'rubygems_mfa_required' => 'true',
|
42
|
+
'source_code_uri' => 'https://github.com/bigcommerce/gruf',
|
43
|
+
'wiki_uri' => 'https://github.com/bigcommerce/gruf/wiki'
|
44
|
+
}
|
37
45
|
|
38
|
-
spec.add_development_dependency 'bundler', '~> 1.11'
|
39
46
|
spec.add_development_dependency 'bundler-audit', '>= 0.6'
|
40
47
|
# rubocop:disable Gemspec/RubyVersionGlobalsUsage
|
41
48
|
spec.add_development_dependency(
|
@@ -57,10 +64,11 @@ Gem::Specification.new do |spec|
|
|
57
64
|
|
58
65
|
spec.add_runtime_dependency 'activesupport', '> 4'
|
59
66
|
spec.add_runtime_dependency 'concurrent-ruby', '> 1'
|
60
|
-
spec.add_runtime_dependency 'e2mmap', '
|
67
|
+
spec.add_runtime_dependency 'e2mmap', '>= 0.1'
|
61
68
|
spec.add_runtime_dependency 'grpc', '~> 1.10'
|
62
69
|
spec.add_runtime_dependency 'grpc-tools', '~> 1.10'
|
63
70
|
spec.add_runtime_dependency 'json', '>= 2.3'
|
64
|
-
spec.add_runtime_dependency 'slop', '
|
65
|
-
spec.add_runtime_dependency 'thwait', '
|
71
|
+
spec.add_runtime_dependency 'slop', '>= 4.6'
|
72
|
+
spec.add_runtime_dependency 'thwait', '>= 0.1'
|
73
|
+
spec.add_runtime_dependency 'zeitwerk', '>= 2'
|
66
74
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2022-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
|
+
# Module for accessing Gruf zeitwerk-based autoloaders
|
21
|
+
#
|
22
|
+
module Autoloaders
|
23
|
+
class << self
|
24
|
+
include Enumerable
|
25
|
+
|
26
|
+
##
|
27
|
+
# Initialize the autoloaders with a given controllers path
|
28
|
+
#
|
29
|
+
# @param [String] controllers_path The path to Gruf Controllers
|
30
|
+
#
|
31
|
+
def load!(controllers_path:)
|
32
|
+
controllers(controllers_path: controllers_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Enumerate across the managed set of autoloaders
|
37
|
+
#
|
38
|
+
def each
|
39
|
+
yield controllers
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Reload all files managed by the autoloader
|
44
|
+
#
|
45
|
+
def reload
|
46
|
+
each(&:reload)
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Lazily instantiate and memoize the Gruf Controllers autoloader in a thread-safe manner
|
51
|
+
#
|
52
|
+
# @return [::Gruf::Controllers::Autoloader]
|
53
|
+
#
|
54
|
+
# rubocop:disable ThreadSafety/InstanceVariableInClassMethod
|
55
|
+
def controllers(controllers_path: nil)
|
56
|
+
controllers_mutex do
|
57
|
+
@controllers ||= ::Gruf::Controllers::Autoloader.new(path: controllers_path || ::Gruf.controllers_path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# rubocop:enable ThreadSafety/InstanceVariableInClassMethod
|
61
|
+
|
62
|
+
##
|
63
|
+
# Handle mutations to the controllers autoloader in a thread-safe manner
|
64
|
+
#
|
65
|
+
# rubocop:disable ThreadSafety/InstanceVariableInClassMethod
|
66
|
+
def controllers_mutex(&block)
|
67
|
+
@controllers_mutex ||= begin
|
68
|
+
require 'monitor'
|
69
|
+
Monitor.new
|
70
|
+
end
|
71
|
+
@controllers_mutex.synchronize(&block)
|
72
|
+
end
|
73
|
+
# rubocop:enable ThreadSafety/InstanceVariableInClassMethod
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/gruf/cli/executor.rb
CHANGED
@@ -23,8 +23,14 @@ module Gruf
|
|
23
23
|
# Handles execution of the gruf binstub, along with command-line arguments
|
24
24
|
#
|
25
25
|
class Executor
|
26
|
+
class NoServicesBoundError < StandardError; end
|
27
|
+
|
26
28
|
##
|
27
29
|
# @param [Hash|ARGV]
|
30
|
+
# @param [::Gruf::Server|NilClass] server
|
31
|
+
# @param [Array<Class>|NilClass] services
|
32
|
+
# @param [Gruf::Hooks::Executor|NilClass] hook_executor
|
33
|
+
# @param [Logger|NilClass] logger
|
28
34
|
#
|
29
35
|
def initialize(
|
30
36
|
args = ARGV,
|
@@ -35,7 +41,7 @@ module Gruf
|
|
35
41
|
)
|
36
42
|
@args = args
|
37
43
|
setup! # ensure we set some defaults from CLI here so we can allow configuration
|
38
|
-
@services = services
|
44
|
+
@services = services.is_a?(Array) ? services : []
|
39
45
|
@hook_executor = hook_executor || Gruf::Hooks::Executor.new(hooks: Gruf.hooks&.prepare)
|
40
46
|
@server = server || Gruf::Server.new(Gruf.server_options)
|
41
47
|
@logger = logger || Gruf.logger || ::Logger.new($stderr)
|
@@ -46,6 +52,17 @@ module Gruf
|
|
46
52
|
#
|
47
53
|
def run
|
48
54
|
exception = nil
|
55
|
+
# wait to load controllers until last possible second to allow late configuration
|
56
|
+
::Gruf.autoloaders.load!(controllers_path: Gruf.controllers_path)
|
57
|
+
# allow lazy registering globally as late as possible, this allows more flexible binstub injections
|
58
|
+
@services = ::Gruf.services unless @services&.any?
|
59
|
+
|
60
|
+
unless @services.any?
|
61
|
+
raise NoServicesBoundError,
|
62
|
+
'No services bound to this gruf process; please bind a service to a Gruf controller ' \
|
63
|
+
'to start the server successfully'
|
64
|
+
end
|
65
|
+
|
49
66
|
begin
|
50
67
|
@services.each { |s| @server.add_service(s) }
|
51
68
|
@hook_executor.call(:before_server_start, server: @server)
|
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
|
##
|
@@ -36,33 +37,5 @@ module Gruf
|
|
36
37
|
super
|
37
38
|
end
|
38
39
|
end
|
39
|
-
|
40
|
-
##
|
41
|
-
# See https://github.com/grpc/grpc-go/blob/master/codes/codes.go for a detailed summary of each error type
|
42
|
-
#
|
43
|
-
module Errors
|
44
|
-
class Base < Gruf::Client::Error; end
|
45
|
-
class Error < Base; end
|
46
|
-
class Validation < Base; end
|
47
|
-
|
48
|
-
class Ok < Base; end
|
49
|
-
|
50
|
-
class InvalidArgument < Validation; end
|
51
|
-
class NotFound < Validation; end
|
52
|
-
class AlreadyExists < Validation; end
|
53
|
-
class OutOfRange < Validation; end
|
54
|
-
|
55
|
-
class Cancelled < Error; end
|
56
|
-
class DataLoss < Error; end
|
57
|
-
class DeadlineExceeded < Error; end
|
58
|
-
class FailedPrecondition < Error; end
|
59
|
-
class Internal < Error; end
|
60
|
-
class PermissionDenied < Error; end
|
61
|
-
class ResourceExhausted < Error; end
|
62
|
-
class Unauthenticated < Error; end
|
63
|
-
class Unavailable < Error; end
|
64
|
-
class Unimplemented < Error; end
|
65
|
-
class Unknown < Error; end
|
66
|
-
end
|
67
40
|
end
|
68
41
|
end
|
@@ -0,0 +1,48 @@
|
|
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
|
+
# See https://github.com/grpc/grpc-go/blob/master/codes/codes.go for a detailed summary of each error type
|
22
|
+
#
|
23
|
+
module Errors
|
24
|
+
class Base < Gruf::Client::Error; end
|
25
|
+
class Error < Base; end
|
26
|
+
class Validation < Base; end
|
27
|
+
|
28
|
+
class Ok < Base; end
|
29
|
+
|
30
|
+
class InvalidArgument < Validation; end
|
31
|
+
class NotFound < Validation; end
|
32
|
+
class AlreadyExists < Validation; end
|
33
|
+
class OutOfRange < Validation; end
|
34
|
+
|
35
|
+
class Cancelled < Error; end
|
36
|
+
class DataLoss < Error; end
|
37
|
+
class DeadlineExceeded < Error; end
|
38
|
+
class FailedPrecondition < Error; end
|
39
|
+
class Internal < Error; end
|
40
|
+
class PermissionDenied < Error; end
|
41
|
+
class ResourceExhausted < Error; end
|
42
|
+
class Unauthenticated < Error; end
|
43
|
+
class Unavailable < Error; end
|
44
|
+
class Unimplemented < Error; end
|
45
|
+
class Unknown < Error; end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/gruf/client.rb
CHANGED
@@ -15,9 +15,6 @@
|
|
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
|
-
require_relative 'client/error'
|
19
|
-
require_relative 'client/error_factory'
|
20
|
-
|
21
18
|
module Gruf
|
22
19
|
##
|
23
20
|
# Abstracts out the calling interface for interacting with gRPC clients. Streamlines calling and provides
|
@@ -38,11 +35,14 @@ module Gruf
|
|
38
35
|
class Client < SimpleDelegator
|
39
36
|
include Gruf::Loggable
|
40
37
|
|
41
|
-
#
|
38
|
+
# @!attribute [r] base_klass
|
39
|
+
# @return [Class] The base, friendly name of the service being requested
|
42
40
|
attr_reader :base_klass
|
43
|
-
#
|
41
|
+
# @!attribute [r] service_klass
|
42
|
+
# @return [Class] The class name of the gRPC service being requested
|
44
43
|
attr_reader :service_klass
|
45
|
-
#
|
44
|
+
# @!attribute [r] opts
|
45
|
+
# @return [Hash] A hash of options for the client
|
46
46
|
attr_reader :opts
|
47
47
|
|
48
48
|
##
|
@@ -230,7 +230,7 @@ module Gruf
|
|
230
230
|
GRPC::Core::TimeConsts::ZERO
|
231
231
|
elsif timeout.is_a?(GRPC::Core::TimeSpec)
|
232
232
|
timeout
|
233
|
-
elsif timeout.is_a?(Numeric)
|
233
|
+
elsif timeout.is_a?(Numeric) # rubocop:disable Lint/DuplicateBranch
|
234
234
|
timeout
|
235
235
|
elsif timeout.respond_to?(:to_f)
|
236
236
|
timeout.to_f
|
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',
|
@@ -27,7 +84,7 @@ module Gruf
|
|
27
84
|
interceptors: nil,
|
28
85
|
hooks: nil,
|
29
86
|
default_channel_credentials: nil,
|
30
|
-
default_client_host: '',
|
87
|
+
default_client_host: '0.0.0.0:9001',
|
31
88
|
use_ssl: false,
|
32
89
|
ssl_crt_file: '',
|
33
90
|
ssl_key_file: '',
|
@@ -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
|
@@ -100,26 +157,40 @@ module Gruf
|
|
100
157
|
VALID_CONFIG_KEYS.each do |k, v|
|
101
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
|
+
cp = ::ENV.fetch('GRUF_CONTROLLERS_PATH', 'app/rpc').to_s
|
169
|
+
self.controllers_path = root_path.to_s.empty? ? cp : "#{root_path}/#{cp}"
|
170
|
+
self.backtrace_on_error = ::ENV.fetch('GRPC_BACKTRACE_ON_ERROR', 0).to_i.positive?
|
171
|
+
self.rpc_server_options = {
|
172
|
+
max_waiting_requests: ::ENV.fetch('GRPC_SERVER_MAX_WAITING_REQUESTS',
|
173
|
+
GRPC::RpcServer::DEFAULT_MAX_WAITING_REQUESTS).to_i,
|
174
|
+
pool_size: ::ENV.fetch('GRPC_SERVER_POOL_SIZE', GRPC::RpcServer::DEFAULT_POOL_SIZE).to_i,
|
175
|
+
pool_keep_alive: ::ENV.fetch('GRPC_SERVER_POOL_KEEP_ALIVE', GRPC::Pool::DEFAULT_KEEP_ALIVE).to_i,
|
176
|
+
poll_period: ::ENV.fetch('GRPC_SERVER_POLL_PERIOD', GRPC::RpcServer::DEFAULT_POLL_PERIOD).to_i,
|
177
|
+
connect_md_proc: nil,
|
178
|
+
server_args: {}
|
179
|
+
}
|
116
180
|
if use_default_interceptors
|
117
|
-
interceptors.use(Gruf::Interceptors::ActiveRecord::ConnectionReset)
|
118
|
-
interceptors.use(Gruf::Interceptors::Instrumentation::OutputMetadataTimer)
|
181
|
+
interceptors.use(::Gruf::Interceptors::ActiveRecord::ConnectionReset)
|
182
|
+
interceptors.use(::Gruf::Interceptors::Instrumentation::OutputMetadataTimer)
|
119
183
|
end
|
120
184
|
options
|
121
185
|
end
|
122
186
|
|
187
|
+
##
|
188
|
+
# @return [Boolean]
|
189
|
+
#
|
190
|
+
def development?
|
191
|
+
environment == 'development'
|
192
|
+
end
|
193
|
+
|
123
194
|
private
|
124
195
|
|
125
196
|
##
|
@@ -128,11 +199,30 @@ module Gruf
|
|
128
199
|
# @return [String] The current Ruby environment
|
129
200
|
#
|
130
201
|
def environment
|
131
|
-
if defined?(Rails)
|
132
|
-
Rails.env.to_s
|
202
|
+
if defined?(::Rails)
|
203
|
+
::Rails.env.to_s
|
204
|
+
else
|
205
|
+
ENV.fetch('RACK_ENV') { ENV.fetch('RAILS_ENV', 'development') }.to_s
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Dynamically determine the appropriate logger
|
211
|
+
#
|
212
|
+
def determine_loggers
|
213
|
+
if defined?(::Rails) && ::Rails.logger
|
214
|
+
self.logger = ::Rails.logger
|
133
215
|
else
|
134
|
-
|
216
|
+
require 'logger'
|
217
|
+
self.logger = ::Logger.new($stdout)
|
218
|
+
log_level = ::ENV.fetch('LOG_LEVEL', 'info').to_s.upcase
|
219
|
+
begin
|
220
|
+
logger.level = ::Logger::Severity.const_get(log_level)
|
221
|
+
rescue NameError => _e
|
222
|
+
logger.level = ::Logger::Severity::INFO
|
223
|
+
end
|
135
224
|
end
|
225
|
+
self.grpc_logger = logger if grpc_logger.nil?
|
136
226
|
end
|
137
227
|
end
|
138
228
|
end
|
@@ -0,0 +1,74 @@
|
|
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
|
+
# Handles autoloading of Gruf controllers in the application path. This allows for code reloading on Gruf
|
22
|
+
# controllers.
|
23
|
+
#
|
24
|
+
class Autoloader
|
25
|
+
include ::Gruf::Loggable
|
26
|
+
|
27
|
+
# @!attribute [r] path
|
28
|
+
# @return [String] The path for this autoloader
|
29
|
+
attr_reader :path
|
30
|
+
|
31
|
+
##
|
32
|
+
# @param [String] path
|
33
|
+
# @param [Boolean] reloading
|
34
|
+
# @param [String] tag
|
35
|
+
#
|
36
|
+
def initialize(path:, reloading: nil, tag: nil)
|
37
|
+
super()
|
38
|
+
@path = path
|
39
|
+
@loader = ::Zeitwerk::Loader.new
|
40
|
+
@loader.tag = tag || 'gruf-controllers'
|
41
|
+
@setup = false
|
42
|
+
@reloading_enabled = reloading || ::Gruf.development?
|
43
|
+
setup!
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Reload all files managed by the autoloader, if reloading is enabled
|
48
|
+
#
|
49
|
+
def reload
|
50
|
+
@loader.reload if @reloading_enabled
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
##
|
56
|
+
# @return [Boolean]
|
57
|
+
#
|
58
|
+
def setup!
|
59
|
+
return true if @setup
|
60
|
+
|
61
|
+
return false unless File.directory?(@path)
|
62
|
+
|
63
|
+
@loader.enable_reloading if @reloading_enabled
|
64
|
+
@loader.ignore("#{@path}/**/*_pb.rb")
|
65
|
+
@loader.push_dir(@path)
|
66
|
+
@loader.setup
|
67
|
+
# always eager load RPC files, so that the service binder can bind the Gruf::Controller instantiation
|
68
|
+
# to the gRPC Service classes
|
69
|
+
@loader.eager_load
|
70
|
+
@setup = true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|