grpcx 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ce77106489146dc1a2c5dbaf39411f2061d86355b857de1100cc952a8d1b9522
4
+ data.tar.gz: 30cdaa7d8aaa269106010a61e91a4c2916c928218fa47624ee6c06a0f4bccd48
5
+ SHA512:
6
+ metadata.gz: 10727d31b94270648bab756d5da572ffcf244f17bf4540ee4830d110635bf26e7c0900de0d11002a5bd840a3796fbda18a417bd5f38353f44fdcdac7b39af03a
7
+ data.tar.gz: 1378bb8ecf7d4528e0400bb109fc80e1e98baa0567a131c510ed40b1f3dd37752337d21ad41f7982cf23fb3a7eb9d71fea3c18fd12de5ac5eb4e3d05c9b4a3f6
data/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .rubocop-*
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ inherit_from:
2
+ - https://storage.googleapis.com/bsm-misc/rubocop.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.2
6
+
7
+ Metrics/AbcSize:
8
+ Enabled: false
9
+
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,107 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ grpcx (0.1.0)
5
+ activesupport (>= 5.0)
6
+ grpc (>= 1.8.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (5.2.0)
12
+ activesupport (= 5.2.0)
13
+ activerecord (5.2.0)
14
+ activemodel (= 5.2.0)
15
+ activesupport (= 5.2.0)
16
+ arel (>= 9.0)
17
+ activesupport (5.2.0)
18
+ concurrent-ruby (~> 1.0, >= 1.0.2)
19
+ i18n (>= 0.7, < 2)
20
+ minitest (~> 5.1)
21
+ tzinfo (~> 1.1)
22
+ addressable (2.5.2)
23
+ public_suffix (>= 2.0.2, < 4.0)
24
+ arel (9.0.0)
25
+ ast (2.4.0)
26
+ concurrent-ruby (1.0.5)
27
+ diff-lcs (1.3)
28
+ faraday (0.15.0)
29
+ multipart-post (>= 1.2, < 3)
30
+ google-protobuf (3.5.1.2-x86_64-linux)
31
+ googleapis-common-protos-types (1.0.1)
32
+ google-protobuf (~> 3.0)
33
+ googleauth (0.6.2)
34
+ faraday (~> 0.12)
35
+ jwt (>= 1.4, < 3.0)
36
+ logging (~> 2.0)
37
+ memoist (~> 0.12)
38
+ multi_json (~> 1.11)
39
+ os (~> 0.9)
40
+ signet (~> 0.7)
41
+ grpc (1.11.0-x86_64-linux)
42
+ google-protobuf (~> 3.1)
43
+ googleapis-common-protos-types (~> 1.0.0)
44
+ googleauth (>= 0.5.1, < 0.7)
45
+ i18n (1.0.1)
46
+ concurrent-ruby (~> 1.0)
47
+ jwt (2.1.0)
48
+ little-plugger (1.1.4)
49
+ logging (2.2.2)
50
+ little-plugger (~> 1.1)
51
+ multi_json (~> 1.10)
52
+ memoist (0.16.0)
53
+ minitest (5.11.3)
54
+ multi_json (1.13.1)
55
+ multipart-post (2.0.0)
56
+ os (0.9.6)
57
+ parallel (1.12.1)
58
+ parser (2.5.1.0)
59
+ ast (~> 2.4.0)
60
+ powerpack (0.1.1)
61
+ public_suffix (3.0.2)
62
+ rainbow (3.0.0)
63
+ rake (12.3.1)
64
+ rspec (3.7.0)
65
+ rspec-core (~> 3.7.0)
66
+ rspec-expectations (~> 3.7.0)
67
+ rspec-mocks (~> 3.7.0)
68
+ rspec-core (3.7.1)
69
+ rspec-support (~> 3.7.0)
70
+ rspec-expectations (3.7.0)
71
+ diff-lcs (>= 1.2.0, < 2.0)
72
+ rspec-support (~> 3.7.0)
73
+ rspec-mocks (3.7.0)
74
+ diff-lcs (>= 1.2.0, < 2.0)
75
+ rspec-support (~> 3.7.0)
76
+ rspec-support (3.7.1)
77
+ rubocop (0.55.0)
78
+ parallel (~> 1.10)
79
+ parser (>= 2.5)
80
+ powerpack (~> 0.1)
81
+ rainbow (>= 2.2.2, < 4.0)
82
+ ruby-progressbar (~> 1.7)
83
+ unicode-display_width (~> 1.0, >= 1.0.1)
84
+ ruby-progressbar (1.9.0)
85
+ signet (0.8.1)
86
+ addressable (~> 2.3)
87
+ faraday (~> 0.9)
88
+ jwt (>= 1.5, < 3.0)
89
+ multi_json (~> 1.10)
90
+ thread_safe (0.3.6)
91
+ tzinfo (1.2.5)
92
+ thread_safe (~> 0.1)
93
+ unicode-display_width (1.3.2)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ activerecord
100
+ bundler
101
+ grpcx!
102
+ rake
103
+ rspec
104
+ rubocop
105
+
106
+ BUNDLED WITH
107
+ 1.16.1
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # grpcx
2
+
3
+ Ruby gRPC extensions/helpers
4
+
5
+
6
+ # Grpcx::Server
7
+
8
+ Mixin for `GRPC::RpcServer`:
9
+
10
+ - handles [GRPC health checks](https://github.com/grpc/grpc/blob/master/doc/health-checking.md) requests
11
+ - handles `ActiveRecord` connection (auto-connect + pooling)
12
+ - instruments each request with `ActiveSupport::Notifications` (available as `process_action.grpc`, includes `action: METHOD_NAME` data)
13
+ - includes `ActiveSupport::Rescuable` and transforms most common `ActiveRecord::ActiveRecordError`-s into `GRPC::BadStatus` ones
14
+
15
+
16
+ Example:
17
+
18
+ ```ruby
19
+ require 'grpcx/server' # or just 'grpcx'
20
+
21
+ class MyServer < GRPC::RpcServer
22
+ include Grpcx::Server
23
+
24
+ # optional custom error handling:
25
+ rescue_from 'MyError' do |e|
26
+ raise Grpc::BadStatus.new(e.to_s, my_extra: e.my_extra)
27
+ end
28
+ end
29
+
30
+ # proceed as with usual GRPC::RpcServer:
31
+ server = MyServer.new(...)
32
+ server.handle(MyService.new)
33
+ server.add_http2_port '127.0.0.1:8080', :this_port_is_insecure
34
+ server.run_till_terminated
35
+ ```
36
+
37
+ Recommended to be used with [Grpclb::Server](https://github.com/bsm/grpclb/tree/master/ruby):
38
+
39
+ ```ruby
40
+ require 'grpclb/server'
41
+ require 'grpcx/server'
42
+
43
+ class MyServer < Grpclb::Server
44
+ include Grpcx::Server
45
+ end
46
+
47
+ ...
48
+ ```
49
+
50
+
51
+ ## Using with [Datadog::Notifications](https://github.com/bsm/datadog-notifications)
52
+
53
+ ```ruby
54
+ module Datadog::Notifications::Plugins
55
+ class GRPC < Base
56
+
57
+ def initialize(opts={})
58
+ super
59
+ Datadog::Notifications.subscribe 'process_action.grpc' do |reporter, event|
60
+ record(reporter, event)
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def record(reporter, event)
67
+ action = event.payload[:action]
68
+ status = event.payload[:exception] ? 'error' : 'ok'
69
+ tags = self.tags + ["rpc:#{action}", "status:#{status}"]
70
+
71
+ reporter.batch do
72
+ reporter.increment 'grpc.request', tags: tags
73
+ reporter.timing 'grpc.request.time', event.duration, tags: tags
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+ Datadog::Notifications.configure do |c|
81
+ c.use Datadog::Notifications::Plugins::GRPC
82
+ end if RUNNING_IN_PROD?
83
+ ```
84
+
85
+
86
+ ## Using with [Sentry](https://sentry.io/)/[Raven](https://github.com/getsentry/raven-ruby)
87
+
88
+ ```ruby
89
+ ActiveSupport::Notifications.subscribe('process_action.grpc') do |_name, _start, _finish, _id, payload|
90
+ e = payload[:exception_object]
91
+ next unless e
92
+
93
+ Raven.capture_exception(e)
94
+ end
95
+
96
+ Raven.configure do |config|
97
+ config.should_capture = proc {|e|
98
+ !e.is_a?(GRPC::BadStatus) # skip GRPC::BadStatus, but report everything else
99
+ }
100
+ end
101
+ ```
102
+
103
+ Similar approach can be used for logging.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+
4
+ require 'rubocop/rake_task'
5
+ RuboCop::RakeTask.new(:rubocop)
6
+
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ task default: %i[rubocop spec]
data/grpcx.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'grpcx'
3
+ s.version = '0.1.0'
4
+ s.authors = ['Black Square Media Ltd']
5
+ s.email = ['info@blacksquaremedia.com']
6
+ s.summary = %(gRPC extensions/helpers)
7
+ s.description = %()
8
+ s.homepage = 'https://bitbucket.org/bsm/grpcx'
9
+ s.license = 'MIT'
10
+
11
+ s.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^spec/}) }
12
+ s.test_files = `git ls-files -z -- spec/*`.split("\x0")
13
+ s.require_paths = ['lib']
14
+ s.required_ruby_version = '>= 2.2'
15
+
16
+ s.add_dependency 'activesupport', '>= 5.0'
17
+ s.add_dependency 'grpc', '>= 1.8.0'
18
+
19
+ s.add_development_dependency 'activerecord'
20
+ s.add_development_dependency 'bundler'
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'rubocop'
24
+ end
@@ -0,0 +1,37 @@
1
+ module Grpcx
2
+ module Server
3
+ module Interceptors
4
+ # Manages ActiveRecord::Base connection,
5
+ # making sure that connection is established before each request
6
+ # and re-pooling connections when request is processed.
7
+ class ActiveRecord < GRPC::ServerInterceptor
8
+
9
+ def request_response(*, &block)
10
+ wrap(&block)
11
+ end
12
+
13
+ def client_streamer(*, &block)
14
+ wrap(&block)
15
+ end
16
+
17
+ def server_streamer(*, &block)
18
+ wrap(&block)
19
+ end
20
+
21
+ def bidi_streamer(*, &block)
22
+ wrap(&block)
23
+ end
24
+
25
+ private
26
+
27
+ def wrap
28
+ ::ActiveRecord::Base.establish_connection unless ::ActiveRecord::Base.connection.active?
29
+ yield
30
+ ensure
31
+ ::ActiveRecord::Base.clear_active_connections!
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ require 'active_support/notifications'
2
+
3
+ module Grpcx
4
+ module Server
5
+ module Interceptors
6
+ class Instrumentation < GRPC::ServerInterceptor
7
+ METRIC_NAME = 'process_action.grpc'.freeze
8
+
9
+ def request_response(method: nil, &block)
10
+ instrument(action: method, &block)
11
+ end
12
+
13
+ def client_streamer(method: nil, &block)
14
+ instrument(action: method, &block)
15
+ end
16
+
17
+ def server_streamer(method: nil, &block)
18
+ instrument(action: method, &block)
19
+ end
20
+
21
+ def bidi_streamer(method: nil, &block)
22
+ instrument(action: method, &block)
23
+ end
24
+
25
+ private
26
+
27
+ def instrument(opts={}, &block)
28
+ ActiveSupport::Notifications.instrument(METRIC_NAME, opts, &block)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ module Grpcx
2
+ module Server
3
+ module Interceptors
4
+ class Rescue < GRPC::ServerInterceptor
5
+ def initialize(rescuable, opts={})
6
+ @rescuable = rescuable
7
+ super(opts)
8
+ end
9
+
10
+ def request_response(*)
11
+ yield
12
+ rescue StandardError => err
13
+ @rescuable.rescue_with_handler(err) || raise
14
+ end
15
+
16
+ def client_streamer(*)
17
+ yield
18
+ rescue StandardError => err
19
+ @rescuable.rescue_with_handler(err) || raise
20
+ end
21
+
22
+ def server_streamer(*)
23
+ yield
24
+ rescue StandardError => err
25
+ @rescuable.rescue_with_handler(err) || raise
26
+ end
27
+
28
+ def bidi_streamer(*)
29
+ yield
30
+ rescue StandardError => err
31
+ @rescuable.rescue_with_handler(err) || raise
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ require 'grpcx/server/interceptors/rescue'
2
+ require 'grpcx/server/interceptors/instrumentation'
3
+ require 'grpcx/server/interceptors/active_record'
@@ -0,0 +1,56 @@
1
+ require 'grpc'
2
+ require 'grpc/health/checker'
3
+ require 'active_support/concern'
4
+ require 'active_support/rescuable'
5
+ require 'grpcx/server/interceptors'
6
+
7
+ module Grpcx
8
+ module Server
9
+ extend ActiveSupport::Concern
10
+ include ActiveSupport::Rescuable
11
+
12
+ ServingStatus = ::Grpc::Health::Checker::HealthCheckResponse::ServingStatus
13
+
14
+ included do
15
+ attr_reader :interceptors
16
+
17
+ rescue_from 'ActiveRecord::RecordInvalid' do |e|
18
+ raise GRPC::InvalidArgument.new('record invalid', errors: e.record.errors.to_h)
19
+ end
20
+ rescue_from 'ActiveRecord::RecordNotFound' do |e|
21
+ raise GRPC::NotFound.new('record not found', id: e.id, model: e.model.to_s)
22
+ end
23
+ end
24
+
25
+ def initialize(opts={})
26
+ opts[:pool_size] ||= ENV['GRPC_SERVER_THREADS'].to_i if ENV['GRPC_SERVER_THREADS']
27
+ opts[:max_waiting_requests] ||= ENV['GRPC_SERVER_QUEUE'].to_i if ENV['GRPC_SERVER_QUEUE']
28
+
29
+ # interceptors are fired in FIFO order.
30
+ opts[:interceptors] ||= []
31
+ opts[:interceptors].prepend Grpcx::Server::Interceptors::Rescue.new(self)
32
+ opts[:interceptors].prepend Grpcx::Server::Interceptors::Instrumentation.new
33
+ opts[:interceptors].prepend Grpcx::Server::Interceptors::ActiveRecord.new if defined?(::ActiveRecord)
34
+
35
+ super(opts).tap do
36
+ handle(health)
37
+ end
38
+ end
39
+
40
+ def handle(service)
41
+ service_name = nil
42
+ if service.is_a?(Class) && service < GRPC::GenericService
43
+ service_name = service.service_name
44
+ elsif service.is_a?(GRPC::GenericService)
45
+ service_name = service.class.service_name
46
+ end
47
+
48
+ health.add_status(service_name, ServingStatus::SERVING) if service_name
49
+ super
50
+ end
51
+
52
+ def health
53
+ @health ||= ::Grpc::Health::Checker.new
54
+ end
55
+ end
56
+ end
data/lib/grpcx.rb ADDED
@@ -0,0 +1 @@
1
+ require 'grpcx/server'
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Grpcx::Server do
4
+
5
+ subject do
6
+ s = Grpcx::Spec::Server.new
7
+ s.handle Grpcx::Spec::Service::V1
8
+ s
9
+ end
10
+
11
+ it 'should have a health-check' do
12
+ expect(subject.health).to be_a(Grpc::Health::Checker)
13
+ expect(subject.health.instance_variable_get(:@statuses)).to eq(
14
+ 'grpcx.spec.service.V1' => 1,
15
+ 'grpc.health.v1.Health' => 1,
16
+ )
17
+ end
18
+
19
+ it 'should have interceptors' do
20
+ expect(subject.interceptors).to be_a(GRPC::InterceptorRegistry)
21
+
22
+ registered = subject.interceptors.instance_variable_get(:@interceptors)
23
+ expect(registered.size).to eq(3)
24
+ end
25
+
26
+ it 'should have rescue handlers' do
27
+ expect(subject.rescue_handlers.size).to eq(3)
28
+ expect(subject.rescue_handlers.map(&:first)).to match_array %w[
29
+ ActiveRecord::RecordInvalid
30
+ ActiveRecord::RecordNotFound
31
+ ArgumentError
32
+ ]
33
+ end
34
+
35
+ end
@@ -0,0 +1,45 @@
1
+ require 'rspec'
2
+ require 'grpcx'
3
+ require 'active_record'
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "grpcx.spec.Message" do
8
+ optional :name, :string, 1
9
+ end
10
+ add_enum "grpcx.spec.Enum" do
11
+ value :V0, 0
12
+ value :V1, 1
13
+ value :V2, 2
14
+ end
15
+ add_message "grpcx.spec.GetMessageRequest" do
16
+ end
17
+ end
18
+
19
+ module Grpcx::Spec
20
+ Message = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.Message").msgclass
21
+ Enum = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.Enum").enummodule
22
+ GetMessageRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.GetMessageRequest").msgclass
23
+
24
+ module Service
25
+ class V1
26
+ include GRPC::GenericService
27
+
28
+ self.marshal_class_method = :encode
29
+ self.unmarshal_class_method = :decode
30
+ self.service_name = 'grpcx.spec.service.V1'
31
+
32
+ rpc :GetMessage, GetMessageRequest, Message
33
+ end
34
+
35
+ Stub = V1.rpc_stub_class
36
+ end
37
+
38
+ class Server < GRPC::RpcServer
39
+ include Grpcx::Server
40
+
41
+ rescue_from 'ArgumentError' do |e|
42
+ raise GRPC::InvalidArgument.new(errors: e.to_s)
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grpcx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Black Square Media Ltd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: grpc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: ''
112
+ email:
113
+ - info@blacksquaremedia.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".editorconfig"
119
+ - ".gitignore"
120
+ - ".rubocop.yml"
121
+ - Gemfile
122
+ - Gemfile.lock
123
+ - README.md
124
+ - Rakefile
125
+ - grpcx.gemspec
126
+ - lib/grpcx.rb
127
+ - lib/grpcx/server.rb
128
+ - lib/grpcx/server/interceptors.rb
129
+ - lib/grpcx/server/interceptors/active_record.rb
130
+ - lib/grpcx/server/interceptors/instrumentation.rb
131
+ - lib/grpcx/server/interceptors/rescue.rb
132
+ - spec/lib/server_spec.rb
133
+ - spec/spec_helper.rb
134
+ homepage: https://bitbucket.org/bsm/grpcx
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '2.2'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.7.3
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: gRPC extensions/helpers
158
+ test_files:
159
+ - spec/lib/server_spec.rb
160
+ - spec/spec_helper.rb