gruf 2.1.0 → 2.1.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 +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
|