grpc 1.32.0-universal-darwin → 1.35.0-universal-darwin

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.

@@ -39,11 +39,38 @@ require_relative '../src/proto/grpc/testing/empty_pb'
39
39
  require_relative '../src/proto/grpc/testing/messages_pb'
40
40
  require_relative '../src/proto/grpc/testing/test_services_pb'
41
41
 
42
+ class RpcConfig
43
+ def init(rpcs_to_send, metadata_to_send)
44
+ @rpcs_to_send = rpcs_to_send
45
+ @metadata_to_send = metadata_to_send
46
+ end
47
+ def rpcs_to_send
48
+ @rpcs_to_send
49
+ end
50
+ def metadata_to_send
51
+ @metadata_to_send
52
+ end
53
+ end
54
+
55
+ # Some global constant mappings
56
+ $RPC_MAP = {
57
+ 'UnaryCall' => :UNARY_CALL,
58
+ 'EmptyCall' => :EMPTY_CALL,
59
+ }
60
+
42
61
  # Some global variables to be shared by server and client
43
62
  $watchers = Array.new
44
63
  $watchers_mutex = Mutex.new
45
64
  $watchers_cv = ConditionVariable.new
46
65
  $shutdown = false
66
+ # These can be configured by the test runner dynamically
67
+ $rpc_config = RpcConfig.new
68
+ $rpc_config.init([:UNARY_CALL], {})
69
+ # These stats are shared across threads
70
+ $accumulated_stats_mu = Mutex.new
71
+ $num_rpcs_started_by_method = {}
72
+ $num_rpcs_succeeded_by_method = {}
73
+ $num_rpcs_failed_by_method = {}
47
74
 
48
75
  # RubyLogger defines a logger for gRPC based on the standard ruby logger.
49
76
  module RubyLogger
@@ -71,6 +98,31 @@ def create_stub(opts)
71
98
  )
72
99
  end
73
100
 
101
+ class ConfigureTarget < Grpc::Testing::XdsUpdateClientConfigureService::Service
102
+ include Grpc::Testing
103
+
104
+ def configure(req, _call)
105
+ rpcs_to_send = req['types'];
106
+ metadata_to_send = {}
107
+ req['metadata'].each do |m|
108
+ rpc = m.type
109
+ if !metadata_to_send.key?(rpc)
110
+ metadata_to_send[rpc] = {}
111
+ end
112
+ metadata_key = m.key
113
+ metadata_value = m.value
114
+ metadata_to_send[rpc][metadata_key] = metadata_value
115
+ end
116
+ GRPC.logger.info("Configuring new rpcs_to_send and metadata_to_send...")
117
+ GRPC.logger.info(rpcs_to_send)
118
+ GRPC.logger.info(metadata_to_send)
119
+ new_rpc_config = RpcConfig.new
120
+ new_rpc_config.init(rpcs_to_send, metadata_to_send)
121
+ $rpc_config = new_rpc_config
122
+ ClientConfigureResponse.new();
123
+ end
124
+ end
125
+
74
126
  # This implements LoadBalancerStatsService required by the test runner
75
127
  class TestTarget < Grpc::Testing::LoadBalancerStatsService::Service
76
128
  include Grpc::Testing
@@ -109,10 +161,20 @@ class TestTarget < Grpc::Testing::LoadBalancerStatsService::Service
109
161
  num_failures: watcher['no_remote_peer'] + watcher['rpcs_needed']
110
162
  );
111
163
  end
164
+
165
+ def get_client_accumulated_stats(req, _call)
166
+ $accumulated_stats_mu.synchronize do
167
+ LoadBalancerAccumulatedStatsResponse.new(
168
+ num_rpcs_started_by_method: $num_rpcs_started_by_method,
169
+ num_rpcs_succeeded_by_method: $num_rpcs_succeeded_by_method,
170
+ num_rpcs_failed_by_method: $num_rpcs_failed_by_method
171
+ )
172
+ end
173
+ end
112
174
  end
113
175
 
114
176
  # execute 1 RPC and return remote hostname
