google-cloud-bigtable 2.10.0 → 2.10.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d725783627648a929493cac00ba2ce282880c423ad727c4925889d23907954e
4
- data.tar.gz: 8f754bdb3f8b0193128fadf28432b24ebf121864d08964f6b7acf194a87c2af1
3
+ metadata.gz: bb8ed222ed2c24d4b39856180ede2faa2f861759a8166bcd86f1c76a969d8c24
4
+ data.tar.gz: 6a3575d2c69f0820899d14727a76bdeeeb89d05fde99abe90ff1b068ced220b0
5
5
  SHA512:
6
- metadata.gz: 1d90935ded28874a4227bb7a1a88072a18b6b9e98bbe965dc3311f78ae42e170c8842c7391d6edc99622f08b1b729883e7fde1533f64e73b3ee7b349d0287f4c
7
- data.tar.gz: 365d71227274e483f955a9ae96d827060cd6a4bc38a908f31d3453e78ff6cb8b30fc5db12cce452de61dadcd8d622613867a6ba87f157cfe5fbcdbe70ce2bd81
6
+ metadata.gz: d1cd0db63088866f0aaf1ee4829b5d6af9a7f9b30ae0b2315cba9e3f6a2ccfb6171820970fb6bc8a2f3c8628c946a7dc37df5665c58b1eb0614337118b94831b
7
+ data.tar.gz: c56bd73b38d3f8b031200f78228c018d9c59d81e170067755204983b8f51c162f31c7183e09cde5be27be89b69cfef3d1c221db31d0247343bf68d03d6bde5e9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Release History
2
2
 
3
+ ### 2.10.1 (2024-03-19)
4
+
5
+ #### Bug Fixes
6
+
7
+ * fix read rows retry so it doesn't trigger a full table scan in t… ([#25391](https://github.com/googleapis/google-cloud-ruby/issues/25391))
8
+
3
9
  ### 2.10.0 (2024-03-07)
4
10
 
5
11
  #### Features
@@ -159,8 +159,10 @@ module Google
159
159
  rescue *RowsReader::RETRYABLE_ERRORS => e
160
160
  rows_reader.retry_count += 1
161
161
  raise Google::Cloud::Error.from_error(e) unless rows_reader.retryable?
162
- rows_limit, row_set = rows_reader.retry_options limit, row_set
163
- retry
162
+ resumption_option = rows_reader.retry_options limit, row_set
163
+ rows_limit = resumption_option.rows_limit
164
+ row_set = resumption_option.row_set
165
+ retry unless resumption_option.complete?
164
166
  end
165
167
  end
166
168
 
@@ -320,6 +322,11 @@ module Google
320
322
  row_set[:row_ranges] = row_ranges.map(&:to_grpc)
321
323
  end
322
324
 
325
+ # Set the row range to full table scan if the row set is empty
326
+ if row_set.empty?
327
+ row_set[:row_ranges] = [Google::Cloud::Bigtable::V2::RowRange.new]
328
+ end
329
+
323
330
  Google::Cloud::Bigtable::V2::RowSet.new row_set
324
331
  end
325
332
  end
@@ -75,6 +75,7 @@ module Google
75
75
  # Array of row or yield block for each processed row.
76
76
  #
77
77
  def read rows: nil, filter: nil, rows_limit: nil
