gapic-common 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c3c4ee7ceef8f5caf7cf84304f6601ed730abd75089f3d7e5305bf2efaefed7
4
- data.tar.gz: 424864e640f307cbfc00829fdcdcfd83899032b4babd9eabf5cbfdbf827b3da2
3
+ metadata.gz: 5b5964ec91020c76501e2424be598b345a114a16515fe209135e46f552100d4e
4
+ data.tar.gz: 4a08e08fe15b6c6d6a3ad3097895a7d01bcfe3377f1392946a0cfe671ca97fdf
5
5
  SHA512:
6
- metadata.gz: fd2c71656a97d36f9f92f64c56cde7e6f9d8b63afa9602c12bbc0f9f8bfcf775e24729893839fc498de2e0629e592fcc56890d614d8ed8c0989c11d3dc11872c
7
- data.tar.gz: c6bb5cdef2186ba06191504fcf5d04ae8aac41820d03da16695d9d4e1a891ff5bdad8338598c339c5963ae9ef6816c457d15a28f26e92e4cc72b91b6a3d39d1a
6
+ metadata.gz: a0270a8d4933fda1f6297233f3465ae4fed20d34ebbf4bb766f228fe13746b5508c97179eb7c0b763d104c52079f59765b514c32a1d6cb2d61196791f007595a
7
+ data.tar.gz: 437633278a8640eee28a975c7821270b11c2127c72970e0259c29b5b643db37b8d394ac5ae1cd80cb367e10c1384311cc018e0a276804dfda7d8a91f9fffb13a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Release History
2
2
 