115
- def execute_rpc(op, fail_on_failed_rpcs)
177
+ def execute_rpc(op, fail_on_failed_rpcs, rpc_stats_key)
116
178
  remote_peer = ""
117
179
  begin
118
180
  op.execute
@@ -120,60 +182,108 @@ def execute_rpc(op, fail_on_failed_rpcs)
120
182
  remote_peer = op.metadata['hostname']
121
183
  end
122
184
  rescue GRPC::BadStatus => e
123
- GRPC.logger.info("ruby xds: rpc failed:|#{e.message}|, " \
124
- "this may or may not be expected")
125
185
  if fail_on_failed_rpcs
126
186
  raise e
127
187
  end
128
188
  end
189
+ $accumulated_stats_mu.synchronize do
190
+ if remote_peer.empty?
191
+ $num_rpcs_failed_by_method[rpc_stats_key] += 1
192
+ else
193
+ $num_rpcs_succeeded_by_method[rpc_stats_key] += 1
194
+ end
195
+ end
129
196
  remote_peer
130
197
  end
131
198
 
199
+ def execute_rpc_in_thread(op, rpc_stats_key)
200
+ Thread.new {
201
+ begin
202
+ op.execute
203
+ # The following should _not_ happen with the current spec
204
+ # because we are only executing RPCs in a thread if we expect it
205
+ # to be kept open, or deadline_exceeded, or dropped by the load
206
+ # balancing policy. These RPCs should not complete successfully.
207
+ # Doing this for consistency
208
+ $accumulated_stats_mu.synchronize do
209
+ $num_rpcs_succeeded_by_method[rpc_stats_key] += 1
210
+ end
211
+ rescue GRPC::BadStatus => e
212
+ # Normal execution arrives here,
213
+ # either because of deadline_exceeded or "call dropped by load
214
+ # balancing policy"
215
+ $accumulated_stats_mu.synchronize do
216
+ $num_rpcs_failed_by_method[rpc_stats_key] += 1
217
+ end
218
+ end
219
+ }
220
+ end
221
+
132
222
  # send 1 rpc every 1/qps second
133
- def run_test_loop(stub, target_seconds_between_rpcs, fail_on_failed_rpcs,
134
- rpcs_to_send, metadata_to_send)
223
+ def run_test_loop(stub, target_seconds_between_rpcs, fail_on_failed_rpcs)
135
224
  include Grpc::Testing
136
225
  simple_req = SimpleRequest.new()
137
226
  empty_req = Empty.new()
138
227
  target_next_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
228
+ # Some RPCs are meant to be "kept open". Since Ruby does not have an
229
+ # async API, we are executing those RPCs in a thread so that they don't
230
+ # block.
231
+ keep_open_threads = Array.new
139
232
  while !$shutdown
140
233
  now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
141
234
  sleep_seconds = target_next_start - now
142
235
  if sleep_seconds < 0
143
236
  target_next_start = now + target_seconds_between_rpcs
144
- GRPC.logger.info(
145
- "ruby xds: warning, rpc takes too long to finish. " \
146
- "Deficit = %.1fms. " \
147
- "If you consistently see this, the qps is too high." \
148
- % [(sleep_seconds * 1000).abs().round(1)])
149
237
  else
150
238
  target_next_start += target_seconds_between_rpcs
151
239
  sleep(sleep_seconds)
152
240
  end
153
241
  deadline = GRPC::Core::TimeConsts::from_relative_time(30) # 30 seconds
154
242
  results = {}
155
- rpcs_to_send.each do |rpc|
156
- metadata = metadata_to_send.key?(rpc) ? metadata_to_send[rpc] : {}
157
- if rpc == 'UnaryCall'
243
+ $rpc_config.rpcs_to_send.each do |rpc|
244
+ # rpc is in the form of :UNARY_CALL or :EMPTY_CALL here
245
+ metadata = $rpc_config.metadata_to_send.key?(rpc) ?
246
+ $rpc_config.metadata_to_send[rpc] : {}
247
+ $accumulated_stats_mu.synchronize do
248
+ $num_rpcs_started_by_method[rpc.to_s] += 1
249
+ num_started = $num_rpcs_started_by_method[rpc.to_s]
250
+ if num_started % 100 == 0
251
+ GRPC.logger.info("Started #{num_started} of #{rpc}")
252
+ end
253
+ end
254
+ if rpc == :UNARY_CALL
158
255
  op = stub.unary_call(simple_req,
159
256
  metadata: metadata,
160
257
  deadline: deadline,
161
258
  return_op: true)
