grpc 1.30.2-x86-linux

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/etc/roots.pem +4644 -0
  3. data/grpc_c.32.ruby +0 -0
  4. data/grpc_c.64.ruby +0 -0
  5. data/src/ruby/bin/math_client.rb +140 -0
  6. data/src/ruby/bin/math_pb.rb +34 -0
  7. data/src/ruby/bin/math_server.rb +191 -0
  8. data/src/ruby/bin/math_services_pb.rb +51 -0
  9. data/src/ruby/bin/noproto_client.rb +93 -0
  10. data/src/ruby/bin/noproto_server.rb +97 -0
  11. data/src/ruby/ext/grpc/ext-export.clang +1 -0
  12. data/src/ruby/ext/grpc/ext-export.gcc +6 -0
  13. data/src/ruby/ext/grpc/extconf.rb +107 -0
  14. data/src/ruby/ext/grpc/rb_byte_buffer.c +64 -0
  15. data/src/ruby/ext/grpc/rb_byte_buffer.h +35 -0
  16. data/src/ruby/ext/grpc/rb_call.c +1050 -0
  17. data/src/ruby/ext/grpc/rb_call.h +53 -0
  18. data/src/ruby/ext/grpc/rb_call_credentials.c +297 -0
  19. data/src/ruby/ext/grpc/rb_call_credentials.h +31 -0
  20. data/src/ruby/ext/grpc/rb_channel.c +835 -0
  21. data/src/ruby/ext/grpc/rb_channel.h +34 -0
  22. data/src/ruby/ext/grpc/rb_channel_args.c +155 -0
  23. data/src/ruby/ext/grpc/rb_channel_args.h +38 -0
  24. data/src/ruby/ext/grpc/rb_channel_credentials.c +267 -0
  25. data/src/ruby/ext/grpc/rb_channel_credentials.h +32 -0
  26. data/src/ruby/ext/grpc/rb_completion_queue.c +100 -0
  27. data/src/ruby/ext/grpc/rb_completion_queue.h +36 -0
  28. data/src/ruby/ext/grpc/rb_compression_options.c +470 -0
  29. data/src/ruby/ext/grpc/rb_compression_options.h +29 -0
  30. data/src/ruby/ext/grpc/rb_enable_cpp.cc +22 -0
  31. data/src/ruby/ext/grpc/rb_event_thread.c +143 -0
  32. data/src/ruby/ext/grpc/rb_event_thread.h +21 -0
  33. data/src/ruby/ext/grpc/rb_grpc.c +328 -0
  34. data/src/ruby/ext/grpc/rb_grpc.h +76 -0
  35. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +573 -0
  36. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +865 -0
  37. data/src/ruby/ext/grpc/rb_loader.c +57 -0
  38. data/src/ruby/ext/grpc/rb_loader.h +25 -0
  39. data/src/ruby/ext/grpc/rb_server.c +372 -0
  40. data/src/ruby/ext/grpc/rb_server.h +32 -0
  41. data/src/ruby/ext/grpc/rb_server_credentials.c +243 -0
  42. data/src/ruby/ext/grpc/rb_server_credentials.h +32 -0
  43. data/src/ruby/lib/grpc.rb +37 -0
  44. data/src/ruby/lib/grpc/2.3/grpc_c.so +0 -0
  45. data/src/ruby/lib/grpc/2.4/grpc_c.so +0 -0
  46. data/src/ruby/lib/grpc/2.5/grpc_c.so +0 -0
  47. data/src/ruby/lib/grpc/2.6/grpc_c.so +0 -0
  48. data/src/ruby/lib/grpc/2.7/grpc_c.so +0 -0
  49. data/src/ruby/lib/grpc/core/status_codes.rb +135 -0
  50. data/src/ruby/lib/grpc/core/time_consts.rb +56 -0
  51. data/src/ruby/lib/grpc/errors.rb +277 -0
  52. data/src/ruby/lib/grpc/generic/active_call.rb +669 -0
  53. data/src/ruby/lib/grpc/generic/bidi_call.rb +233 -0
  54. data/src/ruby/lib/grpc/generic/client_stub.rb +501 -0
  55. data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
  56. data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
  57. data/src/ruby/lib/grpc/generic/rpc_desc.rb +204 -0
  58. data/src/ruby/lib/grpc/generic/rpc_server.rb +551 -0
  59. data/src/ruby/lib/grpc/generic/service.rb +211 -0
  60. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +40 -0
  61. data/src/ruby/lib/grpc/grpc.rb +24 -0
  62. data/src/ruby/lib/grpc/logconfig.rb +44 -0
  63. data/src/ruby/lib/grpc/notifier.rb +45 -0
  64. data/src/ruby/lib/grpc/structs.rb +15 -0
  65. data/src/ruby/lib/grpc/version.rb +18 -0
  66. data/src/ruby/pb/README.md +42 -0
  67. data/src/ruby/pb/generate_proto_ruby.sh +51 -0
  68. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  69. data/src/ruby/pb/grpc/health/v1/health_pb.rb +31 -0
  70. data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +62 -0
  71. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +44 -0
  72. data/src/ruby/pb/grpc/testing/metrics_pb.rb +28 -0
  73. data/src/ruby/pb/grpc/testing/metrics_services_pb.rb +49 -0
  74. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +17 -0
  75. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +105 -0
  76. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +16 -0
  77. data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +118 -0
  78. data/src/ruby/pb/test/client.rb +769 -0
  79. data/src/ruby/pb/test/server.rb +252 -0
  80. data/src/ruby/pb/test/xds_client.rb +213 -0
  81. data/src/ruby/spec/call_credentials_spec.rb +42 -0
  82. data/src/ruby/spec/call_spec.rb +180 -0
  83. data/src/ruby/spec/channel_connection_spec.rb +126 -0
  84. data/src/ruby/spec/channel_credentials_spec.rb +82 -0
  85. data/src/ruby/spec/channel_spec.rb +234 -0
  86. data/src/ruby/spec/client_auth_spec.rb +126 -0
  87. data/src/ruby/spec/client_server_spec.rb +664 -0
  88. data/src/ruby/spec/compression_options_spec.rb +149 -0
  89. data/src/ruby/spec/debug_message_spec.rb +134 -0
  90. data/src/ruby/spec/error_sanity_spec.rb +49 -0
  91. data/src/ruby/spec/errors_spec.rb +142 -0
  92. data/src/ruby/spec/generic/active_call_spec.rb +672 -0
  93. data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
  94. data/src/ruby/spec/generic/client_stub_spec.rb +1083 -0
  95. data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
  96. data/src/ruby/spec/generic/rpc_desc_spec.rb +374 -0
  97. data/src/ruby/spec/generic/rpc_server_pool_spec.rb +127 -0
  98. data/src/ruby/spec/generic/rpc_server_spec.rb +748 -0
  99. data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
  100. data/src/ruby/spec/generic/service_spec.rb +263 -0
  101. data/src/ruby/spec/google_rpc_status_utils_spec.rb +282 -0
  102. data/src/ruby/spec/pb/codegen/grpc/testing/package_options.proto +28 -0
  103. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import.proto +22 -0
  104. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import2.proto +23 -0
  105. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +41 -0
  106. data/src/ruby/spec/pb/codegen/package_option_spec.rb +82 -0
  107. data/src/ruby/spec/pb/duplicate/codegen_spec.rb +57 -0
  108. data/src/ruby/spec/pb/health/checker_spec.rb +236 -0
  109. data/src/ruby/spec/server_credentials_spec.rb +79 -0
  110. data/src/ruby/spec/server_spec.rb +209 -0
  111. data/src/ruby/spec/spec_helper.rb +61 -0
  112. data/src/ruby/spec/support/helpers.rb +107 -0
  113. data/src/ruby/spec/support/services.rb +160 -0
  114. data/src/ruby/spec/testdata/README +1 -0
  115. data/src/ruby/spec/testdata/ca.pem +20 -0
  116. data/src/ruby/spec/testdata/client.key +28 -0
  117. data/src/ruby/spec/testdata/client.pem +20 -0
  118. data/src/ruby/spec/testdata/server1.key +28 -0
  119. data/src/ruby/spec/testdata/server1.pem +22 -0
  120. data/src/ruby/spec/time_consts_spec.rb +74 -0
  121. metadata +394 -0
