gruf 2.13.1 → 2.17.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 +55 -7
- data/README.md +1 -1
- data/gruf.gemspec +12 -10
- data/lib/gruf/autoloaders.rb +76 -0
- data/lib/gruf/cli/executor.rb +95 -6
- data/lib/gruf/client/error.rb +0 -28
- data/lib/gruf/client/errors.rb +48 -0
- data/lib/gruf/client.rb +0 -3
- data/lib/gruf/configuration.rb +23 -5
- data/lib/gruf/controllers/autoloader.rb +96 -0
- data/lib/gruf/controllers/base.rb +3 -5
- data/lib/gruf/controllers/health_controller.rb +39 -0
- data/lib/gruf/controllers/request.rb +6 -0
- data/lib/gruf/controllers/service_binder.rb +73 -81
- data/lib/gruf/error.rb +0 -4
- data/lib/gruf/{logging.rb → grpc_logger.rb} +0 -14
- data/lib/gruf/integrations/rails/railtie.rb +30 -0
- data/lib/gruf/interceptors/active_record/connection_reset.rb +11 -2
- data/lib/gruf/interceptors/base.rb +0 -10
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +0 -3
- data/lib/gruf/logger.rb +32 -0
- data/lib/gruf/server.rb +48 -50
- data/lib/gruf/version.rb +1 -1
- data/lib/gruf.rb +18 -20
- metadata +30 -6
@@ -0,0 +1,39 @@
|
|
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 'grpc/health/v1/health_services_pb'
|
19
|
+
|
20
|
+
module Gruf
|
21
|
+
module Controllers
|
22
|
+
##
|
23
|
+
# Dynamic standard grpc health check controller. Can be used as-is, or can use ::Gruf.health_check_hook to
|
24
|
+
# provide custom responses.
|
25
|
+
#
|
26
|
+
class HealthController < Gruf::Controllers::Base
|
27
|
+
bind ::Grpc::Health::V1::Health::Service
|
28
|
+
|
29
|
+
def check
|
30
|
+
health_proc = ::Gruf.health_check_hook
|
31
|
+
return health_proc.call(request, error) if !health_proc.nil? && health_proc.respond_to?(:call)
|
32
|
+
|
33
|
+
::Grpc::Health::V1::HealthCheckResponse.new(
|
34
|
+
status: ::Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -36,6 +36,11 @@ module Gruf
|
|
36
36
|
# @!attribute [r] service
|
37
37
|
# @return [Class] The GRPC service class for this request
|
38
38
|
attr_reader :service
|
39
|
+
# @!attribute [r] context
|
40
|
+
# @return [::ActiveSupport::HashWithIndifferentAccess] An arbitrary hash of key/value entries that are
|
41
|
+
# accessible for interceptors, that can be used to shared information between interceptors and pass down into
|
42
|
+
# the controller.
|
43
|
+
attr_reader :context
|
39
44
|
|
40
45
|
delegate :metadata, to: :active_call
|
41
46
|
delegate :messages, :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :type
|
@@ -72,6 +77,7 @@ module Gruf
|
|
72
77
|
@message = message
|
73
78
|
@rpc_desc = rpc_desc
|
74
79
|
@type = Type.new(rpc_desc)
|
80
|
+
@context = ::ActiveSupport::HashWithIndifferentAccess.new
|
75
81
|
end
|
76
82
|
|
77
83
|
##
|
@@ -26,92 +26,84 @@ module Gruf
|
|
26
26
|
#
|
27
27
|
class BoundDesc < SimpleDelegator; end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# Bind all methods on the service to the passed controller
|
40
|
-
#
|
41
|
-
# @param [Class<Gruf::Controllers::Base>] controller
|
42
|
-
#
|
43
|
-
def bind!(controller)
|
44
|
-
rpc_methods.each { |name, desc| bind_method(controller, name, desc) }
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
##
|
50
|
-
# Bind the grpc methods to the service, allowing for server interception and execution control
|
51
|
-
#
|
52
|
-
# @param [Gruf::Controllers::Base] controller
|
53
|
-
# @param [Symbol] method_name
|
54
|
-
# @param [BoundDesc] desc
|
55
|
-
#
|
56
|
-
def bind_method(controller, method_name, desc)
|
57
|
-
method_key = method_name.to_s.underscore.to_sym
|
58
|
-
service_ref = @service
|
29
|
+
class << self
|
30
|
+
##
|
31
|
+
# Bind all methods on the service to the passed controller
|
32
|
+
#
|
33
|
+
# @param [Class<Gruf::Controllers::Base>] controller
|
34
|
+
#
|
35
|
+
def bind!(service:, controller:)
|
36
|
+
rpc_methods = service.rpc_descs.map { |rd| BoundDesc.new(rd) }
|
37
|
+
rpc_methods.each { |name, desc| bind_method(service, controller, name, desc) }
|
38
|
+
end
|
59
39
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
40
|
+
##
|
41
|
+
# Bind the grpc methods to the service, allowing for server interception and execution control
|
42
|
+
#
|
43
|
+
# @param [Gruf::Controllers::Base] controller
|
44
|
+
# @param [Symbol] method_name
|
45
|
+
# @param [BoundDesc] desc
|
46
|
+
#
|
47
|
+
def bind_method(service_ref, controller, method_name, desc)
|
48
|
+
method_key = method_name.to_s.underscore.to_sym
|
49
|
+
controller_name = controller.name
|
50
|
+
service_ref.class_eval do
|
51
|
+
if desc.request_response?
|
52
|
+
define_method(method_key) do |message, active_call|
|
53
|
+
Gruf::Autoloaders.controllers.with_fresh_controller(controller_name) do |fresh_controller|
|
54
|
+
c = fresh_controller.new(
|
55
|
+
method_key: method_key,
|
56
|
+
service: service_ref,
|
57
|
+
message: message,
|
58
|
+
active_call: active_call,
|
59
|
+
rpc_desc: desc
|
60
|
+
)
|
61
|
+
c.call(method_key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
elsif desc.client_streamer?
|
65
|
+
define_method(method_key) do |active_call|
|
66
|
+
Gruf::Autoloaders.controllers.with_fresh_controller(controller_name) do |fresh_controller|
|
67
|
+
c = fresh_controller.new(
|
68
|
+
method_key: method_key,
|
69
|
+
service: service_ref,
|
70
|
+
message: proc { |&block| active_call.each_remote_read(&block) },
|
71
|
+
active_call: active_call,
|
72
|
+
rpc_desc: desc
|
73
|
+
)
|
74
|
+
c.call(method_key)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
elsif desc.server_streamer?
|
78
|
+
define_method(method_key) do |message, active_call, &block|
|
79
|
+
Gruf::Autoloaders.controllers.with_fresh_controller(controller_name) do |fresh_controller|
|
80
|
+
c = fresh_controller.new(
|
81
|
+
method_key: method_key,
|
82
|
+
service: service_ref,
|
83
|
+
message: message,
|
84
|
+
active_call: active_call,
|
85
|
+
rpc_desc: desc
|
86
|
+
)
|
87
|
+
c.call(method_key, &block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
else # bidi
|
91
|
+
define_method(method_key) do |messages, active_call, &block|
|
92
|
+
Gruf::Autoloaders.controllers.with_fresh_controller(controller_name) do |fresh_controller|
|
93
|
+
c = fresh_controller.new(
|
94
|
+
method_key: method_key,
|
95
|
+
service: service_ref,
|
96
|
+
message: messages,
|
97
|
+
active_call: active_call,
|
98
|
+
rpc_desc: desc
|
99
|
+
)
|
100
|
+
c.call(method_key, &block)
|
101
|
+
end
|
102
|
+
end
|
104
103
|
end
|
105
104
|
end
|
106
105
|
end
|
107
106
|
end
|
108
|
-
|
109
|
-
##
|
110
|
-
# @return Array<Gruf::Controllers::ServiceBinder::BoundDesc>
|
111
|
-
#
|
112
|
-
def rpc_methods
|
113
|
-
@service.rpc_descs.map { |rd| BoundDesc.new(rd) }
|
114
|
-
end
|
115
107
|
end
|
116
108
|
end
|
117
109
|
end
|
data/lib/gruf/error.rb
CHANGED
@@ -15,10 +15,6 @@
|
|
15
15
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
16
|
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
17
|
#
|
18
|
-
require_relative 'errors/field'
|
19
|
-
require_relative 'errors/debug_info'
|
20
|
-
require_relative 'serializers/errors/base'
|
21
|
-
require_relative 'serializers/errors/json'
|
22
18
|
|
23
19
|
module Gruf
|
24
20
|
##
|
@@ -16,20 +16,6 @@
|
|
16
16
|
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
17
|
#
|
18
18
|
module Gruf
|
19
|
-
##
|
20
|
-
# Handles internal gruf logging requests
|
21
|
-
#
|
22
|
-
module Logger
|
23
|
-
##
|
24
|
-
# Return the current Gruf logger
|
25
|
-
#
|
26
|
-
# @return [Logger]
|
27
|
-
#
|
28
|
-
def logger
|
29
|
-
Gruf.logger
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
19
|
##
|
34
20
|
# Handles grpc internal logging requests
|
35
21
|
#
|
@@ -1,9 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
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
|
+
#
|
3
18
|
module Gruf
|
4
19
|
module Integrations
|
5
20
|
module Rails
|
21
|
+
##
|
22
|
+
# Rails integration for Gruf, that currently only manages code autoloading in a Rails context
|
23
|
+
#
|
6
24
|
class Railtie < ::Rails::Railtie
|
25
|
+
initializer 'gruf.initializer' do |app|
|
26
|
+
config.before_configuration do
|
27
|
+
# Remove autoloading of the controllers path from Rails' zeitwerk, so that we ensure Gruf's zeitwerk
|
28
|
+
# properly manages them itself. This allows us to manage code reloading and logging in Gruf specifically
|
29
|
+
app.config.eager_load_paths -= [::Gruf.controllers_path] if app.config.respond_to?(:eager_load_paths)
|
30
|
+
if ::Rails.respond_to?(:autoloaders) # if we're on a late enough version of rails
|
31
|
+
::Rails.autoloaders.each do |autoloader|
|
32
|
+
autoloader.ignore(Gruf.controllers_path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
7
37
|
end
|
8
38
|
end
|
9
39
|
end
|
@@ -27,11 +27,13 @@ module Gruf
|
|
27
27
|
# connection pool, we need to ensure that this is done to properly
|
28
28
|
#
|
29
29
|
def call
|
30
|
-
|
30
|
+
if enabled?
|
31
|
+
target_classes.each { |klass| klass.establish_connection unless klass.connection.active? }
|
32
|
+
end
|
31
33
|
|
32
34
|
yield
|
33
35
|
ensure
|
34
|
-
|
36
|
+
target_classes.each(&:clear_active_connections!) if enabled?
|
35
37
|
end
|
36
38
|
|
37
39
|
private
|
@@ -42,6 +44,13 @@ module Gruf
|
|
42
44
|
def enabled?
|
43
45
|
defined?(::ActiveRecord::Base)
|
44
46
|
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# @return [Array<Class>] The list of ActiveRecord classes to reset
|
50
|
+
#
|
51
|
+
def target_classes
|
52
|
+
options[:target_classes] || [::ActiveRecord::Base]
|
53
|
+
end
|
45
54
|
end
|
46
55
|
end
|
47
56
|
end
|
@@ -44,13 +44,3 @@ module Gruf
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
48
|
-
require_relative 'client_interceptor'
|
49
|
-
require_relative 'server_interceptor'
|
50
|
-
require_relative 'context'
|
51
|
-
require_relative 'timer'
|
52
|
-
require_relative 'active_record/connection_reset'
|
53
|
-
require_relative 'authentication/basic'
|
54
|
-
require_relative 'instrumentation/statsd'
|
55
|
-
require_relative 'instrumentation/output_metadata_timer'
|
56
|
-
require_relative 'instrumentation/request_logging/interceptor'
|
@@ -16,9 +16,6 @@
|
|
16
16
|
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
17
|
#
|
18
18
|
require 'socket'
|
19
|
-
require_relative 'formatters/base'
|
20
|
-
require_relative 'formatters/logstash'
|
21
|
-
require_relative 'formatters/plain'
|
22
19
|
|
23
20
|
module Gruf
|
24
21
|
module Interceptors
|
data/lib/gruf/logger.rb
ADDED
@@ -0,0 +1,32 @@
|
|
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
|
+
# Handles internal gruf logging requests
|
21
|
+
#
|
22
|
+
module Logger
|
23
|
+
##
|
24
|
+
# Return the current Gruf logger
|
25
|
+
#
|
26
|
+
# @return [Logger]
|
27
|
+
#
|
28
|
+
def logger
|
29
|
+
Gruf.logger
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/gruf/server.rb
CHANGED
@@ -43,39 +43,45 @@ module Gruf
|
|
43
43
|
@options = opts || {}
|
44
44
|
@interceptors = opts.fetch(:interceptor_registry, Gruf.interceptors)
|
45
45
|
@interceptors = Gruf::Interceptors::Registry.new unless @interceptors.is_a?(Gruf::Interceptors::Registry)
|
46
|
-
@services =
|
46
|
+
@services = nil
|
47
47
|
@started = false
|
48
48
|
@hostname = opts.fetch(:hostname, Gruf.server_binding_url)
|
49
49
|
@event_listener_proc = opts.fetch(:event_listener_proc, Gruf.event_listener_proc)
|
50
|
-
setup
|
51
50
|
end
|
52
51
|
|
53
52
|
##
|
54
53
|
# @return [GRPC::RpcServer] The GRPC server running
|
55
54
|
#
|
56
55
|
def server
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
56
|
+
server_mutex do
|
57
|
+
@server ||= begin
|
58
|
+
# For backward compatibility, we allow these options to be passed directly
|
59
|
+
# in the Gruf::Server options, or via Gruf.rpc_server_options.
|
60
|
+
server_options = {
|
61
|
+
pool_size: options.fetch(:pool_size, Gruf.rpc_server_options[:pool_size]),
|
62
|
+
max_waiting_requests: options.fetch(:max_waiting_requests, Gruf.rpc_server_options[:max_waiting_requests]),
|
63
|
+
poll_period: options.fetch(:poll_period, Gruf.rpc_server_options[:poll_period]),
|
64
|
+
pool_keep_alive: options.fetch(:pool_keep_alive, Gruf.rpc_server_options[:pool_keep_alive]),
|
65
|
+
connect_md_proc: options.fetch(:connect_md_proc, Gruf.rpc_server_options[:connect_md_proc]),
|
66
|
+
server_args: options.fetch(:server_args, Gruf.rpc_server_options[:server_args])
|
67
|
+
}
|
68
|
+
|
69
|
+
server = if @event_listener_proc
|
70
|
+
server_options[:event_listener_proc] = @event_listener_proc
|
71
|
+
Gruf::InstrumentableGrpcServer.new(**server_options)
|
72
|
+
else
|
73
|
+
GRPC::RpcServer.new(**server_options)
|
74
|
+
end
|
75
|
+
|
76
|
+
@port = server.add_http2_port(@hostname, ssl_credentials)
|
77
|
+
# do not reference `services` any earlier than this method, as it allows autoloading to take effect
|
78
|
+
# and load services into `Gruf.services` as late as possible, which gives us flexibility with different
|
79
|
+
# execution paths (such as vanilla ruby, grape, multiple Rails versions, etc). The autoloaders are
|
80
|
+
# initially loaded in `Gruf::Cli::Executor` _directly_ before the gRPC services are loaded into the gRPC
|
81
|
+
# server, to allow for loading services as late as possible in the execution chain.
|
82
|
+
services.each { |s| server.handle(s) }
|
83
|
+
server
|
84
|
+
end
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
@@ -87,7 +93,7 @@ module Gruf
|
|
87
93
|
update_proc_title(:starting)
|
88
94
|
|
89
95
|
server_thread = Thread.new do
|
90
|
-
logger.info { "Starting gruf server at #{@hostname}..." }
|
96
|
+
logger.info { "[gruf] Starting gruf server at #{@hostname}..." }
|
91
97
|
server.run_till_terminated_or_interrupted(KILL_SIGNALS)
|
92
98
|
end
|
93
99
|
@started = true
|
@@ -96,7 +102,7 @@ module Gruf
|
|
96
102
|
@started = false
|
97
103
|
|
98
104
|
update_proc_title(:stopped)
|
99
|
-
logger.info { 'Goodbye!' }
|
105
|
+
logger.info { '[gruf] Goodbye!' }
|
100
106
|
end
|
101
107
|
# :nocov:
|
102
108
|
|
@@ -109,7 +115,7 @@ module Gruf
|
|
109
115
|
def add_service(klass)
|
110
116
|
raise ServerAlreadyStartedError if @started
|
111
117
|
|
112
|
-
@services << klass unless
|
118
|
+
@services << klass unless services.include?(klass)
|
113
119
|
end
|
114
120
|
|
115
121
|
##
|
@@ -183,31 +189,11 @@ module Gruf
|
|
183
189
|
private
|
184
190
|
|
185
191
|
##
|
186
|
-
#
|
187
|
-
#
|
188
|
-
# :nocov:
|
189
|
-
def setup
|
190
|
-
load_controllers
|
191
|
-
end
|
192
|
-
# :nocov:
|
193
|
-
|
194
|
-
##
|
195
|
-
# Auto-load all gRPC handlers
|
192
|
+
# @return [Array<Class>]
|
196
193
|
#
|
197
|
-
|
198
|
-
|
199
|
-
return unless File.directory?(controllers_path)
|
200
|
-
|
201
|
-
path = File.realpath(controllers_path)
|
202
|
-
$LOAD_PATH.unshift(path)
|
203
|
-
Dir["#{path}/**/*.rb"].each do |f|
|
204
|
-
next if f.include?('_pb') # exclude if people include proto generated files in app/rpc
|
205
|
-
|
206
|
-
logger.info "- Loading gRPC service file: #{f}"
|
207
|
-
load File.realpath(f)
|
208
|
-
end
|
194
|
+
def services
|
195
|
+
@services ||= (::Gruf.services || (options.fetch(:services, nil) || []))
|
209
196
|
end
|
210
|
-
# :nocov:
|
211
197
|
|
212
198
|
##
|
213
199
|
# @param [String]
|
@@ -242,5 +228,17 @@ module Gruf
|
|
242
228
|
Process.setproctitle("gruf #{Gruf::VERSION} -- #{state}")
|
243
229
|
end
|
244
230
|
# :nocov:
|
231
|
+
#
|
232
|
+
|
233
|
+
##
|
234
|
+
# Handle thread-safe access to the server
|
235
|
+
#
|
236
|
+
def server_mutex(&block)
|
237
|
+
@server_mutex ||= begin
|
238
|
+
require 'monitor'
|
239
|
+
Monitor.new
|
240
|
+
end
|
241
|
+
@server_mutex.synchronize(&block)
|
242
|
+
end
|
245
243
|
end
|
246
244
|
end
|
data/lib/gruf/version.rb
CHANGED
data/lib/gruf.rb
CHANGED
@@ -17,29 +17,21 @@
|
|
17
17
|
#
|
18
18
|
require 'grpc'
|
19
19
|
require 'active_support/core_ext/module/delegation'
|
20
|
+
require 'active_support/hash_with_indifferent_access'
|
20
21
|
require 'active_support/concern'
|
21
22
|
require 'active_support/inflector'
|
22
23
|
require 'base64'
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
require_relative 'gruf/hooks/executor'
|
35
|
-
require_relative 'gruf/hooks/base'
|
36
|
-
require_relative 'gruf/timer'
|
37
|
-
require_relative 'gruf/response'
|
38
|
-
require_relative 'gruf/error'
|
39
|
-
require_relative 'gruf/client'
|
40
|
-
require_relative 'gruf/synchronized_client'
|
41
|
-
require_relative 'gruf/instrumentable_grpc_server'
|
42
|
-
require_relative 'gruf/server'
|
24
|
+
|
25
|
+
# use Zeitwerk to lazily autoload all the files in the lib directory
|
26
|
+
require 'zeitwerk'
|
27
|
+
loader = ::Zeitwerk::Loader.new
|
28
|
+
loader.tag = File.basename(__FILE__, '.rb')
|
29
|
+
loader.inflector = ::Zeitwerk::GemInflector.new(__FILE__)
|
30
|
+
loader.ignore("#{__dir__}/gruf/integrations/rails/railtie.rb")
|
31
|
+
loader.ignore("#{__dir__}/gruf/controllers/health_controller.rb")
|
32
|
+
loader.push_dir(__dir__)
|
33
|
+
loader.setup
|
34
|
+
|
43
35
|
require_relative 'gruf/integrations/rails/railtie' if defined?(::Rails)
|
44
36
|
|
45
37
|
##
|
@@ -47,4 +39,10 @@ require_relative 'gruf/integrations/rails/railtie' if defined?(::Rails)
|
|
47
39
|
#
|
48
40
|
module Gruf
|
49
41
|
extend Configuration
|
42
|
+
|
43
|
+
class << self
|
44
|
+
def autoloaders
|
45
|
+
Autoloaders
|
46
|
+
end
|
47
|
+
end
|
50
48
|
end
|