162
- elsif rpc == 'EmptyCall'
259
+ elsif rpc == :EMPTY_CALL
163
260
  op = stub.empty_call(empty_req,
164
261
  metadata: metadata,
165
262
  deadline: deadline,
166
263
  return_op: true)
167
264
  else
168
- raise "Unsupported rpc %s" % [rpc]
265
+ raise "Unsupported rpc #{rpc}"
266
+ end
267
+ rpc_stats_key = rpc.to_s
268
+ if metadata.key?('rpc-behavior') and
269
+ (metadata['rpc-behavior'] == 'keep-open')
270
+ num_open_threads = keep_open_threads.size
271
+ if num_open_threads % 50 == 0
272
+ GRPC.logger.info("number of keep_open_threads = #{num_open_threads}")
273
+ end
274
+ keep_open_threads << execute_rpc_in_thread(op, rpc_stats_key)
275
+ else
276
+ results[rpc] = execute_rpc(op, fail_on_failed_rpcs, rpc_stats_key)
169
277
  end
170
- results[rpc] = execute_rpc(op, fail_on_failed_rpcs)
171
278
  end
172
279
  $watchers_mutex.synchronize do
173
280
  $watchers.each do |watcher|
174
281
  # this is counted once when each group of all rpcs_to_send were done
175
282
  watcher['rpcs_needed'] -= 1
176
283
  results.each do |rpc_name, remote_peer|
284
+ # These stats expect rpc_name to be in the form of
285
+ # UnaryCall or EmptyCall, not the underscore-case all-caps form
286
+ rpc_name = $RPC_MAP.invert()[rpc_name]
177
287
  if remote_peer.strip.empty?
178
288
  # error is counted per individual RPC
179
289
  watcher['no_remote_peer'] += 1
@@ -191,6 +301,7 @@ def run_test_loop(stub, target_seconds_between_rpcs, fail_on_failed_rpcs,
191
301
  $watchers_cv.broadcast
192
302
  end
193
303
  end
304
+ keep_open_threads.each { |thd| thd.join }
194
305
  end
195
306
 
196
307
  # Args is used to hold the command line info.
@@ -242,18 +353,22 @@ def main
242
353
  s = GRPC::RpcServer.new
243
354
  s.add_http2_port(host, :this_port_is_insecure)
244
355
  s.handle(TestTarget)
356
+ s.handle(ConfigureTarget)
245
357
  server_thread = Thread.new {
246
358
  # run the server until the main test runner terminates this process
247
359
  s.run_till_terminated_or_interrupted(['TERM'])
248
360
  }
249
361
 
250
- # The client just sends unary rpcs continuously in a regular interval
362
+ # Initialize stats
363
+ $RPC_MAP.values.each do |rpc|
364
+ $num_rpcs_started_by_method[rpc.to_s] = 0
365
+ $num_rpcs_succeeded_by_method[rpc.to_s] = 0
366
+ $num_rpcs_failed_by_method[rpc.to_s] = 0
367
+ end
368
+
369
+ # The client just sends rpcs continuously in a regular interval
251
370
  stub = create_stub(opts)
252
371
  target_seconds_between_rpcs = (1.0 / opts['qps'].to_f)
253
- rpcs_to_send = []
254
- if opts['rpc']
255
- rpcs_to_send = opts['rpc'].split(',')
256
- end
257
372
  # Convert 'metadata' input in the form of
258
373
  # rpc1:k1:v1,rpc2:k2:v2,rpc1:k3:v3
259
374
  # into
@@ -266,11 +381,13 @@ def main
266
381
  # 'k2' => 'v2'
267
382
  # },
268
383
  # }
384
+ rpcs_to_send = []
269
385
  metadata_to_send = {}
270
386
  if opts['metadata']
271
387
  metadata_entries = opts['metadata'].split(',')
272
388
  metadata_entries.each do |e|
273
389
  (rpc_name, metadata_key, metadata_value) = e.split(':')
390
+ rpc_name = $RPC_MAP[rpc_name]
274
391
  # initialize if we haven't seen this rpc_name yet
275
392
  if !metadata_to_send.key?(rpc_name)
276
393
  metadata_to_send[rpc_name] = {}
@@ -278,12 +395,20 @@ def main
278
395
  metadata_to_send[rpc_name][metadata_key] = metadata_value
279
396
  end
280
397
  end
398
+ if opts['rpc']
399
+ rpcs_to_send = opts['rpc'].split(',')
400
+ end
401
+ if rpcs_to_send.size > 0
402
+ rpcs_to_send.map! { |rpc| $RPC_MAP[rpc] }
403
+ new_rpc_config = RpcConfig.new
404
+ new_rpc_config.init(rpcs_to_send, metadata_to_send)
405
+ $rpc_config = new_rpc_config
406
+ end
281
407
  client_threads = Array.new
282
408
  opts['num_channels'].times {
283
409
  client_threads << Thread.new {
284
410
  run_test_loop(stub, target_seconds_between_rpcs,
285
- opts['fail_on_failed_rpcs'],
286
- rpcs_to_send, metadata_to_send)
411
+ opts['fail_on_failed_rpcs'])
287
412
  }
288
413
  }
