gruf 2.2.2 → 2.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +107 -12
- data/CODE_OF_CONDUCT.md +38 -41
- data/README.md +8 -360
- data/bin/gruf +2 -12
- data/gruf.gemspec +31 -7
- data/lib/gruf/cli/executor.rb +102 -0
- data/lib/gruf/client/error.rb +68 -0
- data/lib/gruf/client/error_factory.rb +105 -0
- data/lib/gruf/client.rb +52 -38
- data/lib/gruf/configuration.rb +25 -5
- data/lib/gruf/controllers/base.rb +35 -12
- data/lib/gruf/controllers/request.rb +21 -10
- data/lib/gruf/controllers/service_binder.rb +38 -6
- data/lib/gruf/error.rb +34 -9
- data/lib/gruf/errors/debug_info.rb +9 -2
- data/lib/gruf/errors/field.rb +2 -0
- data/lib/gruf/errors/helpers.rb +5 -0
- data/lib/gruf/hooks/base.rb +34 -0
- data/lib/gruf/hooks/executor.rb +47 -0
- data/lib/gruf/hooks/registry.rb +159 -0
- data/lib/gruf/instrumentable_grpc_server.rb +64 -0
- data/lib/gruf/integrations/rails/railtie.rb +10 -0
- data/lib/gruf/interceptors/active_record/connection_reset.rb +4 -3
- data/lib/gruf/interceptors/authentication/basic.rb +10 -2
- data/lib/gruf/interceptors/base.rb +3 -0
- data/lib/gruf/interceptors/client_interceptor.rb +117 -0
- data/lib/gruf/interceptors/context.rb +6 -4
- data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +5 -4
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +5 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +5 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +5 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +60 -29
- data/lib/gruf/interceptors/instrumentation/statsd.rb +5 -4
- data/lib/gruf/interceptors/registry.rb +6 -1
- data/lib/gruf/interceptors/server_interceptor.rb +2 -0
- data/lib/gruf/interceptors/timer.rb +12 -2
- data/lib/gruf/loggable.rb +2 -0
- data/lib/gruf/logging.rb +2 -0
- data/lib/gruf/outbound/request_context.rb +71 -0
- data/lib/gruf/response.rb +5 -2
- data/lib/gruf/serializers/errors/base.rb +2 -0
- data/lib/gruf/serializers/errors/json.rb +2 -0
- data/lib/gruf/server.rb +57 -23
- data/lib/gruf/synchronized_client.rb +97 -0
- data/lib/gruf/timer.rb +9 -6
- data/lib/gruf/version.rb +3 -1
- data/lib/gruf.rb +10 -0
- metadata +254 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bffd546b0bd27dcd8cd54146065623e73e0396211ae263985a197255bb8ec48a
|
4
|
+
data.tar.gz: 9b0364643ab5c1008a330ed61c8fba4458f9b075c34eea81acb10de4ee70f53d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ef4637ca552b572f77b270ccdc491c660b62d7c1d8ff85fe67151cf22f09e92f18a9b88b63d31e956411cb46380ba695e0eccc74d47a2095c8fc7d6ebfaf838
|
7
|
+
data.tar.gz: 0f38cc6c69487f1cab2ebc5e07b5a06de20f5e35d0000ad4c80a021288557aaaef2acf58fe254be6dc292ddd2e764976acfdd65578a7a0233c663dea83018eb3
|
data/CHANGELOG.md
CHANGED
@@ -2,13 +2,108 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
2
2
|
|
3
3
|
### Pending release
|
4
4
|
|
5
|
+
### 2.9.1
|
6
|
+
|
7
|
+
- Drop support for Ruby 2.4/2.5 to align with Ruby EOL schedule, supporting 2.6+ only
|
8
|
+
- Allow for float/TimeSpec timeout values on clients
|
9
|
+
|
10
|
+
### 2.9.0
|
11
|
+
|
12
|
+
- Change to racially neutral terminology across library
|
13
|
+
- blacklist->blocklist
|
14
|
+
- master->main branch
|
15
|
+
- Explicitly declare development dependencies in gemspec
|
16
|
+
- Add script/e2e test for full e2e test in regression suite
|
17
|
+
- Explicitly declare [json gem](https://rubygems.org/gems/json) dependency
|
18
|
+
- Update to Rubocop 1.4, add in rubocop-rspec for spec tests
|
19
|
+
- Add Ruby 2.7, 3.0 support
|
20
|
+
|
21
|
+
### 2.8.1
|
22
|
+
|
23
|
+
- Fix issue with --suppress-default-interceptors not working [#95]
|
24
|
+
- Loosen rake development dependency to >= 10.0 [#97]
|
25
|
+
|
26
|
+
### 2.8.0
|
27
|
+
|
28
|
+
- Pass the controller request object into the request logging formatters [#92]
|
29
|
+
|
30
|
+
### 2.7.1
|
31
|
+
|
32
|
+
- Add `channel_credentials` option to `Gruf::Client` and `default_channel_credentials` option to `Gruf::Configuration` [#85] [#87]
|
33
|
+
|
34
|
+
### 2.7.0
|
35
|
+
|
36
|
+
- Add hook support for executing code paths before a server is started, and after a server stops
|
37
|
+
|
38
|
+
### 2.6.1
|
39
|
+
|
40
|
+
- Add frozen_string_literal: true to files, update rubocop to 0.68
|
41
|
+
|
42
|
+
### 2.6.0
|
43
|
+
|
44
|
+
- 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
|
47
|
+
- Bump rubocop to 0.64, address violations, update activesupport/concurrent-ruby dependencies to have a min version
|
48
|
+
|
49
|
+
### 2.5.2
|
50
|
+
|
51
|
+
- Log ok/validation responses at DEBUG levels to prevent log stampeding in high-volume environments
|
52
|
+
|
53
|
+
### 2.5.1
|
54
|
+
|
55
|
+
- Ensure `timeout` is an int when passed as a client option to a gRPC client
|
56
|
+
- Add `bound_service` reader to `Gruf::Controllers::Base` for finding the service bound to the given controller
|
57
|
+
|
58
|
+
### 2.5.0
|
59
|
+
|
60
|
+
- Client exceptions raised now contain mapped subclasses, such as `Gruf::Client::Errors::InvalidArgument`
|
61
|
+
- Client exceptions will also now catch StandardError and GRPC::Core errors, and handle them as Internal errors
|
62
|
+
- Added SynchronizedClient which prevents multiple calls to the same endpoint with the same params at
|
63
|
+
a given time. This is useful for mitigating thundering herds. To skip this behavior for certain endpoints,
|
64
|
+
pass the `options[:unsynchronized_methods]` param with a list of method names (as symbols).
|
65
|
+
|
66
|
+
### 2.4.2
|
67
|
+
|
68
|
+
- Added error handling for GRPC::Core::CallError, a low-level error in the grpc library that does not inherit
|
69
|
+
from StandardError. [#59]
|
70
|
+
- Removed `Thread.abort\_on\_exception = true`. Exceptions should be handled by gruf or the application,
|
71
|
+
and should not cause the server process to crash. [#59]
|
72
|
+
- Added guard for size of trailing metadata attached to grpc call. The default max for http2 trailing metadata
|
73
|
+
in the gRPC C library is 8kb. If we go over that limit (either through custom metadata attached to the
|
74
|
+
error by the application, or via the error payload encoded by the error serializer), the gRPC library
|
75
|
+
will throw RESOURCE\_EXHAUSTED. Gruf now detects this case, and attempts to prevent it by logging the
|
76
|
+
original error and substituting it with an internal error indicating that the metadata was too large. [#60]
|
77
|
+
- Truncate stack trace in error payload to help avoid overflowing the trailing metadata. Added backtrace\_limit
|
78
|
+
configuration parameter, which defaults to 10.[#60]
|
79
|
+
|
80
|
+
### 2.4.1
|
81
|
+
|
82
|
+
- Safer configuration of GRPC::RpcServer. From now on, use `Gruf.rpc_server_options` for the params
|
83
|
+
to be sent to GPRC::RpcServer. Also provide sane defaults for params for GRPC::RpcServer. [#55]
|
84
|
+
- Added ability to monitor `RESOURCE_EXHAUSTED` and `UNIMPLEMENTED`. By setting `event_listener_proc` in
|
85
|
+
the Gruf configuration, you will receive a callback when these events occur. The parameter to your
|
86
|
+
callback will be a symbol (`:thread_pool_exhausted` or `:unimplemented`). Others may be added in the future.
|
87
|
+
|
88
|
+
### 2.4.0
|
89
|
+
|
90
|
+
- Added a hash of error log levels to RequestLogging interceptor, mapping error code to level of logging to use. To
|
91
|
+
override the level of logging per error response, provide a map of codes to log level in options, key :log_levels.
|
92
|
+
The default is :error log level.
|
93
|
+
|
94
|
+
### 2.3.0
|
95
|
+
|
96
|
+
- Add Gruf::Interceptors::ClientInterceptor for intercepting outbound client calls
|
97
|
+
- Add command-line arguments to the gruf binstub
|
98
|
+
- Add ability to specify server hostname via CLI argument
|
99
|
+
|
5
100
|
### 2.2.2
|
6
101
|
|
7
|
-
-
|
102
|
+
- Add ignore_methods option for RequestLogging interceptor [#45]
|
8
103
|
|
9
104
|
### 2.2.1
|
10
105
|
|
11
|
-
- Now changes proc title once server is ready to process incoming requests [#44]
|
106
|
+
- Now changes proc title once server is ready to process incoming requests [#44]
|
12
107
|
- Gruf now requires gRPC 1.10.x+ due to various fixes and improvements in the gRPC core libraries
|
13
108
|
|
14
109
|
### 2.2.0
|
@@ -17,13 +112,13 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
17
112
|
|
18
113
|
### 2.1.1
|
19
114
|
|
20
|
-
- Add ability to pass in client stub options into Gruf::Client
|
115
|
+
- Add ability to pass in client stub options into Gruf::Client
|
21
116
|
|
22
117
|
### 2.1.0
|
23
118
|
|
24
119
|
- Add ability to list, clear, insert before, insert after, and remove to a server's interceptor
|
25
120
|
registry
|
26
|
-
- Ensure interceptors and services cannot be adjusted on the server after it starts to
|
121
|
+
- Ensure interceptors and services cannot be adjusted on the server after it starts to
|
27
122
|
prevent threading issues
|
28
123
|
- [#36], [#37] Adds `response_class`, `request_class`, and `service` accessors to controller request
|
29
124
|
|
@@ -66,11 +161,11 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
|
|
66
161
|
### 1.2.4
|
67
162
|
|
68
163
|
- Loosen explicit Protobuf dependency now that 3.4.0.2 is released
|
69
|
-
- Guard against nil params in logger
|
164
|
+
- Guard against nil params in logger blocklist
|
70
165
|
|
71
166
|
### 1.2.3
|
72
167
|
|
73
|
-
- Support nested
|
168
|
+
- Support nested blocklist parameters in path.to.key format
|
74
169
|
|
75
170
|
### 1.2.2
|
76
171
|
|
@@ -86,22 +181,22 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
|
|
86
181
|
- Instrumentation hooks now execute similarly to outer_around hooks; they can
|
87
182
|
now instrument failures
|
88
183
|
- Instrumentation hooks now pass a `RequestContext` object that contains information
|
89
|
-
about the incoming request, instead of relying on instance variables
|
184
|
+
about the incoming request, instead of relying on instance variables
|
90
185
|
- StatsD hook now sends success/failure metrics for endpoints
|
91
186
|
- Add ability to turn off sending exception message on uncaught exception.
|
92
187
|
- Add configuration to set the error message when an uncaught exception is
|
93
188
|
handled by gruf.
|
94
|
-
- Add a request logging hook for Rails-style request logging, with optional
|
95
|
-
parameter logging,
|
189
|
+
- Add a request logging hook for Rails-style request logging, with optional
|
190
|
+
parameter logging, blocklists, and formatter support
|
96
191
|
- Optimizations around Symbol casting within service calls
|
97
192
|
|
98
193
|
### 1.1.0
|
99
194
|
|
100
|
-
- Add the ability for call options to the client, which enables deadline setting
|
195
|
+
- Add the ability for call options to the client, which enables deadline setting
|
101
196
|
|
102
197
|
### 1.0.0
|
103
198
|
|
104
|
-
- Bump gRPC to 1.4
|
199
|
+
- Bump gRPC to 1.4
|
105
200
|
|
106
201
|
### 0.14.2
|
107
202
|
|
@@ -130,7 +225,7 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
|
|
130
225
|
### 0.12.0
|
131
226
|
|
132
227
|
- Add ability to run multiple around hooks
|
133
|
-
- Fix bug with error handling that caused error messages to repeat across streams
|
228
|
+
- Fix bug with error handling that caused error messages to repeat across streams
|
134
229
|
|
135
230
|
### 0.11.5
|
136
231
|
|
data/CODE_OF_CONDUCT.md
CHANGED
@@ -1,49 +1,46 @@
|
|
1
|
-
# Contributor Code of Conduct
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
2
|
|
3
|
-
|
4
|
-
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
-
contribute through reporting issues, posting feature requests, updating
|
6
|
-
documentation, submitting pull requests or patches, and other activities.
|
3
|
+
## Our Pledge
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
6
|
+
|
7
|
+
## Our Standards
|
8
|
+
|
9
|
+
Examples of behavior that contributes to creating a positive environment include:
|
10
|
+
|
11
|
+
* Using welcoming and inclusive language
|
12
|
+
* Being respectful of differing viewpoints and experiences
|
13
|
+
* Gracefully accepting constructive criticism
|
14
|
+
* Focusing on what is best for the community
|
15
|
+
* Showing empathy towards other community members
|
12
16
|
|
13
17
|
Examples of unacceptable behavior by participants include:
|
14
18
|
|
15
|
-
* The use of sexualized language or imagery
|
16
|
-
*
|
17
|
-
* Trolling or insulting/derogatory comments
|
19
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
20
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
18
21
|
* Public or private harassment
|
19
|
-
* Publishing
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
-
incident.
|
43
|
-
|
44
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
-
version 1.3.0, available at
|
46
|
-
[http://contributor-covenant.org/version/1/3/0/][version]
|
22
|
+
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
23
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
24
|
+
|
25
|
+
## Our Responsibilities
|
26
|
+
|
27
|
+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
28
|
+
|
29
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
30
|
+
|
31
|
+
## Scope
|
32
|
+
|
33
|
+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
34
|
+
|
35
|
+
## Enforcement
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at engineering@bigcommerce.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
38
|
+
|
39
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
40
|
+
|
41
|
+
## Attribution
|
42
|
+
|
43
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
47
44
|
|
48
45
|
[homepage]: http://contributor-covenant.org
|
49
|
-
[version]: http://contributor-covenant.org/version/1/
|
46
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# gruf - gRPC Ruby Framework
|
2
2
|
|
3
|
-
[![
|
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
|
-
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/main/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,372 +17,20 @@ up fast and efficiently at scale. Some of its features include:
|
|
17
17
|
still preserving gRPC BadStatus codes
|
18
18
|
* Server and client execution timings in responses
|
19
19
|
|
20
|
-
gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.2-2.
|
21
|
-
gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any Ruby framework
|
22
|
-
(such as [Grape](https://github.com/ruby-grape/grape), for instance).
|
20
|
+
gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.2-2.7.
|
21
|
+
gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any Ruby framework
|
22
|
+
(such as [Grape](https://github.com/ruby-grape/grape) or [dry-rb](https://dry-rb.org/), for instance).
|
23
23
|
|
24
|
-
|
24
|
+
### Getting Started
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
```
|
29
|
-
|
30
|
-
Then in an initializer or before use:
|
31
|
-
|
32
|
-
```ruby
|
33
|
-
require 'gruf'
|
34
|
-
```
|
35
|
-
|
36
|
-
Make sure to review [UPGRADING.md](https://github.com/bigcommerce/gruf/blob/master/UPGRADING.md)
|
37
|
-
if you are upgrading gruf between minor or major versions.
|
38
|
-
|
39
|
-
### Client
|
40
|
-
|
41
|
-
Add an initializer:
|
42
|
-
|
43
|
-
```ruby
|
44
|
-
require 'gruf'
|
45
|
-
|
46
|
-
Gruf.configure do |c|
|
47
|
-
c.default_client_host = 'grpc.service.com:9003'
|
48
|
-
end
|
49
|
-
```
|
50
|
-
|
51
|
-
If you don't explicitly set `default_client_host`, you will need to pass it into the client options, like so:
|
52
|
-
|
53
|
-
```ruby
|
54
|
-
client = ::Gruf::Client.new(service: ::Demo::ThingService, options: {hostname: 'grpc.service.com:9003'})
|
55
|
-
```
|
56
|
-
|
57
|
-
From there, you can instantiate a client given a stub service (say on an SslCertificates proto with a GetSslCertificate call):
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
require 'gruf'
|
61
|
-
|
62
|
-
id = args[:id].to_i.presence || 1
|
63
|
-
|
64
|
-
begin
|
65
|
-
client = ::Gruf::Client.new(service: ::Demo::ThingService)
|
66
|
-
response = client.call(:GetMyThing, id: id)
|
67
|
-
puts response.message.inspect
|
68
|
-
rescue Gruf::Client::Error => e
|
69
|
-
puts e.error.inspect
|
70
|
-
end
|
71
|
-
```
|
72
|
-
|
73
|
-
Note this returns a response object. The response object can provide `trailing_metadata` as well as a `execution_time`.
|
74
|
-
|
75
|
-
### Server
|
76
|
-
|
77
|
-
Add an initializer:
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
require 'gruf'
|
81
|
-
|
82
|
-
Gruf.configure do |c|
|
83
|
-
c.server_binding_url = 'grpc.service.com:9003'
|
84
|
-
end
|
85
|
-
```
|
86
|
-
|
87
|
-
Next, setup some handlers based on your proto configurations in `/app/rpc/`. For example, for the Thing service, with a
|
88
|
-
GetThingReq/GetThingResp call based on this proto:
|
89
|
-
|
90
|
-
```proto
|
91
|
-
syntax = "proto3";
|
92
|
-
|
93
|
-
package demo;
|
94
|
-
|
95
|
-
service Jobs {
|
96
|
-
rpc GetJob(GetJobReq) returns (GetJobResp) { }
|
97
|
-
}
|
98
|
-
|
99
|
-
message GetJobReq {
|
100
|
-
uint64 id = 1;
|
101
|
-
}
|
102
|
-
|
103
|
-
message GetJobResp {
|
104
|
-
uint64 id = 1;
|
105
|
-
string name = 2;
|
106
|
-
}
|
107
|
-
```
|
108
|
-
|
109
|
-
You'd have this handler in `/app/rpc/demo/job_controller.rb`
|
110
|
-
|
111
|
-
```ruby
|
112
|
-
module Demo
|
113
|
-
class JobController < ::Gruf::Controllers::Base
|
114
|
-
bind ::Demo::Jobs::Service
|
115
|
-
|
116
|
-
##
|
117
|
-
# @return [Demo::GetJobResp] The job response
|
118
|
-
#
|
119
|
-
def get_job
|
120
|
-
thing = Job.find(request.message.id)
|
121
|
-
|
122
|
-
Demo::GetJobResp.new(id: thing.id)
|
123
|
-
rescue
|
124
|
-
fail!(:not_found, :job_not_found, "Failed to find Job with ID: #{request.message.id}")
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
```
|
129
|
-
|
130
|
-
Finally, you can start the server by running:
|
131
|
-
|
132
|
-
```bash
|
133
|
-
bundle exec gruf
|
134
|
-
```
|
135
|
-
|
136
|
-
### Basic Authentication
|
137
|
-
|
138
|
-
Gruf comes packaged in with a Basic Authentication interceptor. It takes in an array of supported
|
139
|
-
username and password pairs (or password-only credentials).
|
140
|
-
|
141
|
-
In Server:
|
142
|
-
|
143
|
-
```ruby
|
144
|
-
Gruf.configure do |c|
|
145
|
-
c.interceptors.use(
|
146
|
-
Gruf::Interceptors::Authentication::Basic,
|
147
|
-
credentials: [{
|
148
|
-
username: 'my-username-here',
|
149
|
-
password: 'my-password-here',
|
150
|
-
},{
|
151
|
-
username: 'another-username',
|
152
|
-
password: 'another-password',
|
153
|
-
},{
|
154
|
-
password: 'a-password-only'
|
155
|
-
}]
|
156
|
-
)
|
157
|
-
end
|
158
|
-
```
|
159
|
-
|
160
|
-
In Client:
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
require 'gruf'
|
164
|
-
|
165
|
-
id = args[:id].to_i.presence || 1
|
166
|
-
|
167
|
-
options = {
|
168
|
-
username: ENV.fetch('DEMO_THING_SERVICE_USERNAME'),
|
169
|
-
password: ENV.fetch('DEMO_THING_SERVICE_PASSWORD')
|
170
|
-
}
|
171
|
-
|
172
|
-
begin
|
173
|
-
client = ::Gruf::Client.new(service: ::Demo::ThingService, options: options)
|
174
|
-
response = client.call(:GetMyThing, id: id)
|
175
|
-
puts response.message.inspect
|
176
|
-
rescue Gruf::Client::Error => e
|
177
|
-
puts e.error.inspect
|
178
|
-
end
|
179
|
-
```
|
180
|
-
|
181
|
-
Supporting an array of credentials allow for unique credentials per service, or for easy credential
|
182
|
-
rotation with zero downtime.
|
183
|
-
|
184
|
-
### SSL Configuration
|
185
|
-
|
186
|
-
We don't recommend using TLS for gRPC, but instead using something like [linkerd](https://linkerd.io) for TLS
|
187
|
-
encryption between services. If you need it, however, this library supports TLS.
|
188
|
-
|
189
|
-
For the client, you'll need to point to the public certificate:
|
190
|
-
|
191
|
-
```ruby
|
192
|
-
::Gruf::Client.new(
|
193
|
-
service: Demo::ThingService,
|
194
|
-
ssl_certificate: 'x509 public certificate here',
|
195
|
-
# OR
|
196
|
-
ssl_certificate_file: '/path/to/my.crt'
|
197
|
-
)
|
198
|
-
```
|
199
|
-
|
200
|
-
If you want to run a server you'll need both the CRT and the key file if you want to do credentialed auth:
|
201
|
-
|
202
|
-
```ruby
|
203
|
-
Gruf.configure do |c|
|
204
|
-
c.use_ssl = true
|
205
|
-
c.ssl_crt_file = "#{Rails.root}/config/ssl/#{Rails.env}.crt"
|
206
|
-
c.ssl_key_file = "#{Rails.root}/config/ssl/#{Rails.env}.key"
|
207
|
-
end
|
208
|
-
```
|
209
|
-
|
210
|
-
## Server Interceptors
|
211
|
-
|
212
|
-
gruf supports interceptors around the grpc server calls, allowing you to perform actions around your service
|
213
|
-
method calls. This can be used to add tracing data, connection resets in the grpc thread pool, further
|
214
|
-
instrumentation, and other things.
|
215
|
-
|
216
|
-
Adding a hook is as simple as creating a class that extends `Gruf::Interceptor::ServerInterceptor`,
|
217
|
-
and a `call` method that yields control to get the method result:
|
218
|
-
|
219
|
-
```ruby
|
220
|
-
class MyInterceptor < ::Gruf::Interceptors::ServerInterceptor
|
221
|
-
def call
|
222
|
-
yield
|
223
|
-
end
|
224
|
-
end
|
225
|
-
```
|
226
|
-
|
227
|
-
Interceptors have access to the `request` object, which is the `Gruf::Controller::Request` object
|
228
|
-
described above.
|
229
|
-
|
230
|
-
### Failing in an Interceptor
|
231
|
-
|
232
|
-
Interceptors can fail requests with the same method calls as a controller:
|
233
|
-
|
234
|
-
```ruby
|
235
|
-
class MyFailingInterceptor < ::Gruf::Interceptors::ServerInterceptor
|
236
|
-
def call
|
237
|
-
result = yield # this returns the protobuf message
|
238
|
-
unless result.dont_hijack
|
239
|
-
# we'll assume this "dont_hijack" attribute exists on the message for this example
|
240
|
-
fail!(:internal, :hijacked, 'Hijack all the things!')
|
241
|
-
end
|
242
|
-
result
|
243
|
-
end
|
244
|
-
end
|
245
|
-
```
|
246
|
-
|
247
|
-
Similarly, you can raise `GRPC::BadStatus` calls to trigger similar errors without accompanying metadata.
|
248
|
-
|
249
|
-
### Configuring Interceptors
|
250
|
-
|
251
|
-
From there, the interceptor can be added to the server manually (if not executing via `bundle exec gruf`):
|
252
|
-
|
253
|
-
```ruby
|
254
|
-
server = Gruf::Server.new
|
255
|
-
server.add_interceptor(MyInterceptor, option_foo: 'value 123')
|
256
|
-
```
|
257
|
-
|
258
|
-
Or, alternatively, the more common method of passing them into the `interceptors` configuration hash:
|
259
|
-
|
260
|
-
```ruby
|
261
|
-
Gruf.configure do |c|
|
262
|
-
c.interceptors.use(MyInterceptor, option_foo: 'value 123')
|
263
|
-
end
|
264
|
-
```
|
265
|
-
|
266
|
-
Interceptors each wrap the call and are run recursively within each other. This means that if you have
|
267
|
-
three interceptors - `Interceptor1`, `Interceptor2`, and `Interceptor3` - they will run in FIFO
|
268
|
-
(first in, first out) order. `Interceptor1` will run, yielding to `Interceptor2`,
|
269
|
-
which will then yield to `Interceptor3`, which will then yield to your service method call,
|
270
|
-
ending the chain.
|
271
|
-
|
272
|
-
You can utilize the `insert_before` and `insert_after` methods to maintain order:
|
273
|
-
|
274
|
-
```ruby
|
275
|
-
Gruf.configure do |c|
|
276
|
-
c.interceptors.use(Interceptor1)
|
277
|
-
c.interceptors.use(Interceptor2)
|
278
|
-
c.interceptors.insert_before(Interceptor2, Interceptor3) # 3 will now happen before 2
|
279
|
-
c.interceptors.insert_after(Interceptor1, Interceptor4) # 4 will now happen after 1
|
280
|
-
end
|
281
|
-
```
|
282
|
-
|
283
|
-
By default, the ActiveRecord Connection Reset interceptor and Output Metadata Timing interceptor
|
284
|
-
are loaded into gruf unless explicitly told not to via the `use_default_interceptors` configuration
|
285
|
-
parameter.
|
286
|
-
|
287
|
-
## Instrumentation
|
288
|
-
|
289
|
-
gruf comes out of the box with a couple of instrumentation interceptors packed in:
|
290
|
-
output metadata timings and StatsD support.
|
291
|
-
|
292
|
-
### Output Metadata Timing
|
293
|
-
|
294
|
-
Enabled by default, this will push timings for _successful responses_ through the response output
|
295
|
-
metadata back to the client.
|
296
|
-
|
297
|
-
### StatsD
|
298
|
-
|
299
|
-
The StatsD support is not enabled by default. To enable it, you'll want to do:
|
300
|
-
|
301
|
-
```ruby
|
302
|
-
Gruf.configure do |c|
|
303
|
-
c.interceptors.use(
|
304
|
-
Gruf::Interceptors::Instrumentation::Statsd,
|
305
|
-
client: ::Statsd.new('my.statsd.host', 8125),
|
306
|
-
prefix: 'my_application_prefix.rpc'
|
307
|
-
)
|
308
|
-
end
|
309
|
-
```
|
310
|
-
|
311
|
-
This will measure counts and timings for each endpoint.
|
312
|
-
|
313
|
-
### Request Logging
|
314
|
-
|
315
|
-
Gruf 1.2+ comes built with request logging out of the box; you'll get Rails-style logs with your
|
316
|
-
gRPC calls:
|
317
|
-
|
318
|
-
```
|
319
|
-
# plain
|
320
|
-
I, [2017-07-14T09:50:54.200506 #70571] INFO -- : [GRPC::Ok] (thing_service.get_thing) [0.348ms]
|
321
|
-
# logstash
|
322
|
-
I, [2017-07-14T09:51:03.299050 #70595] INFO -- : {"message":"[GRPC::Ok] (thing_service.get_thing) [0.372ms]","service":"thing_service","method":"thing_service.get_thing","grpc_status":"GRPC::Ok"}
|
323
|
-
```
|
324
|
-
|
325
|
-
It supports formatters (including custom ones) that you can use to specify the formatting of the logging:
|
326
|
-
|
327
|
-
```ruby
|
328
|
-
Gruf.configure do |c|
|
329
|
-
c.interceptors.use(
|
330
|
-
Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor,
|
331
|
-
formatter: :logstash
|
332
|
-
)
|
333
|
-
end
|
334
|
-
```
|
335
|
-
|
336
|
-
It comes with a few more options as well:
|
337
|
-
|
338
|
-
| Option | Description | Default |
|
339
|
-
| ------ | ----------- | ------- |
|
340
|
-
| formatter | The formatter to use. By default `:plain` and `:logstash` are supported. | `:logstash` |
|
341
|
-
| log_parameters | If set to true, will log parameters in the response | `false` |
|
342
|
-
| blacklist | An array of parameter key names to redact from logging, in path.to.key format | `[]` |
|
343
|
-
| redacted_string | The string to use for redacted parameters. | `REDACTED` |
|
344
|
-
| ignore_methods | An array of method names to ignore from logging. E.g. `['namespace.health.check']` | `[]` |
|
345
|
-
|
346
|
-
It's important to maintain a safe blacklist should you decide to log parameters; gruf does no
|
347
|
-
parameter sanitization on its own. We also recommend blacklisting parameters that may contain
|
348
|
-
very large values (such as binary or json data).
|
349
|
-
|
350
|
-
## Plugins
|
351
|
-
|
352
|
-
You can build your own hooks and middleware for gruf; here's a list of known open source gems for
|
353
|
-
gruf that you can use today:
|
354
|
-
|
355
|
-
* [gruf-zipkin](https://github.com/bigcommerce/gruf-zipkin) - Provides a [Zipkin](https://zipkin.io)
|
356
|
-
integration
|
357
|
-
* [gruf-circuit-breaker](https://github.com/bigcommerce/gruf-circuit-breaker) - Circuit breaker
|
358
|
-
support for services
|
359
|
-
* [gruf-profiler](https://github.com/bigcommerce/gruf-profiler) - Profiles and provides memory usage
|
360
|
-
reports for clients and services
|
361
|
-
* [gruf-commander](https://github.com/bigcommerce/gruf-commander) - Request/command-style validation and
|
362
|
-
execution patterns for services
|
26
|
+
Please see the [gruf wiki](https://github.com/bigcommerce/gruf/wiki) for detailed information on getting started
|
27
|
+
using gruf.
|
363
28
|
|
364
29
|
## Demo Rails App
|
365
30
|
|
366
31
|
There is a [demonstration Rails application here](https://github.com/bigcommerce/gruf-demo) you can
|
367
32
|
view and clone that shows how to integrate Gruf into an existing Rails application.
|
368
33
|
|
369
|
-
## Roadmap
|
370
|
-
|
371
|
-
### Gruf 3.0
|
372
|
-
|
373
|
-
* Utilize the new core Ruby interceptors in gRPC 1.7
|
374
|
-
* Support client interceptors
|
375
|
-
* Change configuration to an injectable object to ensure thread safety on chained server/client interactions
|
376
|
-
* Move all references to `Gruf.` configuration into injectable parameters
|
377
|
-
* Redo server configuration to be fully injectable
|
378
|
-
* Move client calls to their native method implementation
|
379
|
-
|
380
|
-
## Companies Using Gruf
|
381
|
-
|
382
|
-
Using gruf and want to show your support? Let us know and we'll add your name here.
|
383
|
-
|
384
|
-
* [BigCommerce](https://www.bigcommerce.com/)
|
385
|
-
|
386
34
|
## License
|
387
35
|
|
388
36
|
Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
data/bin/gruf
CHANGED
@@ -25,15 +25,5 @@ end
|
|
25
25
|
load 'config/environment.rb' if defined?(Rails)
|
26
26
|
require 'gruf'
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
Gruf.services.each { |s| server.add_service(s) }
|
31
|
-
server.start!
|
32
|
-
rescue => e
|
33
|
-
msg = "FATAL ERROR: #{e.message} #{e.backtrace.join("\n")}"
|
34
|
-
if Gruf.logger
|
35
|
-
Gruf.logger.fatal msg
|
36
|
-
else
|
37
|
-
Logger.new(STDOUT).fatal msg
|
38
|
-
end
|
39
|
-
end
|
28
|
+
cli = Gruf::Cli::Executor.new
|
29
|
+
cli.run
|