3
+ ### 0.13.0 (2022-10-26)
4
+
5
+ #### Features
6
+
7
+ * Implement server-side streaming support for REST calls in gapic-common ([#826](https://github.com/googleapis/gapic-generator-ruby/issues/826))
8
+
3
9
  ### 0.12.0 (2022-09-15)
4
10
 
5
11
  #### Features
@@ -14,6 +14,6 @@
14
14
 
15
15
  module Gapic
16
16
  module Common
17
- VERSION = "0.12.0".freeze
17
+ VERSION = "0.13.0".freeze
18
18
  end
19
19
  end
@@ -127,8 +127,10 @@ module Gapic
127
127
  # @param params [Hash] query string parameters for the request
128
128
  # @param options [::Gapic::CallOptions,Hash] gapic options to be applied
129
129
  # to the REST call. Currently only timeout and headers are supported.
130
+ # @param is_server_streaming [Boolean] flag if method is streaming
131
+ # @yieldparam chunk [String] The chunk of data received during server streaming.
130
132
  # @return [Faraday::Response]
131
- def make_http_request verb, uri:, body:, params:, options:
133
+ def make_http_request verb, uri:, body:, params:, options:, is_server_streaming: false
132
134
  if @numeric_enums && (!params.key?("$alt") || params["$alt"] == "json")
133
135
  params = params.merge({ "$alt" => "json;enum-encoding=int" })
134
136
  end
@@ -138,6 +140,11 @@ module Gapic
138
140
  req.body = body unless body.nil?
139
141
  req.headers = req.headers.merge options.metadata
140
142
  req.options.timeout = options.timeout if options.timeout&.positive?
143
+ if is_server_streaming
144
+ req.options.on_data = proc do |chunk, _overall_received_bytes|
145
+ yield chunk
146
+ end
147
+ end
141
148
  end
142
149
  end
143
150
  end
@@ -0,0 +1,101 @@
1
+ # Copyright 2022 Google LLC
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
+ # https://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 "json"
16
+
17
+ module Gapic
18
+ module Rest
19
+ ##
20
+ # A class to provide the Enumerable interface to the response of a REST server-streaming dmethod.
21
+ #
22
+ # ServerStream provides the enumerations over the individual response messages within the stream.
23
+ #
24
+ # @example normal iteration over resources.
25
+ # server_stream.each { |response| puts response }
26
+ #
27
+ class ServerStream
28
+ include Enumerable
29
+
30
+ ##
31
+ # Initializes ServerStream object.
32
+ #
33
+ # @param message_klass [Class]
34
+ # @param json_enumerator [Enumerator<String>]
35
+ def initialize message_klass, json_enumerator
36
+ @json_enumerator = json_enumerator
37
+ @obj = ""
38
+ @message_klass = message_klass
39
+ @ready_objs = [] # List of strings
40
+ end
41
+
42
+ ##
43
+ # Iterate over JSON objects in the streamed response.
44
+ #
45
+ # @yield [Object] Gives one complete Message object.
46
+ #
47
+ # @return [Enumerator] if no block is provided
48
+ #
49
+ def each
50
+ return enum_for :each unless block_given?
51
+
52
+ loop do
53
+ while @ready_objs.length.zero?
54
+ begin
55
+ chunk = @json_enumerator.next
56
+ next unless chunk
57
+ next_json! chunk
58
+ rescue StopIteration
59
+ dangling_content = @obj.strip
60
+ error_expl = "Dangling content left after iterating through the stream. " \
61
+ "This means that not all content was received or parsed correctly. " \
62
+ "It is likely a result of server or network error."
63
+ error_text = "#{error_expl}\n Content left unparsed: #{dangling_content}"
64
+
65
+ raise Gapic::Common::Error, error_text unless dangling_content.empty?
66
+ return
67
+ end
68
+ end
69
+ yield @message_klass.decode_json @ready_objs.shift, ignore_unknown_fields: true
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ ##
76
+ # Builds the next JSON object of the server stream from chunk.
77
+ #
78
+ # @param chunk [String] Contains (partial) JSON object
79
+ #
80
+ def next_json! chunk
81
+ chunk.chars.each do |char|
82
+ # Invariant: @obj is always either a part of a single JSON object or the entire JSON object.
83
+ # Hence, it's safe to strip whitespace, commans and array brackets. These characters
84
+ # are only added before @obj is a complete JSON object and essentially can be flushed.
85
+ next if @obj.empty? && char != "{"
86
+ @obj += char
87
+ next unless char == "}"
88
+ begin
89
+ # Two choices here: append a Ruby object into
90
+ # ready_objs or a string. Going with the latter here.
91
+ JSON.parse @obj
92
+ @ready_objs.append @obj
93
+ @obj = ""
94
+ rescue JSON::ParserError
95
+ next
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,71 @@
1
+ # Copyright 2022 Google LLC
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
+ # https://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
+
16
+ module Gapic
17
+ module Rest
18
+ ##
19
+ # @private
20
+ # A class to provide the Enumerable interface to an incoming stream of data.
21
+ #
22
+ # ThreadedEnumerator provides the enumerations over the individual chunks of data received from the server.
23
+ #
24
+ # @example normal iteration over resources.
25
+ # chunk = threaded_enumerator.next
26
+ #
27
+ # @attribute [r] in_q
28
+ # @return [Queue] Input queue.
29
+ # @attribute [r] out_q
30
+ # @return [Queue] Output queue.
31
+ class ThreadedEnumerator
32
+ attr_reader :in_q
33
+ attr_reader :out_q
34
+
35
+ # Spawns a new thread and does appropriate clean-up
36
+ # in case thread fails. Propagates exception back
37
+ # to main thread.
38
+ #
39
+ # @yieldparam in_q[Queue] input queue
40
+ # @yieldparam out_q[Queue] output queue
41
+ def initialize
42
+ @in_q = Queue.new
43
+ @out_q = Queue.new
44
+
45
+ Thread.new do
46
+ yield @in_q, @out_q
47
+ rescue StandardError => e
48
+ @out_q.push e
49
+ end
50
+ end
51
+
52
+ def next
53
+ @in_q.enq :next
54
+ chunk = @out_q.deq
55
+
56
+ if chunk.is_a? StandardError
57
+ @out_q.close
58
+ @in_q.close
59
+ raise chunk
60
+ end
61
+
62
+ if chunk.nil?
63
+ @out_q.close
64
+ @in_q.close
65
+ raise StopIteration
66
+ end
67
+ chunk
68
+ end
69
+ end
70
+ end
71
+ end
data/lib/gapic/rest.rb CHANGED
@@ -27,4 +27,6 @@ require "gapic/rest/faraday_middleware"
27
27
  require "gapic/rest/grpc_transcoder"
28
28
  require "gapic/rest/operation"
29
29
  require "gapic/rest/paged_enumerable"
30
+ require "gapic/rest/server_stream"
31
+ require "gapic/rest/threaded_enumerator"
30
32
  require "json"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gapic-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google API Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-16 00:00:00.000000000 Z
11
+ date: 2022-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -314,6 +314,8 @@ files:
314
314
  - lib/gapic/rest/grpc_transcoder/http_binding.rb
315
315
  - lib/gapic/rest/operation.rb
316
316
  - lib/gapic/rest/paged_enumerable.rb
317
+ - lib/gapic/rest/server_stream.rb
318
+ - lib/gapic/rest/threaded_enumerator.rb
317
319
  - lib/gapic/stream_input.rb
318
320
  homepage: https://github.com/googleapis/gapic-generator-ruby
319
321
  licenses: