rails_grpc 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +40 -40
- data/lib/rails_grpc.rb +11 -4
- data/lib/rails_grpc/dependencies.rb +2 -4
- data/lib/rails_grpc/extension/rpc_server.rb +68 -0
- data/lib/rails_grpc/general_server.rb +70 -0
- data/lib/rails_grpc/interceptor/logging_interceptor.rb +24 -0
- data/lib/rails_grpc/logger.rb +22 -0
- data/lib/rails_grpc/rack_reloader.rb +19 -0
- data/lib/rails_grpc/railtie.rb +2 -6
- data/lib/rails_grpc/reloader.rb +15 -0
- data/lib/rails_grpc/version.rb +1 -1
- data/lib/tasks/protoc.rake +18 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d366cc22163cbb02c16dc299be7180222183b608
|
4
|
+
data.tar.gz: 8ec96617b1c0b8d9acf4120545a0863e6e3111fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57c873d6cbbf088ba58263b0e29334598edbfe635a6872ff7ea921e8bb73476c3c69b2e70789a53958826f4a996e2a6a7bb69f2f5e756b36cfdd0fcf4cca5b3b
|
7
|
+
data.tar.gz: a44d0ce699339c40333385a9a46c12968c8543b5cbfa31eb821a67cf2ac3a6d75df73de08c52d46183a346803614209a930e901151dbc80333ae29e7cc66e908
|
data/Gemfile.lock
CHANGED
@@ -9,7 +9,7 @@ GIT
|
|
9
9
|
PATH
|
10
10
|
remote: .
|
11
11
|
specs:
|
12
|
-
rails_grpc (0.1.
|
12
|
+
rails_grpc (0.1.1)
|
13
13
|
grpc
|
14
14
|
protobuf
|
15
15
|
rails
|
@@ -17,43 +17,43 @@ PATH
|
|
17
17
|
GEM
|
18
18
|
remote: https://rubygems.org/
|
19
19
|
specs:
|
20
|
-
actioncable (5.2.
|
21
|
-
actionpack (= 5.2.
|
20
|
+
actioncable (5.2.1)
|
21
|
+
actionpack (= 5.2.1)
|
22
22
|
nio4r (~> 2.0)
|
23
23
|
websocket-driver (>= 0.6.1)
|
24
|
-
actionmailer (5.2.
|
25
|
-
actionpack (= 5.2.
|
26
|
-
actionview (= 5.2.
|
27
|
-
activejob (= 5.2.
|
24
|
+
actionmailer (5.2.1)
|
25
|
+
actionpack (= 5.2.1)
|
26
|
+
actionview (= 5.2.1)
|
27
|
+
activejob (= 5.2.1)
|
28
28
|
mail (~> 2.5, >= 2.5.4)
|
29
29
|
rails-dom-testing (~> 2.0)
|
30
|
-
actionpack (5.2.
|
31
|
-
actionview (= 5.2.
|
32
|
-
activesupport (= 5.2.
|
30
|
+
actionpack (5.2.1)
|
31
|
+
actionview (= 5.2.1)
|
32
|
+
activesupport (= 5.2.1)
|
33
33
|
rack (~> 2.0)
|
34
34
|
rack-test (>= 0.6.3)
|
35
35
|
rails-dom-testing (~> 2.0)
|
36
36
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
37
|
-
actionview (5.2.
|
38
|
-
activesupport (= 5.2.
|
37
|
+
actionview (5.2.1)
|
38
|
+
activesupport (= 5.2.1)
|
39
39
|
builder (~> 3.1)
|
40
40
|
erubi (~> 1.4)
|
41
41
|
rails-dom-testing (~> 2.0)
|
42
42
|
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
43
|
-
activejob (5.2.
|
44
|
-
activesupport (= 5.2.
|
43
|
+
activejob (5.2.1)
|
44
|
+
activesupport (= 5.2.1)
|
45
45
|
globalid (>= 0.3.6)
|
46
|
-
activemodel (5.2.
|
47
|
-
activesupport (= 5.2.
|
48
|
-
activerecord (5.2.
|
49
|
-
activemodel (= 5.2.
|
50
|
-
activesupport (= 5.2.
|
46
|
+
activemodel (5.2.1)
|
47
|
+
activesupport (= 5.2.1)
|
48
|
+
activerecord (5.2.1)
|
49
|
+
activemodel (= 5.2.1)
|
50
|
+
activesupport (= 5.2.1)
|
51
51
|
arel (>= 9.0)
|
52
|
-
activestorage (5.2.
|
53
|
-
actionpack (= 5.2.
|
54
|
-
activerecord (= 5.2.
|
52
|
+
activestorage (5.2.1)
|
53
|
+
actionpack (= 5.2.1)
|
54
|
+
activerecord (= 5.2.1)
|
55
55
|
marcel (~> 0.3.1)
|
56
|
-
activesupport (5.2.
|
56
|
+
activesupport (5.2.1)
|
57
57
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
58
58
|
i18n (>= 0.7, < 2)
|
59
59
|
minitest (~> 5.1)
|
@@ -72,7 +72,7 @@ GEM
|
|
72
72
|
grpc (1.14.1)
|
73
73
|
google-protobuf (~> 3.1)
|
74
74
|
googleapis-common-protos-types (~> 1.0.0)
|
75
|
-
i18n (1.0
|
75
|
+
i18n (1.1.0)
|
76
76
|
concurrent-ruby (~> 1.0)
|
77
77
|
loofah (2.2.2)
|
78
78
|
crass (~> 1.0.2)
|
@@ -84,7 +84,7 @@ GEM
|
|
84
84
|
method_source (0.9.0)
|
85
85
|
middleware (0.1.0)
|
86
86
|
mimemagic (0.3.2)
|
87
|
-
mini_mime (1.0.
|
87
|
+
mini_mime (1.0.1)
|
88
88
|
mini_portile2 (2.3.0)
|
89
89
|
minitest (5.11.3)
|
90
90
|
nio4r (2.3.1)
|
@@ -104,30 +104,30 @@ GEM
|
|
104
104
|
rack (2.0.5)
|
105
105
|
rack-test (1.1.0)
|
106
106
|
rack (>= 1.0, < 3)
|
107
|
-
rails (5.2.
|
108
|
-
actioncable (= 5.2.
|
109
|
-
actionmailer (= 5.2.
|
110
|
-
actionpack (= 5.2.
|
111
|
-
actionview (= 5.2.
|
112
|
-
activejob (= 5.2.
|
113
|
-
activemodel (= 5.2.
|
114
|
-
activerecord (= 5.2.
|
115
|
-
activestorage (= 5.2.
|
116
|
-
activesupport (= 5.2.
|
107
|
+
rails (5.2.1)
|
108
|
+
actioncable (= 5.2.1)
|
109
|
+
actionmailer (= 5.2.1)
|
110
|
+
actionpack (= 5.2.1)
|
111
|
+
actionview (= 5.2.1)
|
112
|
+
activejob (= 5.2.1)
|
113
|
+
activemodel (= 5.2.1)
|
114
|
+
activerecord (= 5.2.1)
|
115
|
+
activestorage (= 5.2.1)
|
116
|
+
activesupport (= 5.2.1)
|
117
117
|
bundler (>= 1.3.0)
|
118
|
-
railties (= 5.2.
|
118
|
+
railties (= 5.2.1)
|
119
119
|
sprockets-rails (>= 2.0.0)
|
120
120
|
rails-dom-testing (2.0.3)
|
121
121
|
activesupport (>= 4.2.0)
|
122
122
|
nokogiri (>= 1.6)
|
123
123
|
rails-html-sanitizer (1.0.4)
|
124
124
|
loofah (~> 2.2, >= 2.2.2)
|
125
|
-
railties (5.2.
|
126
|
-
actionpack (= 5.2.
|
127
|
-
activesupport (= 5.2.
|
125
|
+
railties (5.2.1)
|
126
|
+
actionpack (= 5.2.1)
|
127
|
+
activesupport (= 5.2.1)
|
128
128
|
method_source
|
129
129
|
rake (>= 0.8.7)
|
130
|
-
thor (>= 0.
|
130
|
+
thor (>= 0.19.0, < 2.0)
|
131
131
|
rake (10.5.0)
|
132
132
|
rspec (3.7.0)
|
133
133
|
rspec-core (~> 3.7.0)
|
data/lib/rails_grpc.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
require "rails_grpc/version"
|
2
2
|
|
3
3
|
module RailsGrpc
|
4
|
-
|
5
|
-
|
6
|
-
if defined?(Rails)
|
4
|
+
# required
|
7
5
|
require "rails_grpc/dependencies"
|
8
|
-
require "rails_grpc/reloader"
|
9
6
|
require "rails_grpc/railtie"
|
7
|
+
require "rails_grpc/logger"
|
8
|
+
require "rails_grpc/interceptor/logging_interceptor"
|
9
|
+
|
10
|
+
# extension
|
11
|
+
require "rails_grpc/extension/rpc_server"
|
12
|
+
|
13
|
+
# options
|
14
|
+
autoload :Reloader, "rails_grpc/reloader"
|
15
|
+
autoload :GeneralServer, "rails_grpc/general_server"
|
16
|
+
autoload :RackReloader, "rails_grpc/rack_reloader"
|
10
17
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "rails"
|
2
|
-
|
3
1
|
module RailsGrpc
|
4
2
|
module Dependencies
|
5
3
|
mattr_accessor :proto_lib_dir
|
@@ -75,12 +73,12 @@ module RailsGrpc
|
|
75
73
|
end
|
76
74
|
|
77
75
|
def load_and_watch(file_path, const_name)
|
78
|
-
watch_file_and_dir(file_path)
|
76
|
+
watch_file_and_dir(file_path) unless self.cache_classes?
|
79
77
|
|
80
78
|
ActiveSupport::Dependencies.require_or_load(file_path, const_name.to_sym)
|
81
79
|
end
|
82
80
|
|
83
|
-
def watch_file_and_dir(
|
81
|
+
def watch_file_and_dir(file_path)
|
84
82
|
dir_path = File.dirname(file_path)
|
85
83
|
|
86
84
|
::Rails.application.config.watchable_dirs[dir_path] = [:rb]
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "grpc"
|
2
|
+
|
3
|
+
module GRPC
|
4
|
+
class RpcServer
|
5
|
+
attr_accessor :application_reload
|
6
|
+
|
7
|
+
# handles calls to the server
|
8
|
+
def loop_handle_server_calls
|
9
|
+
fail 'not started' if running_state == :not_started
|
10
|
+
while running_state == :running
|
11
|
+
begin
|
12
|
+
an_rpc = @server.request_call
|
13
|
+
break if (!an_rpc.nil?) && an_rpc.call.nil?
|
14
|
+
active_call = new_active_server_call(an_rpc)
|
15
|
+
unless active_call.nil?
|
16
|
+
@pool.schedule(active_call) do |ac|
|
17
|
+
c, mth = ac
|
18
|
+
begin
|
19
|
+
# extended for reloader
|
20
|
+
@application_reload.call unless @application_reload.nil?
|
21
|
+
# extended for reloader
|
22
|
+
|
23
|
+
rpc_descs[mth].run_server_method(
|
24
|
+
c,
|
25
|
+
rpc_handlers[mth],
|
26
|
+
@interceptors.build_context
|
27
|
+
)
|
28
|
+
rescue StandardError
|
29
|
+
c.send_status(GRPC::Core::StatusCodes::INTERNAL,
|
30
|
+
'Server handler failed')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rescue Core::CallError, RuntimeError => e
|
35
|
+
# these might happen for various reasons. The correct behavior of
|
36
|
+
# the server is to log them and continue, if it's not shutting down.
|
37
|
+
if running_state == :running
|
38
|
+
GRPC.logger.warn("server call failed: #{e}")
|
39
|
+
end
|
40
|
+
next
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# @running_state should be :stopping here
|
44
|
+
@run_mutex.synchronize do
|
45
|
+
transition_running_state(:stopped)
|
46
|
+
GRPC.logger.info("stopped: #{self}")
|
47
|
+
@server.close
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_force_rpc_descs_for(service)
|
52
|
+
cls = service.is_a?(Class) ? service : service.class
|
53
|
+
specs, handlers = (@rpc_descs ||= {}), (@rpc_handlers ||= {})
|
54
|
+
cls.rpc_descs.each_pair do |name, spec|
|
55
|
+
route = "/#{cls.service_name}/#{name}".to_sym
|
56
|
+
# fail "already registered: rpc #{route} from #{spec}" if specs.key? route
|
57
|
+
specs[route] = spec
|
58
|
+
rpc_name = GenericService.underscore(name.to_s).to_sym
|
59
|
+
if service.is_a?(Class)
|
60
|
+
handlers[route] = cls.new.method(rpc_name)
|
61
|
+
else
|
62
|
+
handlers[route] = service.method(rpc_name)
|
63
|
+
end
|
64
|
+
GRPC.logger.info("handling #{route} with #{handlers[route]}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "grpc"
|
2
|
+
require "rails_grpc/interceptor/logging_interceptor"
|
3
|
+
require "rails_grpc/dependencies"
|
4
|
+
|
5
|
+
module RailsGrpc
|
6
|
+
class GeneralServer
|
7
|
+
attr_accessor :port, :logger, :grpc_server, :handlers, :interceptors
|
8
|
+
|
9
|
+
# When you would like to use autoreload in development mode,
|
10
|
+
# pool_size > 1 reloading is so slow, so you should set pool_size 1.
|
11
|
+
attr_accessor :pool_size
|
12
|
+
|
13
|
+
def initialize(port:, pool_size: nil, logger: Rails.logger)
|
14
|
+
self.port = port
|
15
|
+
self.pool_size = pool_size
|
16
|
+
self.logger = logger
|
17
|
+
self.handlers = []
|
18
|
+
|
19
|
+
self.interceptors = [
|
20
|
+
RailsGrpc::Interceptor::LoggingInterceptor.new(RailsGrpc::Logger.logger(logger))
|
21
|
+
]
|
22
|
+
|
23
|
+
self.grpc_server = if pool_size.present?
|
24
|
+
GRPC::RpcServer.new(pool_size: pool_size, interceptors: self.interceptors)
|
25
|
+
else
|
26
|
+
GRPC::RpcServer.new(interceptors: self.interceptors)
|
27
|
+
end
|
28
|
+
self.grpc_server.add_http2_port(port, :this_port_is_insecure)
|
29
|
+
set_reloader
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_reloader
|
33
|
+
unless RailsGrpc::Dependencies.cache_classes?
|
34
|
+
@grpc_server.application_reload = lambda do
|
35
|
+
changed = Rails.application.reloader.check.call
|
36
|
+
if changed
|
37
|
+
@logger.info("Reloading GRPC Server...")
|
38
|
+
Rails.application.reloader.reload!
|
39
|
+
@logger.info("Reset GRPC services...")
|
40
|
+
|
41
|
+
@handlers.each do |h|
|
42
|
+
reloaded_handler = h.to_s.constantize
|
43
|
+
@grpc_server.send(:add_force_rpc_descs_for, reloaded_handler)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_handlers(handlers)
|
51
|
+
hs = Array(handlers)
|
52
|
+
hs.each do |h|
|
53
|
+
@grpc_server.handle(h)
|
54
|
+
end
|
55
|
+
@handlers.concat(hs)
|
56
|
+
end
|
57
|
+
|
58
|
+
def run
|
59
|
+
@logger.info("GRPC server running on #{port}")
|
60
|
+
begin
|
61
|
+
@grpc_server.run_till_terminated
|
62
|
+
rescue SystemExit, Interrupt
|
63
|
+
# server does not stop gracefully because of it is a bug of grpc ruby.
|
64
|
+
# see: https://github.com/grpc/grpc/issues/14043
|
65
|
+
@logger.info("GRPC server goodbye!")
|
66
|
+
@grpc_server.stop
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "grpc"
|
2
|
+
|
3
|
+
module RailsGrpc
|
4
|
+
module Interceptor
|
5
|
+
class LoggingInterceptor < ::GRPC::ServerInterceptor
|
6
|
+
def initialize(logger)
|
7
|
+
@logger = logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def request_response(request: nil, call: nil, method: nil)
|
11
|
+
grpc_method = "#{method.owner.name}##{method.name}"
|
12
|
+
logger = @logger
|
13
|
+
logger.debug("[GRPC] #{grpc_method}")
|
14
|
+
t = Time.now
|
15
|
+
|
16
|
+
yield
|
17
|
+
|
18
|
+
t = Time.now - t
|
19
|
+
display_duration = "%.1f ms" % (t * 1000.0)
|
20
|
+
logger.debug("[GRPC response] (#{display_duration}) #{grpc_method}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "rails"
|
2
|
+
|
3
|
+
module RailsGrpc
|
4
|
+
class Logger
|
5
|
+
class << self
|
6
|
+
delegate :debug, :info, :warn, :error, :fatal, to: :logger
|
7
|
+
|
8
|
+
def logger(original_logger)
|
9
|
+
return @logger if @logger.present?
|
10
|
+
|
11
|
+
if Rails.env.development? || Rails.env.test?
|
12
|
+
std_logger = ActiveSupport::Logger.new(STDOUT)
|
13
|
+
multiple_loggers = ActiveSupport::Logger.broadcast(std_logger)
|
14
|
+
original_logger.extend(multiple_loggers)
|
15
|
+
end
|
16
|
+
|
17
|
+
@logger = original_logger
|
18
|
+
@logger
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rails_grpc/dependencies"
|
2
|
+
|
3
|
+
module RailsGrpc
|
4
|
+
class RackReloader
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
unless RailsGrpc::Dependencies.cache_classes?
|
11
|
+
changed = Rails.application.reloader.check.call
|
12
|
+
if changed
|
13
|
+
Rails.application.reloader.reload!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rails_grpc/railtie.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require "rails"
|
2
1
|
require "rails_grpc/dependencies"
|
2
|
+
require "rails_grpc/reloader"
|
3
3
|
require "google/protobuf"
|
4
4
|
|
5
5
|
module RailsGrpc
|
@@ -13,11 +13,7 @@ module RailsGrpc
|
|
13
13
|
end
|
14
14
|
|
15
15
|
ActiveSupport::Reloader.to_complete do
|
16
|
-
|
17
|
-
Google::Protobuf::DescriptorPool.generated_pool.clear
|
18
|
-
RailsGrpc::Dependencies.clear_dependencies!
|
19
|
-
RailsGrpc::Dependencies.load_dependencies!
|
20
|
-
end
|
16
|
+
RailsGrpc::Reloader.reload!
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|
data/lib/rails_grpc/reloader.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "rails_grpc/dependencies"
|
2
|
+
|
3
|
+
module RailsGrpc
|
4
|
+
module Reloader
|
5
|
+
class << self
|
6
|
+
def reload!
|
7
|
+
unless RailsGrpc::Dependencies.cache_classes?
|
8
|
+
Google::Protobuf::DescriptorPool.generated_pool.clear
|
9
|
+
RailsGrpc::Dependencies.clear_dependencies!
|
10
|
+
RailsGrpc::Dependencies.load_dependencies!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/rails_grpc/version.rb
CHANGED
data/lib/tasks/protoc.rake
CHANGED
@@ -55,7 +55,24 @@ protoc -I #{proto_path} --ruby_out=#{ruby_out} --grpc_out=#{grpc_out} \
|
|
55
55
|
name.end_with?("_pb.rb") && name.include?("_services_")
|
56
56
|
end
|
57
57
|
service_files.each do |path|
|
58
|
-
source = open(path)
|
58
|
+
source = open(path)
|
59
|
+
.read
|
60
|
+
.split("\n")
|
61
|
+
.reject { |line| line =~ /^require / && !line.include?("grpc") }.join("\n")
|
62
|
+
open(path, "w") do |f|
|
63
|
+
f.write source
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
without_service_files = grpc_out_ruby_files.select do |v|
|
68
|
+
name = File.basename(v)
|
69
|
+
name.end_with?("_pb.rb") && !name.include?("_services_")
|
70
|
+
end
|
71
|
+
without_service_files.each do |path|
|
72
|
+
source = open(path)
|
73
|
+
.read
|
74
|
+
.split("\n")
|
75
|
+
.reject { |line| line =~ /^require / && !line.include?("google/protobuf") }.join("\n")
|
59
76
|
open(path, "w") do |f|
|
60
77
|
f.write source
|
61
78
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_grpc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shinsuke Nishio
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -114,6 +114,11 @@ files:
|
|
114
114
|
- bin/setup
|
115
115
|
- lib/rails_grpc.rb
|
116
116
|
- lib/rails_grpc/dependencies.rb
|
117
|
+
- lib/rails_grpc/extension/rpc_server.rb
|
118
|
+
- lib/rails_grpc/general_server.rb
|
119
|
+
- lib/rails_grpc/interceptor/logging_interceptor.rb
|
120
|
+
- lib/rails_grpc/logger.rb
|
121
|
+
- lib/rails_grpc/rack_reloader.rb
|
117
122
|
- lib/rails_grpc/railtie.rb
|
118
123
|
- lib/rails_grpc/reloader.rb
|
119
124
|
- lib/rails_grpc/version.rb
|
@@ -139,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
144
|
version: '0'
|
140
145
|
requirements: []
|
141
146
|
rubyforge_project:
|
142
|
-
rubygems_version: 2.
|
147
|
+
rubygems_version: 2.6.8
|
143
148
|
signing_key:
|
144
149
|
specification_version: 4
|
145
150
|
summary: gRPC for Ruby on Rails
|