gruf 2.2.2 → 2.3.0
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 +7 -1
- data/README.md +48 -3
- data/bin/gruf +2 -12
- data/gruf.gemspec +1 -0
- data/lib/gruf.rb +2 -0
- data/lib/gruf/cli/executor.rb +71 -0
- data/lib/gruf/controllers/base.rb +8 -7
- data/lib/gruf/controllers/request.rb +12 -5
- data/lib/gruf/controllers/service_binder.rb +8 -2
- data/lib/gruf/errors/debug_info.rb +1 -1
- data/lib/gruf/errors/helpers.rb +3 -0
- data/lib/gruf/interceptors/base.rb +1 -0
- data/lib/gruf/interceptors/client_interceptor.rb +99 -0
- data/lib/gruf/interceptors/timer.rb +5 -0
- data/lib/gruf/outbound/request_context.rb +69 -0
- data/lib/gruf/server.rb +11 -2
- data/lib/gruf/version.rb +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d13a8ed53bfc2a83d33c7ca8eed57d302019d9b7
|
4
|
+
data.tar.gz: c665d27586c8c446071275b1490c6814391e7f49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18b6a5bb4cc864ec8f9dd66428fd08843d71b27a5c61706f4d352e2554644b9e9062e37c8e165917c021cc1970560099920e8f7f3be0149f60b18fa35e86c02c
|
7
|
+
data.tar.gz: 6432ce2af8567422c3ee0dce084bac1f6100536421f4f93cfee554dd78384f989ac163247d81a52c3043123d06a4e841337198bb9e6a4cf2ce4dbdf36410cce2
|
data/CHANGELOG.md
CHANGED
@@ -2,9 +2,15 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
|
|
2
2
|
|
3
3
|
### Pending release
|
4
4
|
|
5
|
+
### 2.3.0
|
6
|
+
|
7
|
+
- Add Gruf::Interceptors::ClientInterceptor for intercepting outbound client calls
|
8
|
+
- Add command-line arguments to the gruf binstub
|
9
|
+
- Add ability to specify server hostname via CLI argument
|
10
|
+
|
5
11
|
### 2.2.2
|
6
12
|
|
7
|
-
-
|
13
|
+
- Add ignore_methods option for RequestLogging interceptor [#45]
|
8
14
|
|
9
15
|
### 2.2.1
|
10
16
|
|
data/README.md
CHANGED
@@ -72,6 +72,39 @@ end
|
|
72
72
|
|
73
73
|
Note this returns a response object. The response object can provide `trailing_metadata` as well as a `execution_time`.
|
74
74
|
|
75
|
+
### Client Interceptors
|
76
|
+
|
77
|
+
Gruf comes with an assistance class for client interceptors that you can use - or you can use the native gRPC core
|
78
|
+
interceptors. Either way, you pass them into the client_options when creating a client:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class MyInterceptor < Gruf::Interceptors::ClientInterceptor
|
82
|
+
def call(request_context:)
|
83
|
+
logger.info "Got method #{request_context.method}!"
|
84
|
+
yield
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
::Gruf::Client.new(
|
89
|
+
service: ::Demo::ThingService,
|
90
|
+
client_options: [
|
91
|
+
interceptors: [MyInterceptor.new]
|
92
|
+
])
|
93
|
+
```
|
94
|
+
|
95
|
+
The `interceptors` option in `client_options` can accept either a `GRPC::ClientInterceptor` class or a
|
96
|
+
`Gruf::Interceptors::ClientInterceptor`, since the latter just extends the former. The gruf client interceptors
|
97
|
+
take an optional alternative approach: rather than having separate methods for each request type, it provides a default
|
98
|
+
`call` method that passes in a `RequestContext` object, which has the following attributes:
|
99
|
+
|
100
|
+
* *type* - A Symbol of the type of request (`request_response`, `server_streamer`, etc)
|
101
|
+
* *requests* An enumerable of requests being sent. For unary requests, this is a single request in an array
|
102
|
+
* *call* - The `GRPC::ActiveCall` object
|
103
|
+
* *method* - The Method being called
|
104
|
+
* *metadata* - The hash of outgoing metadata
|
105
|
+
|
106
|
+
Note that you _must_ yield back the block when building a client interceptor, so that the call can be executed.
|
107
|
+
|
75
108
|
### Server
|
76
109
|
|
77
110
|
Add an initializer:
|
@@ -133,6 +166,21 @@ Finally, you can start the server by running:
|
|
133
166
|
bundle exec gruf
|
134
167
|
```
|
135
168
|
|
169
|
+
### Command-Line Options
|
170
|
+
|
171
|
+
Gruf comes baked in with a few command-line options for the binstub:
|
172
|
+
|
173
|
+
| Option | Description |
|
174
|
+
| ------ | ----------- |
|
175
|
+
| -h, --help | Displays the help message |
|
176
|
+
| -v, --version | Displays the gruf version |
|
177
|
+
| --host | Specify the server binding host |
|
178
|
+
| --suppress-default-interceptors | Do not use the default interceptors for the server |
|
179
|
+
| --backtrace-on-error | Push backtraces on exceptions to the error serializer |
|
180
|
+
|
181
|
+
These options will override whatever is passed in the Gruf configure block or
|
182
|
+
initializer.
|
183
|
+
|
136
184
|
### Basic Authentication
|
137
185
|
|
138
186
|
Gruf comes packaged in with a Basic Authentication interceptor. It takes in an array of supported
|
@@ -370,12 +418,9 @@ view and clone that shows how to integrate Gruf into an existing Rails applicati
|
|
370
418
|
|
371
419
|
### Gruf 3.0
|
372
420
|
|
373
|
-
* Utilize the new core Ruby interceptors in gRPC 1.7
|
374
|
-
* Support client interceptors
|
375
421
|
* Change configuration to an injectable object to ensure thread safety on chained server/client interactions
|
376
422
|
* Move all references to `Gruf.` configuration into injectable parameters
|
377
423
|
* Redo server configuration to be fully injectable
|
378
|
-
* Move client calls to their native method implementation
|
379
424
|
|
380
425
|
## Companies Using Gruf
|
381
426
|
|
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
|
data/gruf.gemspec
CHANGED
data/lib/gruf.rb
CHANGED
@@ -23,7 +23,9 @@ require_relative 'gruf/logging'
|
|
23
23
|
require_relative 'gruf/loggable'
|
24
24
|
require_relative 'gruf/configuration'
|
25
25
|
require_relative 'gruf/errors/helpers'
|
26
|
+
require_relative 'gruf/cli/executor'
|
26
27
|
require_relative 'gruf/controllers/base'
|
28
|
+
require_relative 'gruf/outbound/request_context'
|
27
29
|
require_relative 'gruf/interceptors/registry'
|
28
30
|
require_relative 'gruf/interceptors/base'
|
29
31
|
require_relative 'gruf/timer'
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
4
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
5
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
6
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
7
|
+
#
|
8
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
9
|
+
# Software.
|
10
|
+
#
|
11
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
12
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
13
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
14
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
15
|
+
#
|
16
|
+
require 'slop'
|
17
|
+
|
18
|
+
module Gruf
|
19
|
+
module Cli
|
20
|
+
##
|
21
|
+
# Handles execution of the gruf binstub, along with command-line arguments
|
22
|
+
#
|
23
|
+
class Executor
|
24
|
+
##
|
25
|
+
# @param [Hash|ARGV]
|
26
|
+
#
|
27
|
+
def initialize(args = ARGV)
|
28
|
+
@args = args
|
29
|
+
setup!
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Run the server
|
34
|
+
#
|
35
|
+
def run
|
36
|
+
server = Gruf::Server.new(Gruf.server_options)
|
37
|
+
Gruf.services.each { |s| server.add_service(s) }
|
38
|
+
server.start!
|
39
|
+
rescue StandardError => e
|
40
|
+
msg = "FATAL ERROR: #{e.message} #{e.backtrace.join("\n")}"
|
41
|
+
logger = Gruf.logger ? Gruf.logger : Logger.new(STDERR)
|
42
|
+
logger.fatal msg
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
##
|
48
|
+
# Setup options for CLI execution and configure Gruf based on inputs
|
49
|
+
#
|
50
|
+
def setup!
|
51
|
+
opts = Slop.parse(@args) do |o|
|
52
|
+
o.null '-h', '--help', 'Display help message' do
|
53
|
+
puts o
|
54
|
+
exit(0)
|
55
|
+
end
|
56
|
+
o.string '--host', 'Specify the binding url for the gRPC service'
|
57
|
+
o.bool '--suppress-default-interceptors', 'Do not use the default interceptors'
|
58
|
+
o.bool '--backtrace-on-error', 'Push backtraces on exceptions to the error serializer'
|
59
|
+
o.null '-v', '--version', 'print gruf version' do
|
60
|
+
puts Gruf::VERSION
|
61
|
+
exit(0)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Gruf.server_binding_url = opts[:host] if opts[:host]
|
66
|
+
Gruf.use_default_interceptors = false if opts.suppress_default_interceptors?
|
67
|
+
Gruf.backtrace_on_error = true if opts.backtrace_on_error?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -32,11 +32,11 @@ module Gruf
|
|
32
32
|
##
|
33
33
|
# Initialize the controller within the given request context
|
34
34
|
#
|
35
|
-
# @param [Symbol] method_key
|
36
|
-
# @param [GRPC::GenericService] service
|
37
|
-
# @param [GRPC::RpcDesc] rpc_desc
|
38
|
-
# @param [GRPC::ActiveCall] active_call
|
39
|
-
# @param [Google::Protobuf::MessageExts] message
|
35
|
+
# @param [Symbol] method_key The gRPC method that this controller relates to
|
36
|
+
# @param [GRPC::GenericService] service The gRPC service stub for this controller
|
37
|
+
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor for this service method
|
38
|
+
# @param [GRPC::ActiveCall] active_call The gRPC ActiveCall object
|
39
|
+
# @param [Google::Protobuf::MessageExts] message The incoming protobuf request message
|
40
40
|
#
|
41
41
|
def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
|
42
42
|
@request = Request.new(
|
@@ -53,7 +53,7 @@ module Gruf
|
|
53
53
|
##
|
54
54
|
# Bind the controller to the given service and add it to the service registry
|
55
55
|
#
|
56
|
-
# @param [GRPC::GenericService] service
|
56
|
+
# @param [GRPC::GenericService] service The name of the service to bind this controller to
|
57
57
|
#
|
58
58
|
def self.bind(service)
|
59
59
|
Gruf.services << service.name.constantize
|
@@ -63,7 +63,8 @@ module Gruf
|
|
63
63
|
##
|
64
64
|
# Call a method on this controller
|
65
65
|
#
|
66
|
-
# @param [Symbol] method_key
|
66
|
+
# @param [Symbol] method_key The name of the gRPC service method being called as a Symbol
|
67
|
+
# @param [block] &block The passed block for executing the method
|
67
68
|
#
|
68
69
|
def call(method_key, &block)
|
69
70
|
Interceptors::Context.new(@interceptors).intercept! do
|
@@ -33,11 +33,16 @@ module Gruf
|
|
33
33
|
delegate :metadata, to: :active_call
|
34
34
|
delegate :messages, :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :type
|
35
35
|
|
36
|
+
##
|
37
|
+
# Abstract representation of a gRPC request type
|
38
|
+
#
|
36
39
|
class Type
|
37
40
|
delegate :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :@rpc_desc
|
38
41
|
|
39
42
|
##
|
40
|
-
#
|
43
|
+
# Initialize a new request type object
|
44
|
+
#
|
45
|
+
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor for the request type
|
41
46
|
#
|
42
47
|
def initialize(rpc_desc)
|
43
48
|
@rpc_desc = rpc_desc
|
@@ -45,6 +50,8 @@ module Gruf
|
|
45
50
|
end
|
46
51
|
|
47
52
|
##
|
53
|
+
# Initialize an inbound controller request object
|
54
|
+
#
|
48
55
|
# @param [Symbol] method_key The method symbol of the RPC method being executed
|
49
56
|
# @param [Class] service The class of the service being executed against
|
50
57
|
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor of the call
|
@@ -64,21 +71,21 @@ module Gruf
|
|
64
71
|
# Returns the service name as a translated name separated by periods. Strips
|
65
72
|
# the superfluous "Service" suffix from the name
|
66
73
|
#
|
67
|
-
# @return [String]
|
74
|
+
# @return [String] The mapped service key
|
68
75
|
#
|
69
76
|
def service_key
|
70
77
|
@service.name.underscore.tr('/', '.').gsub('.service', '')
|
71
78
|
end
|
72
79
|
|
73
80
|
##
|
74
|
-
# @return [Class]
|
81
|
+
# @return [Class] The class of the response message
|
75
82
|
#
|
76
83
|
def response_class
|
77
84
|
@rpc_desc.output
|
78
85
|
end
|
79
86
|
|
80
87
|
##
|
81
|
-
# @return [Class]
|
88
|
+
# @return [Class] The class of the request message
|
82
89
|
#
|
83
90
|
def request_class
|
84
91
|
@rpc_desc.input
|
@@ -96,7 +103,7 @@ module Gruf
|
|
96
103
|
##
|
97
104
|
# Return all messages for this request, properly handling different request types
|
98
105
|
#
|
99
|
-
# @return Enumerable<Object>
|
106
|
+
# @return Enumerable<Object> All messages for this request
|
100
107
|
#
|
101
108
|
def messages
|
102
109
|
if client_streamer?
|
@@ -25,14 +25,18 @@ module Gruf
|
|
25
25
|
class BoundDesc < SimpleDelegator; end
|
26
26
|
|
27
27
|
##
|
28
|
-
#
|
28
|
+
# Initialize a service binder instance with the given service
|
29
|
+
#
|
30
|
+
# @param [GRPC::GenericService] service The gRPC service stub to bind
|
29
31
|
#
|
30
32
|
def initialize(service)
|
31
33
|
@service = service
|
32
34
|
end
|
33
35
|
|
34
36
|
##
|
35
|
-
#
|
37
|
+
# Bind all methods on the service to the passed controller
|
38
|
+
#
|
39
|
+
# @param [Gruf::Controllers::Base] controller
|
36
40
|
#
|
37
41
|
def bind!(controller)
|
38
42
|
rpc_methods.each { |name, desc| bind_method(controller, name, desc) }
|
@@ -41,6 +45,8 @@ module Gruf
|
|
41
45
|
private
|
42
46
|
|
43
47
|
##
|
48
|
+
# Bind the grpc methods to the service, allowing for server interception and execution control
|
49
|
+
#
|
44
50
|
# @param [Gruf::Controllers::Base] controller
|
45
51
|
# @param [Symbol] method_name
|
46
52
|
# @param [BoundDesc] desc
|
data/lib/gruf/errors/helpers.rb
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
4
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
5
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
6
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
7
|
+
#
|
8
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
9
|
+
# Software.
|
10
|
+
#
|
11
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
12
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
13
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
14
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
15
|
+
#
|
16
|
+
module Gruf
|
17
|
+
module Interceptors
|
18
|
+
##
|
19
|
+
# Intercepts outbound client requests to provide a unified interface and request context
|
20
|
+
#
|
21
|
+
class ClientInterceptor < GRPC::ClientInterceptor
|
22
|
+
include Gruf::Loggable
|
23
|
+
|
24
|
+
##
|
25
|
+
# Handles interception of outbound calls. Implement this in your derivative interceptor implementation.
|
26
|
+
#
|
27
|
+
# @param [Gruf::Outbound::RequestContext] request_context The context of the outbound request
|
28
|
+
# @return [Object] This method must return the response from the yielded block
|
29
|
+
#
|
30
|
+
def call(request_context:)
|
31
|
+
logger.debug "Logging client interceptor for request: #{request_context.method}"
|
32
|
+
yield
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Call the interceptor from the request_response call
|
37
|
+
#
|
38
|
+
# @param [Object] request The request being sent
|
39
|
+
# @param [GRPC::ActiveCall] call The GRPC ActiveCall object
|
40
|
+
# @param [Method] method The method being called
|
41
|
+
# @param [Hash] metadata A hash of outgoing metadata
|
42
|
+
# @return [Object] The response message
|
43
|
+
#
|
44
|
+
def request_response(request: nil, call: nil, method: nil, metadata: nil)
|
45
|
+
rc = Gruf::Outbound::RequestContext.new(type: :request_response, requests: [request], call: call, method: method, metadata: metadata)
|
46
|
+
call(request_context: rc) do
|
47
|
+
yield
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Call the interceptor from the client_streamer call
|
53
|
+
#
|
54
|
+
# @param [Enumerable] requests An enumerable of requests being sent
|
55
|
+
# @param [GRPC::ActiveCall] call The GRPC ActiveCall object
|
56
|
+
# @param [Method] method The method being called
|
57
|
+
# @param [Hash] metadata A hash of outgoing metadata
|
58
|
+
# @return [Object] The response message
|
59
|
+
#
|
60
|
+
def client_streamer(requests: nil, call: nil, method: nil, metadata: nil)
|
61
|
+
rc = Gruf::Outbound::RequestContext.new(type: :client_streamer, requests: requests, call: call, method: method, metadata: metadata)
|
62
|
+
call(request_context: rc) do
|
63
|
+
yield
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Call the interceptor from the server_streamer call
|
69
|
+
#
|
70
|
+
# @param [Object] request The request being sent
|
71
|
+
# @param [GRPC::ActiveCall] call The GRPC ActiveCall object
|
72
|
+
# @param [Method] method The method being called
|
73
|
+
# @param [Hash] metadata A hash of outgoing metadata
|
74
|
+
# @return [Object] The response message
|
75
|
+
#
|
76
|
+
def server_streamer(request: nil, call: nil, method: nil, metadata: nil)
|
77
|
+
rc = Gruf::Outbound::RequestContext.new(type: :server_streamer, requests: [request], call: call, method: method, metadata: metadata)
|
78
|
+
call(request_context: rc) do
|
79
|
+
yield
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Call the interceptor from the bidi_streamer call
|
85
|
+
#
|
86
|
+
# @param [Enumerable] requests An enumerable of requests being sent
|
87
|
+
# @param [GRPC::ActiveCall] call The GRPC ActiveCall object
|
88
|
+
# @param [Method] method The method being called
|
89
|
+
# @param [Hash] metadata A hash of outgoing metadata
|
90
|
+
#
|
91
|
+
def bidi_streamer(requests: nil, call: nil, method: nil, metadata: nil)
|
92
|
+
rc = Gruf::Outbound::RequestContext.new(type: :bidi_streamer, requests: requests, call: call, method: method, metadata: metadata)
|
93
|
+
call(request_context: rc) do
|
94
|
+
yield
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -26,6 +26,11 @@ module Gruf
|
|
26
26
|
attr_reader :message
|
27
27
|
attr_reader :elapsed
|
28
28
|
|
29
|
+
##
|
30
|
+
# @param [Object] message The protobuf message
|
31
|
+
# @param [Float] elapsed The elapsed time of the request
|
32
|
+
# @param [Boolean] successful If the request was successful
|
33
|
+
#
|
29
34
|
def initialize(message, elapsed, successful)
|
30
35
|
@message = message
|
31
36
|
@elapsed = elapsed.to_f
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
4
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
5
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
6
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
7
|
+
#
|
8
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
9
|
+
# Software.
|
10
|
+
#
|
11
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
12
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
13
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
14
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
15
|
+
#
|
16
|
+
module Gruf
|
17
|
+
module Outbound
|
18
|
+
##
|
19
|
+
# Encapsulates the context of an outbound client request
|
20
|
+
#
|
21
|
+
class RequestContext
|
22
|
+
# @var [Symbol]
|
23
|
+
attr_reader :type
|
24
|
+
# @var [Enumerable] requests
|
25
|
+
attr_reader :requests
|
26
|
+
# @var [GRPC::ActiveCall]
|
27
|
+
attr_reader :call
|
28
|
+
# @var [Method] method
|
29
|
+
attr_reader :method
|
30
|
+
# @var [Hash] metadata
|
31
|
+
attr_reader :metadata
|
32
|
+
|
33
|
+
##
|
34
|
+
# Initialize the new request context
|
35
|
+
#
|
36
|
+
# @param [Symbol] type The type of request
|
37
|
+
# @param [Enumerable] requests An enumerable of requests being sent
|
38
|
+
# @param [GRPC::ActiveCall] call The GRPC ActiveCall object
|
39
|
+
# @param [Method] method The method being called
|
40
|
+
# @param [Hash] metadata A hash of outgoing metadata
|
41
|
+
#
|
42
|
+
def initialize(type:, requests:, call:, method:, metadata:)
|
43
|
+
@type = type
|
44
|
+
@requests = requests
|
45
|
+
@call = call
|
46
|
+
@method = method
|
47
|
+
@metadata = metadata
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Return the name of the method being called, e.g. GetThing
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
#
|
55
|
+
def method_name
|
56
|
+
@method.to_s.split('/').last
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Return the proper routing key for the request
|
61
|
+
#
|
62
|
+
# @return [String]
|
63
|
+
#
|
64
|
+
def route_key
|
65
|
+
@method[1..-1].underscore.tr('/', '.')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/gruf/server.rb
CHANGED
@@ -43,6 +43,7 @@ module Gruf
|
|
43
43
|
@stop_server_cv = ConditionVariable.new
|
44
44
|
@stop_server_mu = Monitor.new
|
45
45
|
@server_mu = Monitor.new
|
46
|
+
@hostname = options.fetch(:hostname, Gruf.server_binding_url)
|
46
47
|
setup
|
47
48
|
end
|
48
49
|
|
@@ -53,7 +54,7 @@ module Gruf
|
|
53
54
|
@server_mu.synchronize do
|
54
55
|
@server ||= begin
|
55
56
|
server = GRPC::RpcServer.new(options)
|
56
|
-
@port = server.add_http2_port(
|
57
|
+
@port = server.add_http2_port(@hostname, ssl_credentials)
|
57
58
|
@services.each { |s| server.handle(s) }
|
58
59
|
server
|
59
60
|
end
|
@@ -68,7 +69,7 @@ module Gruf
|
|
68
69
|
update_proc_title(:starting)
|
69
70
|
|
70
71
|
server_thread = Thread.new do
|
71
|
-
logger.info {
|
72
|
+
logger.info { "Starting gruf server at #{@hostname}..." }
|
72
73
|
server.run
|
73
74
|
end
|
74
75
|
|
@@ -94,6 +95,8 @@ module Gruf
|
|
94
95
|
# :nocov:
|
95
96
|
|
96
97
|
##
|
98
|
+
# Add a gRPC service stub to be served by gruf
|
99
|
+
#
|
97
100
|
# @param [Class] klass
|
98
101
|
# @raise [ServerAlreadyStartedError] if the server is already started
|
99
102
|
#
|
@@ -115,6 +118,8 @@ module Gruf
|
|
115
118
|
end
|
116
119
|
|
117
120
|
##
|
121
|
+
# Insert an interceptor before another in the currently registered order of execution
|
122
|
+
#
|
118
123
|
# @param [Class] before_class The interceptor that you want to add the new interceptor before
|
119
124
|
# @param [Class] interceptor_class The Interceptor to add to the registry
|
120
125
|
# @param [Hash] options A hash of options for the interceptor
|
@@ -125,6 +130,8 @@ module Gruf
|
|
125
130
|
end
|
126
131
|
|
127
132
|
##
|
133
|
+
# Insert an interceptor after another in the currently registered order of execution
|
134
|
+
#
|
128
135
|
# @param [Class] after_class The interceptor that you want to add the new interceptor after
|
129
136
|
# @param [Class] interceptor_class The Interceptor to add to the registry
|
130
137
|
# @param [Hash] options A hash of options for the interceptor
|
@@ -146,6 +153,8 @@ module Gruf
|
|
146
153
|
##
|
147
154
|
# Remove an interceptor from the server
|
148
155
|
#
|
156
|
+
# @param [Class] klass
|
157
|
+
#
|
149
158
|
def remove_interceptor(klass)
|
150
159
|
raise ServerAlreadyStartedError if @started
|
151
160
|
@interceptors.remove(klass)
|
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.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shaun McCormick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: slop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '4.6'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '4.6'
|
97
111
|
description: gRPC Ruby Framework
|
98
112
|
email:
|
99
113
|
- splittingred@gmail.com
|
@@ -108,6 +122,7 @@ files:
|
|
108
122
|
- bin/gruf
|
109
123
|
- gruf.gemspec
|
110
124
|
- lib/gruf.rb
|
125
|
+
- lib/gruf/cli/executor.rb
|
111
126
|
- lib/gruf/client.rb
|
112
127
|
- lib/gruf/configuration.rb
|
113
128
|
- lib/gruf/controllers/base.rb
|
@@ -120,6 +135,7 @@ files:
|
|
120
135
|
- lib/gruf/interceptors/active_record/connection_reset.rb
|
121
136
|
- lib/gruf/interceptors/authentication/basic.rb
|
122
137
|
- lib/gruf/interceptors/base.rb
|
138
|
+
- lib/gruf/interceptors/client_interceptor.rb
|
123
139
|
- lib/gruf/interceptors/context.rb
|
124
140
|
- lib/gruf/interceptors/instrumentation/output_metadata_timer.rb
|
125
141
|
- lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb
|
@@ -132,6 +148,7 @@ files:
|
|
132
148
|
- lib/gruf/interceptors/timer.rb
|
133
149
|
- lib/gruf/loggable.rb
|
134
150
|
- lib/gruf/logging.rb
|
151
|
+
- lib/gruf/outbound/request_context.rb
|
135
152
|
- lib/gruf/response.rb
|
136
153
|
- lib/gruf/serializers/errors/base.rb
|
137
154
|
- lib/gruf/serializers/errors/json.rb
|