gruf 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8db09af385df9c2a441b0bf6ece236e8d3a0735a
4
+ data.tar.gz: dff8c04b4439335743edb8c6cbd7e74d7cb64f43
5
+ SHA512:
6
+ metadata.gz: 040cfcf2678a142635796b35706dc1599e4b0364a4cc6a90fbc9628e02d3b273427452b3325d6e08988b53e80d2a08482879072c90927de16f697ad7f7937c3f
7
+ data.tar.gz: 3a67f98f29b8be1b9216a0c609e040308721afe822719d591cd74a82cb3d3c791b796d96eee750e096b2de7c837607377e01101b760d1fd4fb82dcc2e98ca904
@@ -0,0 +1,81 @@
1
+ Changelog for the gruf gem. This includes internal history before the gem was made.
2
+
3
+ h3. 1.0.0
4
+
5
+ - Bump gRPC to 1.4
6
+
7
+ h3. 0.14.2
8
+
9
+ - Added rubocop style-guide checks
10
+
11
+ h3. 0.14.1
12
+
13
+ - Updated license to MIT
14
+
15
+ h3. 0.14.0
16
+
17
+ - Send gRPC status 16 (Unauthenticated) instead of 7 (PermissionDenied) when authentication fails
18
+
19
+ h3. 0.13.0
20
+
21
+ - Move to gRPC 1.3.4
22
+
23
+ h4. 0.12.2
24
+
25
+ - Add outer_around hook for wrapping the entire call chain
26
+
27
+ h4. 0.12.1
28
+
29
+ - Add ability to specify a separate gRPC logger from the Gruf logger
30
+
31
+ h3. 0.12.0
32
+
33
+ - Add ability to run multiple around hooks
34
+ - Fix bug with error handling that caused error messages to repeat across streams
35
+
36
+ h3. 0.11.5
37
+
38
+ - Fix issue with around hook
39
+
40
+ h3. 0.11.4
41
+
42
+ - Add catchall rescue handler to capture uncaught exceptions and
43
+ raise a GRPC::Internal error.
44
+ - Add Gruf.backtrace_on_error configuration value. If set, Gruf
45
+ will call Service.set_debug_info with the exception backtrace
46
+ if an uncaught exception occurs.
47
+
48
+ h3. 0.11.3
49
+
50
+ - Pass the service instance into hooks for reference
51
+
52
+ h3. 0.11.2
53
+
54
+ - Ensure timer is measuring in milliseconds
55
+
56
+ h3. 0.11.1
57
+
58
+ - Fix issue with interceptor and call signature
59
+
60
+ h3. 0.11.0
61
+
62
+ - Add instrumentation layer and ability to register new instrumentors
63
+ - Add out-of-the-box statsd instrumentation support
64
+
65
+ h3. 0.10.0
66
+
67
+ - Rename Gruf::Endpoint to Gruf::Service
68
+ - Make services auto-mount to server upon declaration
69
+
70
+ h3. 0.9.2
71
+
72
+ - Support mount command on services to allow automatic setup on the server
73
+ - Cleanup and consolidate binstub to prevent need for custom binstub per-app
74
+
75
+ h3. 0.9.1
76
+
77
+ - Relax licensing to a clean BSD license
78
+
79
+ h3. 0.9.0
80
+
81
+ - Initial public release
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
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.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at splittingred@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
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]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
@@ -0,0 +1,312 @@
1
+ # gruf - gRPC Ruby Framework
2
+
3
+ [![Build Status](https://travis-ci.com/bigcommerce/gruf.svg?token=D3Cc4LCF9BgpUx4dpPpv&branch=master)](https://travis-ci.com/bigcommerce/gruf)
4
+
5
+ gruf is a Ruby framework that wraps the [gRPC Ruby library](https://github.com/grpc/grpc/tree/master/src/ruby) to
6
+ provide a more streamlined integration into Ruby and Ruby on Rails applications.
7
+
8
+ It provides an abstracted server and client for gRPC services, along with other tools to help get gRPC services in Ruby
9
+ up fast and efficiently at scale. Some of its features include:
10
+
11
+ * Abstracted server endpoints with before, around, outer around, and after hooks during an endpoint call
12
+ * Robust client error handling and metadata transport abilities
13
+ * Server authentication strategy support, with basic auth with multiple key support built in
14
+ * TLS support for client-server auth, though we recommend using [linkerd](https://linkerd.io/) instead
15
+ * Error data serialization in output metadata to allow fine-grained error handling in the transport while still
16
+ preserving gRPC BadStatus codes
17
+ * Server and client execution timings in responses
18
+
19
+ gruf currently has active support for gRPC 1.4.x. gruf is compatible and tested with with Ruby 2.2, 2.3, and 2.4. gruf
20
+ is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any Ruby framework (such as
21
+ [Grape](https://github.com/ruby-grape/grape), for instance).
22
+
23
+ ## Installation
24
+
25
+ ```ruby
26
+ gem 'gruf'
27
+ ```
28
+
29
+ Then in an initializer or before use:
30
+
31
+ ```ruby
32
+ require 'gruf'
33
+ ```
34
+
35
+ ### Client
36
+
37
+ From there, you can instantiate a client given a stub service (say on an SslCertificates proto with a GetSslCertificate call):
38
+
39
+ ```ruby
40
+ require 'gruf'
41
+
42
+ id = args[:id].to_i.presence || 1
43
+
44
+ begin
45
+ client = ::Gruf::Client.new(service: MyPackage::MyService)
46
+ response = client.call(:GetMyThing, id: id)
47
+ puts response.message.inspect
48
+ rescue Gruf::Client::Error => e
49
+ puts e.error.inspect
50
+ end
51
+ ```
52
+
53
+ Note this returns a response object. The response object can provide `trailing_metadata` as well as a `execution_time`.
54
+
55
+ ### Server
56
+
57
+ Add an initializer:
58
+
59
+ ```ruby
60
+ require 'gruf'
61
+
62
+ Gruf.configure do |c|
63
+ c.server_binding_url = 'grpc.service.com:9003'
64
+ end
65
+ ```
66
+
67
+ Next, setup some handlers based on your proto configurations in `/app/rpc/`. For example, for the Thing service, with a
68
+ GetThingReq/GetThingResp call based on this proto:
69
+
70
+ ```
71
+ syntax = "proto3";
72
+
73
+ package demo;
74
+
75
+ service Thing {
76
+ rpc GetThing(GetThingReq) returns (GetSslCertificateResp) { }
77
+ }
78
+
79
+ message ThingReq {
80
+ uint64 id = 1;
81
+ }
82
+
83
+ message ThingResp {
84
+ uint64 id = 1;
85
+ string name = 2;
86
+ }
87
+ ```
88
+
89
+ You'd have this handler in `/app/rpc/demo/thing_server.rb`
90
+
91
+ ```ruby
92
+ module Demo
93
+ class ThingServer < ::Demo::ThingService::Service
94
+ include Gruf::Service
95
+
96
+ ##
97
+ # @param [Demo::GetThingReq] req
98
+ # @param [GRPC::ActiveCall] call
99
+ # @return [Demo::GetThingResp]
100
+ #
101
+ def get_thing(req, call)
102
+ ssl = Thing.find(req.id)
103
+
104
+ Demo::Things::GetThingResp.new(
105
+ id: ssl.id
106
+ )
107
+ rescue
108
+ fail!(req, call, :not_found, :thing_not_found, "Failed to find Thing with ID: #{req.id}")
109
+ end
110
+ end
111
+ end
112
+ ```
113
+
114
+ Finally, you can start the server by running:
115
+
116
+ bundle exec gruf
117
+
118
+ ### Authentication
119
+
120
+ Authentication is done via a strategy pattern and are injectable via middleware. If any of the strategies return `true`,
121
+ it will proceed the request as successful. For example, to add basic auth, you can do:
122
+
123
+ ```ruby
124
+ Gruf::Authentication::Strategies.add(:basic, Gruf::Authentication::Basic)
125
+ ```
126
+
127
+ Options to the middleware libraries can be passed through the `authentication_options` configuration option.
128
+
129
+ To add a custom authentication pattern, your class must extend the `Gruf::Authentication::Base` class, and implement
130
+ the `valid?(call)` method. For example, this class allows everyone in:
131
+
132
+ ```
133
+ class NoAuth < Gruf::Authentication::Base
134
+ def valid?(_call)
135
+ true
136
+ end
137
+ end
138
+ ```
139
+
140
+ #### Basic Auth
141
+
142
+ gruf supports simple basic authentication with an array of accepted credentials:
143
+
144
+ ```ruby
145
+ Gruf.configure do |c|
146
+ c.authentication_options = {
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
+ Supporting an array of credentials allow for unique credentials per service, or for easy credential rotation with
161
+ zero downtime.
162
+
163
+ ### SSL Configuration
164
+
165
+ We don't recommend using TLS for gRPC, but instead using something like [linkerd](https://linkerd.io) for TLS
166
+ encryption between services. If you need it, however, this library supports TLS.
167
+
168
+ For the client, you'll need to point to the public certificate:
169
+
170
+ ```ruby
171
+ ::Gruf::Client.new(
172
+ service: Demo::ThingService,
173
+ ssl_certificate: 'x509 public certificate here',
174
+ # OR
175
+ ssl_certificate_file: '/path/to/my.crt'
176
+ )
177
+ ```
178
+
179
+ If you want to run a server you'll need both the CRT and the key file if you want to do credentialed auth:
180
+
181
+ ```ruby
182
+ Gruf.configure do |c|
183
+ c.use_ssl = true
184
+ c.ssl_crt_file = "#{Rails.root}/config/ssl/#{Rails.env}.crt"
185
+ c.ssl_key_file = "#{Rails.root}/config/ssl/#{Rails.env}.key"
186
+ end
187
+ ```
188
+
189
+ ## Hooks
190
+
191
+ gruf supports hooks that act as interceptors around the grpc server calls, allowing you to perform actions before,
192
+ after, and even around your server endpoints. This can be used to add tracing data, connection resets in the grpc thread
193
+ pool, further instrumentation, and other things.
194
+
195
+ Adding a hook is as simple as creating a class that extends `Gruf::Hooks::Base`, and implementing it via the registry.
196
+
197
+ ### Before
198
+
199
+ A before hook passes in the method call signature, request object, and `GRPC::ActiveCall` object:
200
+ ```ruby
201
+ class MyBeforeHook < Gruf::Hooks::Base
202
+ def before(call_signature, request, active_call)
203
+ # do my thing before the call. Calling `fail!` here will prevent the call from happening.
204
+ end
205
+ end
206
+ Gruf::Hooks::Registry.add(:my_before_hook, MyBeforeHook)
207
+ ```
208
+
209
+ ### After
210
+
211
+ An after hook passes in the response object, method call signature, request object, and `GRPC::ActiveCall` object:
212
+ ```ruby
213
+ class MyAfterHook < Gruf::Hooks::Base
214
+ def after(success, response, call_signature, request, active_call)
215
+ # You can modify the response object
216
+ end
217
+ end
218
+ Gruf::Hooks::Registry.add(:my_after_hook, MyAfterHook)
219
+ ```
220
+
221
+ ### Around
222
+
223
+ An around hook passes in the method call signature, request object, `GRPC::ActiveCall` object, and the block
224
+ being executed:
225
+ ```ruby
226
+ class MyAroundHook < Gruf::Hooks::Base
227
+ def around(call_signature, request, active_call, &block)
228
+ # do my thing here
229
+ resp = yield
230
+ # do my thing there
231
+ resp
232
+ end
233
+ end
234
+ Gruf::Hooks::Registry.add(:my_around_hook, MyAroundHook)
235
+ ```
236
+
237
+ Around hooks are a special case - because each needs to wrap the call, they are run recursively within each other.
238
+ This means that if you have three hooks - `Hook1`, `Hook2`, and `Hook3` - they will run in LIFO (last in, first out)
239
+ order. `Hook3` will run, calling `Hook2`, which will then call `Hook1`, ending the chain.
240
+
241
+ ### Outer Around
242
+
243
+ And finally, an "outer" around hook passes in the method call signature, request object, `GRPC::ActiveCall`
244
+ object, and the block being executed, and executes around the _entire_ call chain (before, around, request, after):
245
+
246
+ ```ruby
247
+ class MyOuterAroundHook < Gruf::Hooks::Base
248
+ def outer_around(call_signature, request, active_call, &block)
249
+ # do my thing here
250
+ resp = yield
251
+ # do my thing there
252
+ resp
253
+ end
254
+ end
255
+ Gruf::Hooks::Registry.add(:my_outer_around_hook, MyOuterAroundHook)
256
+ ```
257
+
258
+ Outer around hooks behave similarly in execution order to around hooks.
259
+
260
+ Note: It's important to note that the authentication step happens immediately before the first _before_ hook is called,
261
+ so don't perform any actions that you want behind authentication in outer around hooks, as they are not called with
262
+ authentication.
263
+
264
+ ## Instrumentation
265
+
266
+ gruf comes out of the box with a couple of instrumentors packed in: output metadata timings, and StatsD
267
+ support.
268
+
269
+ ### Output Metadata Timing
270
+
271
+ Enabled by default, this will push timings for _successful responses_ through the response output metadata back to the
272
+ client.
273
+
274
+ ### StatsD
275
+
276
+ The StatsD support is not enabled by default. To enable it, you'll want to do:
277
+
278
+ ```ruby
279
+ Gruf.configure do |c|
280
+ c.instrumentation_options = {
281
+ statsd: {
282
+ client: ::Statsd.new('my.statsd.host', 8125),
283
+ prefix: 'my_application_prefix.rpc'
284
+ }
285
+ }
286
+ end
287
+ Gruf::Instrumentation::Registry.add(:statsd, Gruf::Instrumentation::Statsd)
288
+ ```
289
+
290
+ This will measure counts and timings for each endpoint.
291
+
292
+ ### Custom Instrumentors
293
+
294
+ Similar to hooks, simply extend the `Gruf::Instrumentation::Base` class, and implement the `call` method. See the StatsD
295
+ instrumentor for an example.
296
+
297
+ ## License
298
+
299
+ Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
300
+
301
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
302
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
303
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
304
+ persons to whom the Software is furnished to do so, subject to the following conditions:
305
+
306
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
307
+ Software.
308
+
309
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
310
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
311
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
312
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.