gruf 2.13.1 → 2.17.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|