78
+ @rows_count = 0
78
79
  response = @table.service.read_rows(
79
80
  @table.instance_id,
80
81
  @table.table_id,
@@ -116,40 +117,54 @@ module Google
116
117
  # If not specified, reads from all rows.
117
118
  # A hash of the same form as `Google::Cloud::Bigtable::V2::RowSet`
118
119
  # can also be provided.
119
- # @return [Integer, Google::Cloud::Bigtable::V2::RowSet]
120
+ # @return ResumptionOption
120
121
  #
121
122
  def retry_options rows_limit, row_set
122
- return [rows_limit, row_set] unless last_key
123
+ return ResumptionOption.new false, rows_limit, row_set unless last_key
124
+
125
+ # Check if we've already read read rows_limit number of rows.
126
+ # If true, mark ResumptionOption is_complete to true.
127
+ return ResumptionOption.new true, nil, nil if rows_limit && rows_limit == @rows_count
123
128
 
124
- # 1. Reduce the limit by the number of already returned responses.
129
+ # Reduce the limit by the number of already returned responses.
125
130
  rows_limit -= @rows_count if rows_limit
126
131
 
127
- # 2. Remove ranges that have already been read, and reduce ranges that
132
+ reset_row_set rows_limit, row_set
133
+ end
134
+
135
+ ##
136
+ # Calculate the new row_set for the retry request
137
+ # @param rows_limit [Integer]
138
+ # the updated rows_limit
139
+ # @param row_set [Google::Cloud::Bigtable::V2::RowSet]
140
+ # original row_set
141
+ # @return ResumptionOption
142
+ def reset_row_set rows_limit, row_set
143
+ # 1. Remove ranges that have already been read, and reduce ranges that
128
144
  # include the last read rows
129
145
  if last_key
130
- delete_indexes = []
131
-
132
- row_set.row_ranges.each_with_index do |range, i|
133
- if end_key_read? range
134
- delete_indexes << i
135
- elsif start_key_read? range
146
+ row_set.row_ranges.reject! { |r| end_key_read? r }
147
+ row_set.row_ranges.each do |range|
148
+ if start_key_read? range
136
149
  range.start_key_open = last_key
137
150
  end
138
151
  end
139
-
140
- delete_indexes.each { |i| row_set.row_ranges.delete_at i }
141
- end
142
-
143
- if row_set.row_ranges.empty?
144
- row_set.row_ranges <<
145
- Google::Cloud::Bigtable::V2::RowRange.new(start_key_open: last_key)
146
152
  end
147
153
 
148
- # 3. Remove all individual keys before and up to the last read key
154
+ # 2. Remove all individual keys before and up to the last read key
149
155
  row_set.row_keys.select! { |k| k > last_key }
150
156
 
157
+ # 3. In read_operations, we always add an empty row_range if row_ranges and
158
+ # row_keys are not defined. So if both row_ranges and row_keys are empty,
159
+ # it means that we've already read all the ranges and keys, set ResumptionOption
160
+ # is_complete to true to indicate that this read is successful.
161
+ if last_key && row_set.row_ranges.empty? && row_set.row_keys.empty?
162
+ return ResumptionOption.new true, nil, nil
163
+ end
164
+
151
165
  @chunk_processor.reset_to_new_row
152
- [rows_limit, row_set]
166
+
167
+ ResumptionOption.new false, rows_limit, row_set
153
168
  end
154
169
 
155
170
  ##
@@ -170,13 +185,14 @@ module Google
170
185
  # @return [Boolean]
171
186
  #
172
187
  def start_key_read? range
173
- start_key = if range.start_key_closed.empty?
174
- range.start_key_open
175
- else
176
- range.start_key_closed
177
- end
178
-
179
- start_key.empty? || last_key >= start_key
188
+ if !range.start_key_closed.empty?
189
+ last_key >= range.start_key_closed
190
+ elsif !range.start_key_open.empty?
191
+ last_key > range.start_key_closed
192
+ else
193
+ # start is unbounded
194
+ true
195
+ end
180
196
  end
181
197
 
182
198
  ##
@@ -186,13 +202,42 @@ module Google
186
202
  # @return [Boolean]
187
203
  #
188
204
  def end_key_read? range
189
- end_key = if range.end_key_closed.empty?
190
- range.end_key_open
191
- else
192
- range.end_key_closed
193
- end
205
+ if !range.end_key_closed.empty?
206
+ range.end_key_closed <= last_key
207
+ elsif !range.end_key_open.empty?
208
+ range.end_key_open <= last_key
209
+ else
210
+ # end is unbounded
211
+ false
212
+ end
213
+ end
214
+ end
194
215
 
195
- end_key && end_key <= last_key
216
+ # @private
217
+ # ResumptionOption
218
+ # Helper class returned by retry_options
219
+ class ResumptionOption
220
+ # @private
221
+ # Creates a ResumptionOption instance
222
+ # @param is_complete [Boolean]
223
+ # marks if the current read is complete
224
+ # @param rows_limit [Integer]
225
+ # limit of the retry request
226
+ # @param row_set [Google::Cloud::Bigtable::V2::RowSet]
227
+ # row_set of the retry request
228
+ def initialize is_complete, rows_limit, row_set
229
+ @is_complete = is_complete
230
+ @rows_limit = rows_limit
231
+ @row_set = row_set
232
+ end
233
+
234
+ attr_reader :rows_limit
235
+ attr_reader :row_set
236
+
237
+ ##
238
+ # returns if this operation should be retried
239
+ def complete?
240
+ @is_complete
196
241
  end
197
242
  end
198
243
  end
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Bigtable
19
- VERSION = "2.10.0".freeze
19
+ VERSION = "2.10.1".freeze
20
20
  end
21
21
  end
22
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-bigtable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-07 00:00:00.000000000 Z
11
+ date: 2024-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby