gruf 2.9.1 → 2.15.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![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)
|
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) [![Maintainability](https://api.codeclimate.com/v1/badges/4a8e9269f99100aeb7cb/maintainability)](https://codeclimate.com/github/bigcommerce/gruf/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/4a8e9269f99100aeb7cb/test_coverage)](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
|