@@ -0,0 +1,233 @@
1
+ # Copyright 2015 gRPC authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'forwardable'
16
+ require_relative '../grpc'
17
+
18
+ # GRPC contains the General RPC module.
19
+ module GRPC
20
+ # The BiDiCall class orchestrates execution of a BiDi stream on a client or
21
+ # server.
22
+ class BidiCall
23
+ include Core::CallOps
24
+ include Core::StatusCodes
25
+ include Core::TimeConsts
26
+
27
+ # Creates a BidiCall.
28
+ #
29
+ # BidiCall should only be created after a call is accepted. That means
30
+ # different things on a client and a server. On the client, the call is
31
+ # accepted after call.invoke. On the server, this is after call.accept.
32
+ #
33
+ # #initialize cannot determine if the call is accepted or not; so if a
34
+ # call that's not accepted is used here, the error won't be visible until
35
+ # the BidiCall#run is called.
36
+ #
37
+ # deadline is the absolute deadline for the call.
38
+ #
39
+ # @param call [Call] the call used by the ActiveCall
40
+ # @param marshal [Function] f(obj)->string that marshal requests
41
+ # @param unmarshal [Function] f(string)->obj that unmarshals responses
42
+ # @param metadata_received [true|false] indicates if metadata has already
43
+ # been received. Should always be true for server calls
44
+ def initialize(call, marshal, unmarshal, metadata_received: false,
45
+ req_view: nil)
46
+ fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
47
+ @call = call
48
+ @marshal = marshal
49
+ @op_notifier = nil # signals completion on clients
50
+ @unmarshal = unmarshal
51
+ @metadata_received = metadata_received
52
+ @reads_complete = false
53
+ @writes_complete = false
54
+ @complete = false
55
+ @done_mutex = Mutex.new
56
+ @req_view = req_view
57
+ end
58
+
59
+ # Begins orchestration of the Bidi stream for a client sending requests.
60
+ #
61
+ # The method either returns an Enumerator of the responses, or accepts a
62
+ # block that can be invoked with each response.
63
+ #
64
+ # @param requests the Enumerable of requests to send
65
+ # @param set_input_stream_done [Proc] called back when we're done
66
+ # reading the input stream
67
+ # @param set_output_stream_done [Proc] called back when we're done
68
+ # sending data on the output stream
69
+ # @return an Enumerator of requests to yield
70
+ def run_on_client(requests,
71
+ set_input_stream_done,
72
+ set_output_stream_done,
73
+ &blk)
74
+ @enq_th = Thread.new do
75
+ write_loop(requests, set_output_stream_done: set_output_stream_done)
76
+ end
77
+ read_loop(set_input_stream_done, &blk)
78
+ end
79
+
80
+ # Begins orchestration of the Bidi stream for a server generating replies.
81
+ #
82
+ # N.B. gen_each_reply is a func(Enumerable<Requests>)
83
+ #
84
+ # It takes an enumerable of requests as an arg, in case there is a
85
+ # relationship between the stream of requests and the stream of replies.
86
+ #
87
+ # This does not mean that must necessarily be one. E.g, the replies
88
+ # produced by gen_each_reply could ignore the received_msgs
89
+ #
90
+ # @param [Proc] gen_each_reply generates the BiDi stream replies.
91
+ # @param [Enumerable] requests The enumerable of requests to run
92
+ def run_on_server(gen_each_reply, requests)
93
+ replies = nil
94
+
95
+ # Pass in the optional call object parameter if possible
96
+ if gen_each_reply.arity == 1
97
+ replies = gen_each_reply.call(requests)
98
+ elsif gen_each_reply.arity == 2
99
+ replies = gen_each_reply.call(requests, @req_view)
100
+ else
101
+ fail 'Illegal arity of reply generator'
102
+ end
103
+
104
+ write_loop(replies, is_client: false)
105
+ end
106
+
107
+ ##
108
+ # Read the next stream iteration
109
+ #
110
+ # @param [Proc] finalize_stream callback to call when the reads have been
111
+ # completely read through.
112
+ # @param [Boolean] is_client If this is a client or server request
113
+ #
114
+ def read_next_loop(finalize_stream, is_client = false)
115
+ read_loop(finalize_stream, is_client: is_client)
116
+ end
117
+
118
+ private
119
+
120
+ END_OF_READS = :end_of_reads
121
+ END_OF_WRITES = :end_of_writes
122
+
123
+ # performs a read using @call.run_batch, ensures metadata is set up
124
+ def read_using_run_batch
125
+ ops = { RECV_MESSAGE => nil }
126
+ ops[RECV_INITIAL_METADATA] = nil unless @metadata_received
127
+ begin
128
+ batch_result = @call.run_batch(ops)
129
+ unless @metadata_received
130
+ @call.metadata = batch_result.metadata
131
+ @metadata_received = true
132
+ end
133
+ batch_result
134
+ rescue GRPC::Core::CallError => e
135
+ GRPC.logger.warn('bidi call: read_using_run_batch failed')
136
+ GRPC.logger.warn(e)
137
+ nil
138
+ end
139
+ end
140
+
141
+ # set_output_stream_done is relevant on client-side
142
+ def write_loop(requests, is_client: true, set_output_stream_done: nil)
143
+ GRPC.logger.debug('bidi-write-loop: starting')
144
+ count = 0
145
+ requests.each do |req|
146
+ GRPC.logger.debug("bidi-write-loop: #{count}")
147
+ count += 1
148
+ payload = @marshal.call(req)
149
+ # Fails if status already received
150
+ begin
151
+ @req_view.send_initial_metadata unless @req_view.nil?
152
+ @call.run_batch(SEND_MESSAGE => payload)
153
+ rescue GRPC::Core::CallError => e
154
+ # This is almost definitely caused by a status arriving while still
155
+ # writing. Don't re-throw the error
156
+ GRPC.logger.warn('bidi-write-loop: ended with error')
157
+ GRPC.logger.warn(e)
158
+ break
159
+ end
160
+ end
161
+ GRPC.logger.debug("bidi-write-loop: #{count} writes done")
162
+ if is_client
163
+ GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
164
+ begin
165
+ @call.run_batch(SEND_CLOSE_FROM_CLIENT => nil)
166
+ rescue GRPC::Core::CallError => e
167
+ GRPC.logger.warn('bidi-write-loop: send close failed')
168
+ GRPC.logger.warn(e)
169
+ end
170
+ GRPC.logger.debug('bidi-write-loop: done')
171
+ end
172
+ GRPC.logger.debug('bidi-write-loop: finished')
173
+ rescue StandardError => e
174
+ GRPC.logger.warn('bidi-write-loop: failed')
175
+ GRPC.logger.warn(e)
176
+ if is_client
177
+ @call.cancel_with_status(GRPC::Core::StatusCodes::UNKNOWN,
178
+ "GRPC bidi call error: #{e.inspect}")
179
+ else
180
+ raise e
181
+ end
182
+ ensure
183
+ set_output_stream_done.call if is_client
184
+ end
185
+
186
+ # Provides an enumerator that yields results of remote reads
187
+ def read_loop(set_input_stream_done, is_client: true)
188
+ return enum_for(:read_loop,
189
+ set_input_stream_done,
190
+ is_client: is_client) unless block_given?
191
+ GRPC.logger.debug('bidi-read-loop: starting')
192
+ begin
193
+ count = 0
194
+ # queue the initial read before beginning the loop
195
+ loop do
196
+ GRPC.logger.debug("bidi-read-loop: #{count}")
197
+ count += 1
198
+ batch_result = read_using_run_batch
199
+
200
+ # handle the next message
201
+ if batch_result.nil? || batch_result.message.nil?
202
+ GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
203
+
204
+ if is_client
205
+ batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
206
+ @call.status = batch_result.status
207
+ @call.trailing_metadata = @call.status.metadata if @call.status
208
+ GRPC.logger.debug("bidi-read-loop: done status #{@call.status}")
209
+ batch_result.check_status
210
+ end
211
+
212
+ GRPC.logger.debug('bidi-read-loop: done reading!')
213
+ break
214
+ end
215
+
216
+ res = @unmarshal.call(batch_result.message)
217
+ yield res
218
+ end
219
+ rescue StandardError => e
220
+ GRPC.logger.warn('bidi: read-loop failed')
221
+ GRPC.logger.warn(e)
222
+ raise e
223
+ ensure
224
+ set_input_stream_done.call
225
+ end
226
+ GRPC.logger.debug('bidi-read-loop: finished')
227
+ # Make sure that the write loop is done before finishing the call.
228
+ # Note that blocking is ok at this point because we've already received
229
+ # a status
230
+ @enq_th.join if is_client
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,501 @@
1
+ # Copyright 2015 gRPC authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative 'active_call'
16
+ require_relative '../version'
17
+
18
+ # GRPC contains the General RPC module.
19
+ module GRPC
20
+ # rubocop:disable Metrics/ParameterLists
21
+
22
+ # ClientStub represents a client connection to a gRPC server, and can be used
23
+ # to send requests.
24
+ class ClientStub
25
+ include Core::StatusCodes
26
+ include Core::TimeConsts
27
+
28
+ # Default timeout is infinity.
29
+ DEFAULT_TIMEOUT = INFINITE_FUTURE
30
+
31
+ # setup_channel is used by #initialize to constuct a channel from its
32
+ # arguments.
33
+ def self.setup_channel(alt_chan, host, creds, channel_args = {})
34
+ unless alt_chan.nil?
35
+ fail(TypeError, '!Channel') unless alt_chan.is_a?(Core::Channel)
36
+ return alt_chan
37
+ end
38
+ if channel_args['grpc.primary_user_agent'].nil?
39
+ channel_args['grpc.primary_user_agent'] = ''
40
+ else
41
+ channel_args['grpc.primary_user_agent'] += ' '
42
+ end
43
+ channel_args['grpc.primary_user_agent'] += "grpc-ruby/#{VERSION}"
44
+ unless creds.is_a?(Core::ChannelCredentials) || creds.is_a?(Symbol)
45
+ fail(TypeError, '!ChannelCredentials or Symbol')
46
+ end
47
+ Core::Channel.new(host, channel_args, creds)
48
+ end
49
+
50
+ # Allows users of the stub to modify the propagate mask.
51
+ #
52
+ # This is an advanced feature for use when making calls to another gRPC
53
+ # server whilst running in the handler of an existing one.
54
+ attr_writer :propagate_mask
55
+
56
+ # Creates a new ClientStub.
57
+ #
58
+ # Minimally, a stub is created with the just the host of the gRPC service
59
+ # it wishes to access, e.g.,
60
+ #
61
+ # my_stub = ClientStub.new(example.host.com:50505,
62
+ # :this_channel_is_insecure)
63
+ #
64
+ # If a channel_override argument is passed, it will be used as the
65
+ # underlying channel. Otherwise, the channel_args argument will be used
66
+ # to construct a new underlying channel.
67
+ #
68
+ # There are some specific keyword args that are not used to configure the
69
+ # channel:
70
+ #
71
+ # - :channel_override
72
+ # when present, this must be a pre-created GRPC::Core::Channel. If it's
73
+ # present the host and arbitrary keyword arg areignored, and the RPC
74
+ # connection uses this channel.
75
+ #
76
+ # - :timeout
77
+ # when present, this is the default timeout used for calls
78
+ #
79
+ # @param host [String] the host the stub connects to
80
+ # @param creds [Core::ChannelCredentials|Symbol] the channel credentials, or
81
+ # :this_channel_is_insecure, which explicitly indicates that the client
82
+ # should be created with an insecure connection. Note: this argument is
83
+ # ignored if the channel_override argument is provided.
84
+ # @param channel_override [Core::Channel] a pre-created channel
85
+ # @param timeout [Number] the default timeout to use in requests
86
+ # @param propagate_mask [Number] A bitwise combination of flags in
87
+ # GRPC::Core::PropagateMasks. Indicates how data should be propagated
88
+ # from parent server calls to child client calls if this client is being
89
+ # used within a gRPC server.
90
+ # @param channel_args [Hash] the channel arguments. Note: this argument is
91
+ # ignored if the channel_override argument is provided.
92
+ # @param interceptors [Array<GRPC::ClientInterceptor>] An array of
93
+ # GRPC::ClientInterceptor objects that will be used for
94
+ # intercepting calls before they are executed
95
+ # Interceptors are an EXPERIMENTAL API.
96
+ def initialize(host, creds,
97
+ channel_override: nil,
98
+ timeout: nil,
99
+ propagate_mask: nil,
100
+ channel_args: {},
101
+ interceptors: [])
102
+ @ch = ClientStub.setup_channel(channel_override, host, creds,
103
+ channel_args)
104
+ alt_host = channel_args[Core::Channel::SSL_TARGET]
105
+ @host = alt_host.nil? ? host : alt_host
106
+ @propagate_mask = propagate_mask
107
+ @timeout = timeout.nil? ? DEFAULT_TIMEOUT : timeout
108
+ @interceptors = InterceptorRegistry.new(interceptors)
109
+ end
110
+
111
+ # request_response sends a request to a GRPC server, and returns the
112
+ # response.
113
+ #
114
+ # == Flow Control ==
115
+ # This is a blocking call.
116
+ #
117
+ # * it does not return until a response is received.
118
+ #
119
+ # * the requests is sent only when GRPC core's flow control allows it to
120
+ # be sent.
121
+ #
122
+ # == Errors ==
123
+ # An RuntimeError is raised if
124
+ #
125
+ # * the server responds with a non-OK status
126
+ #
127
+ # * the deadline is exceeded
128
+ #
129
+ # == Return Value ==
130
+ #
131
+ # If return_op is false, the call returns the response
132
+ #
133
+ # If return_op is true, the call returns an Operation, calling execute
134
+ # on the Operation returns the response.
135
+ #
136
+ # @param method [String] the RPC method to call on the GRPC server
137
+ # @param req [Object] the request sent to the server
138
+ # @param marshal [Function] f(obj)->string that marshals requests
139
+ # @param unmarshal [Function] f(string)->obj that unmarshals responses
140
+ # @param deadline [Time] (optional) the time the request should complete
141
+ # @param return_op [true|false] return an Operation if true
142
+ # @param parent [Core::Call] a prior call whose reserved metadata
143
+ # will be propagated by this one.
144
+ # @param credentials [Core::CallCredentials] credentials to use when making
145
+ # the call
146
+ # @param metadata [Hash] metadata to be sent to the server
147
+ # @return [Object] the response received from the server
148
+ def request_response(method, req, marshal, unmarshal,
149
+ deadline: nil,
150
+ return_op: false,
151
+ parent: nil,
152
+ credentials: nil,
153
+ metadata: {})
154
+ c = new_active_call(method, marshal, unmarshal,
155
+ deadline: deadline,
156
+ parent: parent,
157
+ credentials: credentials)
158
+ interception_context = @interceptors.build_context
159
+ intercept_args = {
160
+ method: method,
161
+ request: req,
162
+ call: c.interceptable,
163
+ metadata: metadata
164
+ }
165
+ if return_op
166
+ # return the operation view of the active_call; define #execute as a
167
+ # new method for this instance that invokes #request_response.
168
+ c.merge_metadata_to_send(metadata)
169
+ op = c.operation
170
+ op.define_singleton_method(:execute) do
171
+ interception_context.intercept!(:request_response, intercept_args) do
172
+ c.request_response(req, metadata: metadata)
173
+ end
174
+ end
175
+ op
176
+ else
177
+ interception_context.intercept!(:request_response, intercept_args) do
178
+ c.request_response(req, metadata: metadata)
179
+ end
180
+ end
181
+ end
182
+
183
+ # client_streamer sends a stream of requests to a GRPC server, and
184
+ # returns a single response.
185
+ #
186
+ # requests provides an 'iterable' of Requests. I.e. it follows Ruby's
187
+ # #each enumeration protocol. In the simplest case, requests will be an
188
+ # array of marshallable objects; in typical case it will be an Enumerable
189
+ # that allows dynamic construction of the marshallable objects.
190
+ #
191
+ # == Flow Control ==
192
+ # This is a blocking call.
193
+ #
194
+ # * it does not return until a response is received.
195
+ #
196
+ # * each requests is sent only when GRPC core's flow control allows it to
197
+ # be sent.
198
+ #
199
+ # == Errors ==
200
+ # An RuntimeError is raised if
201
+ #
202
+ # * the server responds with a non-OK status
203
+ #
204
+ # * the deadline is exceeded
205
+ #
206
+ # == Return Value ==
207
+ #
208
+ # If return_op is false, the call consumes the requests and returns
209
+ # the response.
210
+ #
211
+ # If return_op is true, the call returns the response.
212
+ #
213
+ # @param method [String] the RPC method to call on the GRPC server
214
+ # @param requests [Object] an Enumerable of requests to send
215
+ # @param marshal [Function] f(obj)->string that marshals requests
216
+ # @param unmarshal [Function] f(string)->obj that unmarshals responses
217
+ # @param deadline [Time] (optional) the time the request should complete
218
+ # @param return_op [true|false] return an Operation if true
219
+ # @param parent [Core::Call] a prior call whose reserved metadata
220
+ # will be propagated by this one.
221
+ # @param credentials [Core::CallCredentials] credentials to use when making
222
+ # the call
223
+ # @param metadata [Hash] metadata to be sent to the server
224
+ # @return [Object|Operation] the response received from the server
225
+ def client_streamer(method, requests, marshal, unmarshal,
226
+ deadline: nil,
227
+ return_op: false,
228
+ parent: nil,
229
+ credentials: nil,
230
+ metadata: {})
231
+ c = new_active_call(method, marshal, unmarshal,
232
+ deadline: deadline,
233
+ parent: parent,
234
+ credentials: credentials)
235
+ interception_context = @interceptors.build_context
236
+ intercept_args = {
237
+ method: method,
238
+ requests: requests,
239
+ call: c.interceptable,
240
+ metadata: metadata
241
+ }
242
+ if return_op
243
+ # return the operation view of the active_call; define #execute as a
244
+ # new method for this instance that invokes #client_streamer.
245
+ c.merge_metadata_to_send(metadata)
246
+ op = c.operation
247
+ op.define_singleton_method(:execute) do
248
+ interception_context.intercept!(:client_streamer, intercept_args) do
249
+ c.client_streamer(requests)
250
+ end
251
+ end
252
+ op
253
+ else
254
+ interception_context.intercept!(:client_streamer, intercept_args) do
255
+ c.client_streamer(requests, metadata: metadata)
256
+ end
257
+ end
258
+ end
259
+
260
+ # server_streamer sends one request to the GRPC server, which yields a
261
+ # stream of responses.
262
+ #
263
+ # responses provides an enumerator over the streamed responses, i.e. it
264
+ # follows Ruby's #each iteration protocol. The enumerator blocks while
265
+ # waiting for each response, stops when the server signals that no
266
+ # further responses will be supplied. If the implicit block is provided,
267
+ # it is executed with each response as the argument and no result is
268
+ # returned.
269
+ #
270
+ # == Flow Control ==
271
+ # This is a blocking call.
272
+ #
273
+ # * the request is sent only when GRPC core's flow control allows it to
274
+ # be sent.
275
+ #
276
+ # * the request will not complete until the server sends the final
277
+ # response followed by a status message.
278
+ #
279
+ # == Errors ==
280
+ # An RuntimeError is raised if
281
+ #
282
+ # * the server responds with a non-OK status when any response is
283
+ # * retrieved
284
+ #
285
+ # * the deadline is exceeded
286
+ #
287
+ # == Return Value ==
288
+ #
289
+ # if the return_op is false, the return value is an Enumerator of the
290
+ # results, unless a block is provided, in which case the block is
291
+ # executed with each response.
292
+ #
293
+ # if return_op is true, the function returns an Operation whose #execute
294
+ # method runs server streamer call. Again, Operation#execute either
295
+ # calls the given block with each response or returns an Enumerator of the
296
+ # responses.
297
+ #
298
+ # == Keyword Args ==
299
+ #
300
+ # Unspecified keyword arguments are treated as metadata to be sent to the
301
+ # server.
302
+ #
303
+ # @param method [String] the RPC method to call on the GRPC server
304
+ # @param req [Object] the request sent to the server
305
+ # @param marshal [Function] f(obj)->string that marshals requests
306
+ # @param unmarshal [Function] f(string)->obj that unmarshals responses
307
+ # @param deadline [Time] (optional) the time the request should complete
308
+ # @param return_op [true|false]return an Operation if true
309
+ # @param parent [Core::Call] a prior call whose reserved metadata
310
+ # will be propagated by this one.
311
+ # @param credentials [Core::CallCredentials] credentials to use when making
312
+ # the call
313
+ # @param metadata [Hash] metadata to be sent to the server
314
+ # @param blk [Block] when provided, is executed for each response
315
+ # @return [Enumerator|Operation|nil] as discussed above
316
+ def server_streamer(method, req, marshal, unmarshal,
317
+ deadline: nil,
318
+ return_op: false,
319
+ parent: nil,
320
+ credentials: nil,
321
+ metadata: {},
322
+ &blk)
323
+ c = new_active_call(method, marshal, unmarshal,
324
+ deadline: deadline,
325
+ parent: parent,
326
+ credentials: credentials)
327
+ interception_context = @interceptors.build_context
328
+ intercept_args = {
329
+ method: method,
330
+ request: req,
331
+ call: c.interceptable,
332
+ metadata: metadata
333
+ }
334
+ if return_op
335
+ # return the operation view of the active_call; define #execute
336
+ # as a new method for this instance that invokes #server_streamer
337
+ c.merge_metadata_to_send(metadata)
338
+ op = c.operation
339
+ op.define_singleton_method(:execute) do
340
+ interception_context.intercept!(:server_streamer, intercept_args) do
341
+ c.server_streamer(req, &blk)
342
+ end
343
+ end
344
+ op
345
+ else
346
+ interception_context.intercept!(:server_streamer, intercept_args) do
347
+ c.server_streamer(req, metadata: metadata, &blk)
348
+ end
349
+ end
350
+ end
351
+
352
+ # bidi_streamer sends a stream of requests to the GRPC server, and yields
353
+ # a stream of responses.
354
+ #
355
+ # This method takes an Enumerable of requests, and returns and enumerable
356
+ # of responses.
357
+ #
358
+ # == requests ==
359
+ #
360
+ # requests provides an 'iterable' of Requests. I.e. it follows Ruby's
361
+ # #each enumeration protocol. In the simplest case, requests will be an
362
+ # array of marshallable objects; in typical case it will be an
363
+ # Enumerable that allows dynamic construction of the marshallable
364
+ # objects.
365
+ #
366
+ # == responses ==
367
+ #
368
+ # This is an enumerator of responses. I.e, its #next method blocks
369
+ # waiting for the next response. Also, if at any point the block needs
370
+ # to consume all the remaining responses, this can be done using #each or
371
+ # #collect. Calling #each or #collect should only be done if
372
+ # the_call#writes_done has been called, otherwise the block will loop
373
+ # forever.
374
+ #
375
+ # == Flow Control ==
376
+ # This is a blocking call.
377
+ #
378
+ # * the call completes when the next call to provided block returns
379
+ # false
380
+ #
381
+ # * the execution block parameters are two objects for sending and
382
+ # receiving responses, each of which blocks waiting for flow control.
383
+ # E.g, calles to bidi_call#remote_send will wait until flow control
384
+ # allows another write before returning; and obviously calls to
385
+ # responses#next block until the next response is available.
386
+ #
387
+ # == Termination ==
388
+ #
389
+ # As well as sending and receiving messages, the block passed to the
390
+ # function is also responsible for:
391
+ #
392
+ # * calling bidi_call#writes_done to indicate no further reqs will be
393
+ # sent.
394
+ #
395
+ # * returning false if once the bidi stream is functionally completed.
396
+ #
397
+ # Note that response#next will indicate that there are no further
398
+ # responses by throwing StopIteration, but can only happen either
399
+ # if bidi_call#writes_done is called.
400
+ #
401
+ # To properly terminate the RPC, the responses should be completely iterated
402
+ # through; one way to do this is to loop on responses#next until no further
403
+ # responses are available.
404
+ #
405
+ # == Errors ==
406
+ # An RuntimeError is raised if
407
+ #
408
+ # * the server responds with a non-OK status when any response is
409
+ # * retrieved
410
+ #
411
+ # * the deadline is exceeded
412
+ #
413
+ #
414
+ # == Return Value ==
415
+ #
416
+ # if the return_op is false, the return value is an Enumerator of the
417
+ # results, unless a block is provided, in which case the block is
418
+ # executed with each response.
419
+ #
420
+ # if return_op is true, the function returns an Operation whose #execute
421
+ # method runs the Bidi call. Again, Operation#execute either calls a
422
+ # given block with each response or returns an Enumerator of the
423
+ # responses.
424
+ #
425
+ # @param method [String] the RPC method to call on the GRPC server
426
+ # @param requests [Object] an Enumerable of requests to send
427
+ # @param marshal [Function] f(obj)->string that marshals requests
428
+ # @param unmarshal [Function] f(string)->obj that unmarshals responses
429
+ # @param deadline [Time] (optional) the time the request should complete
430
+ # @param return_op [true|false] return an Operation if true
431
+ # @param parent [Core::Call] a prior call whose reserved metadata
432
+ # will be propagated by this one.
433
+ # @param credentials [Core::CallCredentials] credentials to use when making
434
+ # the call
435
+ # @param metadata [Hash] metadata to be sent to the server
436
+ # @param blk [Block] when provided, is executed for each response
437
+ # @return [Enumerator|nil|Operation] as discussed above
438
+ def bidi_streamer(method, requests, marshal, unmarshal,
439
+ deadline: nil,
440
+ return_op: false,
441
+ parent: nil,
442
+ credentials: nil,
443
+ metadata: {},
444
+ &blk)
445
+ c = new_active_call(method, marshal, unmarshal,
446
+ deadline: deadline,
447
+ parent: parent,
448
+ credentials: credentials)
449
+ interception_context = @interceptors.build_context
450
+ intercept_args = {
451
+ method: method,
452
+ requests: requests,
453
+ call: c.interceptable,
454
+ metadata: metadata
455
+ }
456
+ if return_op
457
+ # return the operation view of the active_call; define #execute
458
+ # as a new method for this instance that invokes #bidi_streamer
459
+ c.merge_metadata_to_send(metadata)
460
+ op = c.operation
461
+ op.define_singleton_method(:execute) do
462
+ interception_context.intercept!(:bidi_streamer, intercept_args) do
463
+ c.bidi_streamer(requests, &blk)
464
+ end
465
+ end
466
+ op
467
+ else
468
+ interception_context.intercept!(:bidi_streamer, intercept_args) do
469
+ c.bidi_streamer(requests, metadata: metadata, &blk)
470
+ end
471
+ end
472
+ end
473
+
474
+ private
475
+
476
+ # Creates a new active stub
477
+ #
478
+ # @param method [string] the method being called.
479
+ # @param marshal [Function] f(obj)->string that marshals requests
480
+ # @param unmarshal [Function] f(string)->obj that unmarshals responses
481
+ # @param parent [Grpc::Call] a parent call, available when calls are
482
+ # made from server
483
+ # @param credentials [Core::CallCredentials] credentials to use when making
484
+ # the call
485
+ def new_active_call(method, marshal, unmarshal,
486
+ deadline: nil,
487
+ parent: nil,
488
+ credentials: nil)
489
+ deadline = from_relative_time(@timeout) if deadline.nil?
490
+ # Provide each new client call with its own completion queue
491
+ call = @ch.create_call(parent, # parent call
492
+ @propagate_mask, # propagation options
493
+ method,
494
+ nil, # host use nil,
495
+ deadline)
496
+ call.set_credentials! credentials unless credentials.nil?
497
+ ActiveCall.new(call, marshal, unmarshal, deadline,
498
+ started: false)
499
+ end
500
+ end
501
+ end