289
414
 
@@ -71,14 +71,10 @@ describe 'Code Generation Options' do
71
71
  end
72
72
 
73
73
  def with_protos(file_paths)
74
- fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG']
75
- bins_sub_dir = ENV['CONFIG']
76
-
77
74
  pb_dir = File.dirname(__FILE__)
78
- bins_dir = File.join('..', '..', '..', '..', '..', 'bins', bins_sub_dir)
79
-
75
+ bins_dir = File.join('..', '..', '..', '..', '..', 'cmake', 'build')
80
76
  plugin = File.join(bins_dir, 'grpc_ruby_plugin')
81
- protoc = File.join(bins_dir, 'protobuf', 'protoc')
77
+ protoc = File.join(bins_dir, 'third_party', 'protobuf', 'protoc')
82
78
 
83
79
  # Generate the service from the proto
84
80
  Dir.mktmpdir(nil, File.dirname(__FILE__)) do |tmp_dir|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.32.0
4
+ version: 1.35.0
5
5
  platform: universal-darwin
6
6
  authors:
7
7
  - gRPC Authors
8
- autorequire:
8
+ autorequire:
9
9
  bindir: src/ruby/bin
10
10
  cert_chain: []
11
- date: 2020-09-08 00:00:00.000000000 Z
11
+ date: 2021-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.13'
19
+ version: '3.14'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '3.13'
26
+ version: '3.14'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: googleapis-common-protos-types
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -330,7 +330,7 @@ homepage: https://github.com/google/grpc/tree/master/src/ruby
330
330
  licenses:
331
331
  - Apache-2.0
332
332
  metadata: {}
333
- post_install_message:
333
+ post_install_message:
334
334
  rdoc_options: []
335
335
  require_paths:
336
336
  - src/ruby/lib
@@ -343,15 +343,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
343
343
  version: '2.3'
344
344
  - - "<"
345
345
  - !ruby/object:Gem::Version
346
- version: 2.8.dev
346
+ version: 3.1.dev
347
347
  required_rubygems_version: !ruby/object:Gem::Requirement
348
348
  requirements:
349
349
  - - ">="
350
350
  - !ruby/object:Gem::Version
351
351
  version: '0'
352
352
  requirements: []
353
- rubygems_version: 3.1.4
354
- signing_key:
353
+ rubygems_version: 3.2.6
354
+ signing_key:
355
355
  specification_version: 4
356
356
  summary: GRPC system in Ruby
357
357
  test_files: