istox_gruf 2.7.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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +246 -0
  3. data/CODE_OF_CONDUCT.md +46 -0
  4. data/README.md +544 -0
  5. data/bin/gruf +29 -0
  6. data/lib/gruf.rb +50 -0
  7. data/lib/gruf/cli/executor.rb +99 -0
  8. data/lib/gruf/client.rb +217 -0
  9. data/lib/gruf/client/error.rb +66 -0
  10. data/lib/gruf/client/error_factory.rb +105 -0
  11. data/lib/gruf/configuration.rb +137 -0
  12. data/lib/gruf/controllers/base.rb +102 -0
  13. data/lib/gruf/controllers/request.rb +121 -0
  14. data/lib/gruf/controllers/service_binder.rb +117 -0
  15. data/lib/gruf/error.rb +230 -0
  16. data/lib/gruf/errors/debug_info.rb +56 -0
  17. data/lib/gruf/errors/field.rb +56 -0
  18. data/lib/gruf/errors/helpers.rb +44 -0
  19. data/lib/gruf/hooks/base.rb +34 -0
  20. data/lib/gruf/hooks/executor.rb +47 -0
  21. data/lib/gruf/hooks/registry.rb +159 -0
  22. data/lib/gruf/instrumentable_grpc_server.rb +64 -0
  23. data/lib/gruf/integrations/rails/railtie.rb +10 -0
  24. data/lib/gruf/interceptors/active_record/connection_reset.rb +48 -0
  25. data/lib/gruf/interceptors/authentication/basic.rb +87 -0
  26. data/lib/gruf/interceptors/base.rb +53 -0
  27. data/lib/gruf/interceptors/client_interceptor.rb +125 -0
  28. data/lib/gruf/interceptors/context.rb +56 -0
  29. data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +61 -0
  30. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +41 -0
  31. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +43 -0
  32. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +48 -0
  33. data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +225 -0
  34. data/lib/gruf/interceptors/instrumentation/statsd.rb +82 -0
  35. data/lib/gruf/interceptors/registry.rb +161 -0
  36. data/lib/gruf/interceptors/server_interceptor.rb +34 -0
  37. data/lib/gruf/interceptors/timer.rb +85 -0
  38. data/lib/gruf/loggable.rb +30 -0
  39. data/lib/gruf/logging.rb +53 -0
  40. data/lib/gruf/outbound/request_context.rb +71 -0
  41. data/lib/gruf/response.rb +71 -0
  42. data/lib/gruf/serializers/errors/base.rb +57 -0
  43. data/lib/gruf/serializers/errors/json.rb +43 -0
  44. data/lib/gruf/server.rb +294 -0
  45. data/lib/gruf/synchronized_client.rb +97 -0
  46. data/lib/gruf/timer.rb +78 -0
  47. data/lib/gruf/version.rb +20 -0
  48. metadata +203 -0
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Outbound
20
+ ##
21
+ # Encapsulates the context of an outbound client request
22
+ #
23
+ class RequestContext
24
+ # @var [Symbol]
25
+ attr_reader :type
26
+ # @var [Enumerable] requests
27
+ attr_reader :requests
28
+ # @var [GRPC::ActiveCall]
29
+ attr_reader :call
30
+ # @var [Method] method
31
+ attr_reader :method
32
+ # @var [Hash] metadata
33
+ attr_reader :metadata
34
+
35
+ ##
36
+ # Initialize the new request context
37
+ #
38
+ # @param [Symbol] type The type of request
39
+ # @param [Enumerable] requests An enumerable of requests being sent
40
+ # @param [GRPC::ActiveCall] call The GRPC ActiveCall object
41
+ # @param [Method] method The method being called
42
+ # @param [Hash] metadata A hash of outgoing metadata
43
+ #
44
+ def initialize(type:, requests:, call:, method:, metadata:)
45
+ @type = type
46
+ @requests = requests
47
+ @call = call
48
+ @method = method
49
+ @metadata = metadata
50
+ end
51
+
52
+ ##
53
+ # Return the name of the method being called, e.g. GetThing
54
+ #
55
+ # @return [String]
56
+ #
57
+ def method_name
58
+ @method.to_s.split('/').last
59
+ end
60
+
61
+ ##
62
+ # Return the proper routing key for the request
63
+ #
64
+ # @return [String]
65
+ #
66
+ def route_key
67
+ @method[1..-1].underscore.tr('/', '.')
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ ##
20
+ # Wraps the active call operation to provide metadata and timing around the request
21
+ #
22
+ class Response
23
+ # @return [GRPC::ActiveCall::Operation] The operation that was executed for the given request
24
+ attr_reader :operation
25
+ # @return [Hash] The metadata that was attached to the operation
26
+ attr_reader :metadata
27
+ # @return [Hash] The trailing metadata that the service returned
28
+ attr_reader :trailing_metadata
29
+ # @return [Time] The set deadline on the call
30
+ attr_reader :deadline
31
+ # @return [Boolean] Whether or not the operation was cancelled
32
+ attr_reader :cancelled
33
+ # @return [Float] The time that the request took to execute
34
+ attr_reader :execution_time
35
+
36
+ ##
37
+ # Initialize a response object with the given gRPC operation
38
+ #
39
+ # @param [GRPC::ActiveCall::Operation] operation The given operation for the current call
40
+ # @param [StdClass] message
41
+ # @param [Float] execution_time The amount of time that the response took to occur
42
+ #
43
+ def initialize(operation:, message:, execution_time: nil)
44
+ @operation = operation
45
+ @message = message
46
+ @metadata = operation.metadata
47
+ @trailing_metadata = operation.trailing_metadata
48
+ @deadline = operation.deadline
49
+ @cancelled = operation.cancelled?
50
+ @execution_time = execution_time || 0.0
51
+ end
52
+
53
+ ##
54
+ # Return the message returned by the request
55
+ #
56
+ # @return [Object] The protobuf response message
57
+ #
58
+ def message
59
+ @message ||= @operation.execute
60
+ end
61
+
62
+ ##
63
+ # Return execution time of the call internally on the server in ms
64
+ #
65
+ # @return [Float] The execution time of the response
66
+ #
67
+ def internal_execution_time
68
+ trailing_metadata['timer'].to_f
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Serializers
20
+ module Errors
21
+ ##
22
+ # Base class for serialization of errors for transport across the grpc protocol
23
+ #
24
+ class Base
25
+ # @return [Gruf::Error|String] The error being serialized
26
+ attr_reader :error
27
+
28
+ ##
29
+ # @param [Gruf::Error|String] err The error to serialize
30
+ #
31
+ def initialize(err)
32
+ @error = err
33
+ end
34
+
35
+ ##
36
+ # Must be implemented in a derived class. This method should serialize the error into a transportable String
37
+ # that can be pushed into GRPC metadata across the wire.
38
+ #
39
+ # @return [String] The serialized error
40
+ #
41
+ def serialize
42
+ raise NotImplementedError
43
+ end
44
+
45
+ ##
46
+ # Must be implemented in a derived class. This method should deserialize the error object that is transported
47
+ # over the gRPC trailing metadata payload.
48
+ #
49
+ # @return [Object|Hash] The deserialized error object
50
+ #
51
+ def deserialize
52
+ raise NotImplementedError
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ require 'json'
19
+
20
+ module Gruf
21
+ module Serializers
22
+ module Errors
23
+ ##
24
+ # Serializes the error via JSON for transport
25
+ #
26
+ class Json < Base
27
+ ##
28
+ # @return [String] The serialized JSON string
29
+ #
30
+ def serialize
31
+ @error.to_h.to_json
32
+ end
33
+
34
+ ##
35
+ # @return [Hash] A hash deserialized from the inputted JSON
36
+ #
37
+ def deserialize
38
+ JSON.parse(@error)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,294 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ ##
20
+ # Represents a gRPC server. Automatically loads and augments gRPC handlers and services
21
+ # based on configuration values.
22
+ #
23
+ class Server
24
+ class ServerAlreadyStartedError < StandardError; end
25
+
26
+ include Gruf::Loggable
27
+
28
+ # @return [Integer] The port the server is bound to
29
+ attr_reader :port
30
+ # @return [Hash] Hash of options passed into the server
31
+ attr_reader :options
32
+
33
+ ##
34
+ # Initialize the server and load and setup the services
35
+ #
36
+ # @param [Hash] opts
37
+ #
38
+ def initialize(opts = {})
39
+ init(opts)
40
+ end
41
+
42
+ def init(opts = {})
43
+ @options = opts || {}
44
+ @interceptors = opts.fetch(:interceptor_registry, Gruf.interceptors)
45
+ @interceptors = Gruf::Interceptors::Registry.new unless @interceptors.is_a?(Gruf::Interceptors::Registry)
46
+ @services = []
47
+ @started = false
48
+ @stop_server = false
49
+ @stop_server_cv = ConditionVariable.new
50
+ @stop_server_mu = Monitor.new
51
+ @server_mu = Monitor.new
52
+ @hostname = opts.fetch(:hostname, Gruf.server_binding_url)
53
+ @event_listener_proc = opts.fetch(:event_listener_proc, Gruf.event_listener_proc)
54
+ setup
55
+ end
56
+
57
+ ##
58
+ # @return [GRPC::RpcServer] The GRPC server running
59
+ #
60
+ def server
61
+ @server_mu.synchronize do
62
+ @server ||= begin
63
+ # For backward compatibility, we allow these options to be passed directly
64
+ # in the Gruf::Server options, or via Gruf.rpc_server_options.
65
+ server_options = {
66
+ pool_size: options.fetch(:pool_size, Gruf.rpc_server_options[:pool_size]),
67
+ max_waiting_requests: options.fetch(:max_waiting_requests, Gruf.rpc_server_options[:max_waiting_requests]),
68
+ poll_period: options.fetch(:poll_period, Gruf.rpc_server_options[:poll_period]),
69
+ pool_keep_alive: options.fetch(:pool_keep_alive, Gruf.rpc_server_options[:pool_keep_alive]),
70
+ connect_md_proc: options.fetch(:connect_md_proc, Gruf.rpc_server_options[:connect_md_proc]),
71
+ server_args: options.fetch(:server_args, Gruf.rpc_server_options[:server_args])
72
+ }
73
+
74
+ server = if @event_listener_proc
75
+ server_options[:event_listener_proc] = @event_listener_proc
76
+ Gruf::InstrumentableGrpcServer.new(server_options)
77
+ else
78
+ GRPC::RpcServer.new(server_options)
79
+ end
80
+
81
+ @port = server.add_http2_port(@hostname, ssl_credentials)
82
+ @services.each { |s| server.handle(s) }
83
+ server
84
+ end
85
+ end
86
+ end
87
+
88
+ ##
89
+ # Start the gRPC server
90
+ #
91
+ # :nocov:
92
+ def start!
93
+ update_proc_title(:starting)
94
+
95
+ server_thread = Thread.new do
96
+ logger.info { "Starting gruf server at #{@hostname}..." }
97
+ server.run
98
+ end
99
+
100
+ stop_server_thread = Thread.new do
101
+ loop do
102
+ break if @stop_server
103
+
104
+ @stop_server_mu.synchronize { @stop_server_cv.wait(@stop_server_mu, 2) }
105
+ end
106
+ logger.info { 'Shutting down...' }
107
+ server.stop
108
+ end
109
+
110
+ server.wait_till_running
111
+ @started = true
112
+ update_proc_title(:serving)
113
+ stop_server_thread.join
114
+ server_thread.join
115
+ @started = false
116
+
117
+ update_proc_title(:stopped)
118
+ logger.info { 'Goodbye!' }
119
+ end
120
+
121
+ def init_restart
122
+ logger.info { 'Restarting gruf...' }
123
+ @restart = true
124
+ @stop_server = true
125
+ end
126
+
127
+ def required_restart
128
+ @restart
129
+ end
130
+
131
+ # :nocov:
132
+
133
+ ##
134
+ # Add a gRPC service stub to be served by gruf
135
+ #
136
+ # @param [Class] klass
137
+ # @raise [ServerAlreadyStartedError] if the server is already started
138
+ #
139
+ def add_service(klass)
140
+ raise ServerAlreadyStartedError if @started
141
+
142
+ @services << klass unless @services.include?(klass)
143
+ end
144
+
145
+ ##
146
+ # Add an interceptor to the server
147
+ #
148
+ # @param [Class] klass The Interceptor to add to the registry
149
+ # @param [Hash] opts A hash of options for the interceptor
150
+ # @raise [ServerAlreadyStartedError] if the server is already started
151
+ #
152
+ def add_interceptor(klass, opts = {})
153
+ raise ServerAlreadyStartedError if @started
154
+
155
+ @interceptors.use(klass, opts)
156
+ end
157
+
158
+ ##
159
+ # Insert an interceptor before another in the currently registered order of execution
160
+ #
161
+ # @param [Class] before_class The interceptor that you want to add the new interceptor before
162
+ # @param [Class] interceptor_class The Interceptor to add to the registry
163
+ # @param [Hash] opts A hash of options for the interceptor
164
+ #
165
+ def insert_interceptor_before(before_class, interceptor_class, opts = {})
166
+ raise ServerAlreadyStartedError if @started
167
+
168
+ @interceptors.insert_before(before_class, interceptor_class, opts)
169
+ end
170
+
171
+ ##
172
+ # Insert an interceptor after another in the currently registered order of execution
173
+ #
174
+ # @param [Class] after_class The interceptor that you want to add the new interceptor after
175
+ # @param [Class] interceptor_class The Interceptor to add to the registry
176
+ # @param [Hash] opts A hash of options for the interceptor
177
+ #
178
+ def insert_interceptor_after(after_class, interceptor_class, opts = {})
179
+ raise ServerAlreadyStartedError if @started
180
+
181
+ @interceptors.insert_after(after_class, interceptor_class, opts)
182
+ end
183
+
184
+ ##
185
+ # Return the current list of added interceptor classes
186
+ #
187
+ # @return [Array<Class>]
188
+ #
189
+ def list_interceptors
190
+ @interceptors.list
191
+ end
192
+
193
+ ##
194
+ # Remove an interceptor from the server
195
+ #
196
+ # @param [Class] klass
197
+ #
198
+ def remove_interceptor(klass)
199
+ raise ServerAlreadyStartedError if @started
200
+
201
+ @interceptors.remove(klass)
202
+ end
203
+
204
+ ##
205
+ # Clear the interceptor registry of interceptors
206
+ #
207
+ def clear_interceptors
208
+ raise ServerAlreadyStartedError if @started
209
+
210
+ @interceptors.clear
211
+ end
212
+
213
+ private
214
+
215
+ ##
216
+ # Setup server
217
+ #
218
+ # :nocov:
219
+ def setup
220
+ setup_signal_handlers
221
+ load_controllers
222
+ end
223
+ # :nocov:
224
+
225
+ ##
226
+ # Register signal handlers
227
+ #
228
+ # :nocov:
229
+ def setup_signal_handlers
230
+ Signal.trap('INT') do
231
+ @stop_server = true
232
+ @stop_server_cv.broadcast
233
+ end
234
+
235
+ Signal.trap('TERM') do
236
+ @stop_server = true
237
+ @stop_server_cv.broadcast
238
+ end
239
+ end
240
+ # :nocov:
241
+
242
+ ##
243
+ # Auto-load all gRPC handlers
244
+ #
245
+ # :nocov:
246
+ def load_controllers
247
+ return unless File.directory?(controllers_path)
248
+
249
+ path = File.realpath(controllers_path)
250
+ $LOAD_PATH.unshift(path)
251
+ Dir["#{path}/**/*.rb"].each do |f|
252
+ next if f.include?('_pb') # exclude if people include proto generated files in app/rpc
253
+
254
+ logger.info "- Loading gRPC service file: #{f}"
255
+ load File.realpath(f)
256
+ end
257
+ end
258
+ # :nocov:
259
+
260
+ ##
261
+ # @param [String]
262
+ #
263
+ def controllers_path
264
+ options.fetch(:controllers_path, Gruf.controllers_path)
265
+ end
266
+
267
+ ##
268
+ # Load the SSL/TLS credentials for this server
269
+ #
270
+ # @return [GRPC::Core::ServerCredentials|Symbol]
271
+ #
272
+ # :nocov:
273
+ def ssl_credentials
274
+ return :this_port_is_insecure unless options.fetch(:use_ssl, Gruf.use_ssl)
275
+
276
+ private_key = File.read(options.fetch(:ssl_key_file, Gruf.ssl_key_file))
277
+ cert_chain = File.read(options.fetch(:ssl_crt_file, Gruf.ssl_crt_file))
278
+ certs = [nil, [{ private_key: private_key, cert_chain: cert_chain }], false]
279
+ GRPC::Core::ServerCredentials.new(*certs)
280
+ end
281
+ # :nocov:
282
+
283
+ ##
284
+ # Updates proc name/title
285
+ #
286
+ # @param [Symbol] state
287
+ #
288
+ # :nocov:
289
+ def update_proc_title(state)
290
+ Process.setproctitle("gruf #{Gruf::VERSION} -- #{state}")
291
+ end
292
+ # :nocov:
293
+ end
294
+ end