gruf 2.1.0 → 2.1.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 +4 -0
- data/README.md +88 -45
- data/lib/gruf/client.rb +13 -2
- data/lib/gruf/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53a6a934e512aeba4261172db33d22e9994ede7f
|
4
|
+
data.tar.gz: 5fb09d8483bd0ff4d22f759ab9ae442b3f4e63cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f8ff602e9d5a53eface3706b55546dd83f964cae57a20d1dc41d74aa6770a6f06d67a3a1aa0c040f3091b03cc3a132bca6d83ed3eb5351ee0520b7c480d6c0f
|
7
|
+
data.tar.gz: a44dd99112b76fa2f5116a6418cc80a90c5c7ff8a1ad8a4c45e03bcd384172ced2221d60daf7614c2a022f107b2fdd19e0d786c84dfb4ea9c3a4b1f090f3fbc5
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
2
2
|
|
3
3
|
### Pending release
|
4
4
|
|
5
|
+
### 2.1.1
|
6
|
+
|
7
|
+
- Add ability to pass in client stub options into Gruf::Client
|
8
|
+
|
5
9
|
### 2.1.0
|
6
10
|
|
7
11
|
- Add ability to list, clear, insert before, insert after, and remove to a server's interceptor
|
data/README.md
CHANGED
@@ -8,17 +8,17 @@ provide a more streamlined integration into Ruby and Ruby on Rails applications.
|
|
8
8
|
It provides an abstracted server and client for gRPC services, along with other tools to help get gRPC services in Ruby
|
9
9
|
up fast and efficiently at scale. Some of its features include:
|
10
10
|
|
11
|
-
* Abstracted controllers with request context support
|
12
|
-
* Full interceptors with timing and unified request context support
|
11
|
+
* Abstracted controllers with request context support
|
12
|
+
* Full interceptors with timing and unified request context support
|
13
13
|
* Robust client error handling and metadata transport abilities
|
14
14
|
* Server authentication via interceptors, with basic auth with multiple key support built in
|
15
15
|
* TLS support for client-server auth, though we recommend using [linkerd](https://linkerd.io/) instead
|
16
|
-
* Error data serialization in output metadata to allow fine-grained error handling in the transport while
|
16
|
+
* Error data serialization in output metadata to allow fine-grained error handling in the transport while
|
17
17
|
still preserving gRPC BadStatus codes
|
18
18
|
* Server and client execution timings in responses
|
19
19
|
|
20
20
|
gruf currently has active support for gRPC 1.4.x-1.8.x. gruf is compatible and tested with Ruby 2.2,
|
21
|
-
2.3, and 2.4. gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any
|
21
|
+
2.3, and 2.4. gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any
|
22
22
|
Ruby framework (such as [Grape](https://github.com/ruby-grape/grape), for instance).
|
23
23
|
|
24
24
|
## Installation
|
@@ -33,11 +33,27 @@ Then in an initializer or before use:
|
|
33
33
|
require 'gruf'
|
34
34
|
```
|
35
35
|
|
36
|
-
Make sure to review [UPGRADING.md](https://github.com/bigcommerce/gruf/blob/master/UPGRADING.md)
|
36
|
+
Make sure to review [UPGRADING.md](https://github.com/bigcommerce/gruf/blob/master/UPGRADING.md)
|
37
37
|
if you are upgrading gruf between minor or major versions.
|
38
38
|
|
39
39
|
### Client
|
40
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
|
+
|
41
57
|
From there, you can instantiate a client given a stub service (say on an SslCertificates proto with a GetSslCertificate call):
|
42
58
|
|
43
59
|
```ruby
|
@@ -68,10 +84,10 @@ Gruf.configure do |c|
|
|
68
84
|
end
|
69
85
|
```
|
70
86
|
|
71
|
-
Next, setup some handlers based on your proto configurations in `/app/rpc/`. For example, for the Thing service, with a
|
87
|
+
Next, setup some handlers based on your proto configurations in `/app/rpc/`. For example, for the Thing service, with a
|
72
88
|
GetThingReq/GetThingResp call based on this proto:
|
73
89
|
|
74
|
-
```
|
90
|
+
```proto
|
75
91
|
syntax = "proto3";
|
76
92
|
|
77
93
|
package demo;
|
@@ -96,13 +112,13 @@ You'd have this handler in `/app/rpc/demo/job_controller.rb`
|
|
96
112
|
module Demo
|
97
113
|
class JobController < ::Gruf::Controllers::Base
|
98
114
|
bind ::Demo::Jobs::Service
|
99
|
-
|
115
|
+
|
100
116
|
##
|
101
117
|
# @return [Demo::GetJobResp] The job response
|
102
118
|
#
|
103
119
|
def get_job
|
104
120
|
thing = Job.find(request.message.id)
|
105
|
-
|
121
|
+
|
106
122
|
Demo::GetJobResp.new(id: thing.id)
|
107
123
|
rescue
|
108
124
|
fail!(:not_found, :job_not_found, "Failed to find Job with ID: #{request.message.id}")
|
@@ -113,23 +129,27 @@ end
|
|
113
129
|
|
114
130
|
Finally, you can start the server by running:
|
115
131
|
|
116
|
-
|
132
|
+
```bash
|
133
|
+
bundle exec gruf
|
134
|
+
```
|
117
135
|
|
118
136
|
### Basic Authentication
|
119
137
|
|
120
|
-
Gruf comes packaged in with a Basic Authentication interceptor. It takes in an array of supported
|
138
|
+
Gruf comes packaged in with a Basic Authentication interceptor. It takes in an array of supported
|
121
139
|
username and password pairs (or password-only credentials).
|
122
140
|
|
141
|
+
In Server:
|
142
|
+
|
123
143
|
```ruby
|
124
144
|
Gruf.configure do |c|
|
125
145
|
c.interceptors.use(
|
126
146
|
Gruf::Interceptors::Authentication::Basic,
|
127
147
|
credentials: [{
|
128
148
|
username: 'my-username-here',
|
129
|
-
password: 'my-password-here',
|
149
|
+
password: 'my-password-here',
|
130
150
|
},{
|
131
151
|
username: 'another-username',
|
132
|
-
password: 'another-password',
|
152
|
+
password: 'another-password',
|
133
153
|
},{
|
134
154
|
password: 'a-password-only'
|
135
155
|
}]
|
@@ -137,7 +157,28 @@ Gruf.configure do |c|
|
|
137
157
|
end
|
138
158
|
```
|
139
159
|
|
140
|
-
|
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
|
141
182
|
rotation with zero downtime.
|
142
183
|
|
143
184
|
### SSL Configuration
|
@@ -152,7 +193,7 @@ For the client, you'll need to point to the public certificate:
|
|
152
193
|
service: Demo::ThingService,
|
153
194
|
ssl_certificate: 'x509 public certificate here',
|
154
195
|
# OR
|
155
|
-
ssl_certificate_file: '/path/to/my.crt'
|
196
|
+
ssl_certificate_file: '/path/to/my.crt'
|
156
197
|
)
|
157
198
|
```
|
158
199
|
|
@@ -169,10 +210,10 @@ end
|
|
169
210
|
## Server Interceptors
|
170
211
|
|
171
212
|
gruf supports interceptors around the grpc server calls, allowing you to perform actions around your service
|
172
|
-
method calls. This can be used to add tracing data, connection resets in the grpc thread pool, further
|
213
|
+
method calls. This can be used to add tracing data, connection resets in the grpc thread pool, further
|
173
214
|
instrumentation, and other things.
|
174
215
|
|
175
|
-
Adding a hook is as simple as creating a class that extends `Gruf::Interceptor::ServerInterceptor`,
|
216
|
+
Adding a hook is as simple as creating a class that extends `Gruf::Interceptor::ServerInterceptor`,
|
176
217
|
and a `call` method that yields control to get the method result:
|
177
218
|
|
178
219
|
```ruby
|
@@ -197,7 +238,7 @@ class MyFailingInterceptor < ::Gruf::Interceptors::ServerInterceptor
|
|
197
238
|
unless result.dont_hijack
|
198
239
|
# we'll assume this "dont_hijack" attribute exists on the message for this example
|
199
240
|
fail!(:internal, :hijacked, 'Hijack all the things!')
|
200
|
-
end
|
241
|
+
end
|
201
242
|
result
|
202
243
|
end
|
203
244
|
end
|
@@ -222,10 +263,10 @@ Gruf.configure do |c|
|
|
222
263
|
end
|
223
264
|
```
|
224
265
|
|
225
|
-
Interceptors each wrap the call and are run recursively within each other. This means that if you have
|
226
|
-
three interceptors - `Interceptor1`, `Interceptor2`, and `Interceptor3` - they will run in FIFO
|
227
|
-
(first in, first out) order. `Interceptor1` will run, yielding to `Interceptor2`,
|
228
|
-
which will then yield to `Interceptor3`, which will then yield to your service method call,
|
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,
|
229
270
|
ending the chain.
|
230
271
|
|
231
272
|
You can utilize the `insert_before` and `insert_after` methods to maintain order:
|
@@ -245,12 +286,12 @@ parameter.
|
|
245
286
|
|
246
287
|
## Instrumentation
|
247
288
|
|
248
|
-
gruf comes out of the box with a couple of instrumentation interceptors packed in:
|
249
|
-
output metadata timings and StatsD support.
|
289
|
+
gruf comes out of the box with a couple of instrumentation interceptors packed in:
|
290
|
+
output metadata timings and StatsD support.
|
250
291
|
|
251
292
|
### Output Metadata Timing
|
252
293
|
|
253
|
-
Enabled by default, this will push timings for _successful responses_ through the response output
|
294
|
+
Enabled by default, this will push timings for _successful responses_ through the response output
|
254
295
|
metadata back to the client.
|
255
296
|
|
256
297
|
### StatsD
|
@@ -271,7 +312,7 @@ This will measure counts and timings for each endpoint.
|
|
271
312
|
|
272
313
|
### Request Logging
|
273
314
|
|
274
|
-
Gruf 1.2+ comes built with request logging out of the box; you'll get Rails-style logs with your
|
315
|
+
Gruf 1.2+ comes built with request logging out of the box; you'll get Rails-style logs with your
|
275
316
|
gRPC calls:
|
276
317
|
|
277
318
|
```
|
@@ -282,7 +323,7 @@ I, [2017-07-14T09:51:03.299050 #70595] INFO -- : {"message":"[GRPC::Ok] (thing_
|
|
282
323
|
```
|
283
324
|
|
284
325
|
It supports formatters (including custom ones) that you can use to specify the formatting of the logging:
|
285
|
-
|
326
|
+
|
286
327
|
```ruby
|
287
328
|
Gruf.configure do |c|
|
288
329
|
c.interceptors.use(
|
@@ -301,26 +342,28 @@ It comes with a few more options as well:
|
|
301
342
|
| blacklist | An array of parameter key names to redact from logging, in path.to.key format | `[]` |
|
302
343
|
| redacted_string | The string to use for redacted parameters. | `REDACTED` |
|
303
344
|
|
304
|
-
It's important to maintain a safe blacklist should you decide to log parameters; gruf does no
|
305
|
-
parameter sanitization on its own. We also recommend blacklisting parameters that may contain
|
345
|
+
It's important to maintain a safe blacklist should you decide to log parameters; gruf does no
|
346
|
+
parameter sanitization on its own. We also recommend blacklisting parameters that may contain
|
306
347
|
very large values (such as binary or json data).
|
307
348
|
|
308
349
|
## Plugins
|
309
350
|
|
310
351
|
You can build your own hooks and middleware for gruf; here's a list of known open source gems for
|
311
352
|
gruf that you can use today:
|
312
|
-
|
353
|
+
|
313
354
|
* [gruf-zipkin](https://github.com/bigcommerce/gruf-zipkin) - Provides a [Zipkin](https://zipkin.io)
|
314
|
-
integration
|
315
|
-
* [gruf-circuit-breaker](https://github.com/bigcommerce/gruf-circuit-breaker) -
|
316
|
-
support for
|
317
|
-
* [gruf-profiler](https://github.com/bigcommerce/gruf-profiler) - Profiles and provides memory usage
|
318
|
-
reports for
|
355
|
+
integration
|
356
|
+
* [gruf-circuit-breaker](https://github.com/bigcommerce/gruf-circuit-breaker) - Circuit breaker
|
357
|
+
support for services
|
358
|
+
* [gruf-profiler](https://github.com/bigcommerce/gruf-profiler) - Profiles and provides memory usage
|
359
|
+
reports for clients and services
|
360
|
+
* [gruf-commander](https://github.com/bigcommerce/gruf-commander) - Request/command-style validation and
|
361
|
+
execution patterns for services
|
319
362
|
|
320
363
|
## Demo Rails App
|
321
364
|
|
322
|
-
There is a [demonstration Rails application here](https://github.com/bigcommerce/gruf-demo) you can
|
323
|
-
view and clone that shows how to integrate Gruf into an existing Rails application.
|
365
|
+
There is a [demonstration Rails application here](https://github.com/bigcommerce/gruf-demo) you can
|
366
|
+
view and clone that shows how to integrate Gruf into an existing Rails application.
|
324
367
|
|
325
368
|
## Roadmap
|
326
369
|
|
@@ -341,17 +384,17 @@ Using gruf and want to show your support? Let us know and we'll add your name he
|
|
341
384
|
|
342
385
|
## License
|
343
386
|
|
344
|
-
Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
387
|
+
Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
345
388
|
|
346
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
347
|
-
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
348
|
-
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
389
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
390
|
+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
391
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
349
392
|
persons to whom the Software is furnished to do so, subject to the following conditions:
|
350
393
|
|
351
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
394
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
352
395
|
Software.
|
353
396
|
|
354
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
355
|
-
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
356
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
397
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
398
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
399
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
357
400
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/gruf/client.rb
CHANGED
@@ -66,14 +66,15 @@ module Gruf
|
|
66
66
|
# @param [Hash] options A hash of options for the client
|
67
67
|
# @option options [String] :password The password for basic authentication for the service.
|
68
68
|
# @option options [String] :hostname The hostname of the service. Defaults to linkerd.
|
69
|
+
# @param [Hash] client_options A hash of options to pass to the gRPC client stub
|
69
70
|
#
|
70
|
-
def initialize(service:, options: {})
|
71
|
+
def initialize(service:, options: {}, client_options: {})
|
71
72
|
@base_klass = service
|
72
73
|
@service_klass = "#{base_klass}::Service".constantize
|
73
74
|
@opts = options || {}
|
74
75
|
@opts[:password] = options.fetch(:password, '').to_s
|
75
76
|
@opts[:hostname] = options.fetch(:hostname, Gruf.default_client_host)
|
76
|
-
client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials)
|
77
|
+
client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials, client_options)
|
77
78
|
super(client)
|
78
79
|
end
|
79
80
|
|
@@ -88,6 +89,7 @@ module Gruf
|
|
88
89
|
# @return [Gruf::Response] The response from the server
|
89
90
|
# @raise [Gruf::Client::Error|GRPC::BadStatus] If an error occurs, an exception will be raised according to the
|
90
91
|
# error type that was returned
|
92
|
+
#
|
91
93
|
def call(request_method, params = {}, metadata = {}, opts = {}, &block)
|
92
94
|
request_method = request_method.to_sym
|
93
95
|
req = streaming_request?(request_method) ? params : request_object(request_method, params)
|
@@ -108,6 +110,15 @@ module Gruf
|
|
108
110
|
raise
|
109
111
|
end
|
110
112
|
|
113
|
+
##
|
114
|
+
# Returns the currently set timeout on the client stub
|
115
|
+
#
|
116
|
+
# @return [Integer|NilClass]
|
117
|
+
#
|
118
|
+
def timeout
|
119
|
+
__getobj__.instance_variable_get(:@timeout)
|
120
|
+
end
|
121
|
+
|
111
122
|
private
|
112
123
|
|
113
124
|
##
|
data/lib/gruf/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gruf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shaun McCormick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -158,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
158
|
version: '0'
|
159
159
|
requirements: []
|
160
160
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.6.
|
161
|
+
rubygems_version: 2.6.14
|
162
162
|
signing_key:
|
163
163
|
specification_version: 4
|
164
164
|
summary: gRPC Ruby Framework
|