Skip to content

Commit 127caa0

Browse files
authored
fix: resume read stream on Unknown transport-layer exception (#263)
1 parent 1ac1356 commit 127caa0

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

google/cloud/bigquery_storage_v1/reader.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@
3939
pyarrow = None
4040

4141

42-
_STREAM_RESUMPTION_EXCEPTIONS = (google.api_core.exceptions.ServiceUnavailable,)
42+
_STREAM_RESUMPTION_EXCEPTIONS = (
43+
google.api_core.exceptions.ServiceUnavailable,
44+
# Caused by transport-level error. No status code was received.
45+
# https://github.com/googleapis/python-bigquery-storage/issues/262
46+
google.api_core.exceptions.Unknown,
47+
)
4348

4449
# The Google API endpoint can unexpectedly close long-running HTTP/2 streams.
4550
# Unfortunately, this condition is surfaced to the caller as an internal error

tests/unit/test_reader_v1.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ def _pages_w_unavailable(pages):
103103
raise google.api_core.exceptions.ServiceUnavailable("test: please reconnect")
104104

105105

106+
def _pages_w_unknown(pages):
107+
for page in pages:
108+
yield page
109+
raise google.api_core.exceptions.Unknown("No status received")
110+
111+
106112
def _avro_blocks_w_deadline(avro_blocks):
107113
for block in avro_blocks:
108114
yield block
@@ -237,14 +243,19 @@ def test_rows_w_reconnect(class_under_test, mock_gapic_client):
237243
]
238244
avro_blocks_1 = _pages_w_unavailable(_bq_to_avro_blocks(bq_blocks_1, avro_schema))
239245
bq_blocks_2 = [[{"int_col": 1024}, {"int_col": 512}], [{"int_col": 256}]]
240-
avro_blocks_2 = _bq_to_avro_blocks(bq_blocks_2, avro_schema)
241246
avro_blocks_2 = _pages_w_resumable_internal_error(
242247
_bq_to_avro_blocks(bq_blocks_2, avro_schema)
243248
)
244-
bq_blocks_3 = [[{"int_col": 567}, {"int_col": 789}], [{"int_col": 890}]]
245-
avro_blocks_3 = _bq_to_avro_blocks(bq_blocks_3, avro_schema)
246-
247-
mock_gapic_client.read_rows.side_effect = (avro_blocks_2, avro_blocks_3)
249+
bq_blocks_3 = [[{"int_col": -1}, {"int_col": -2}], [{"int_col": -4}]]
250+
avro_blocks_3 = _pages_w_unknown(_bq_to_avro_blocks(bq_blocks_3, avro_schema))
251+
bq_blocks_4 = [[{"int_col": 567}, {"int_col": 789}], [{"int_col": 890}]]
252+
avro_blocks_4 = _bq_to_avro_blocks(bq_blocks_4, avro_schema)
253+
254+
mock_gapic_client.read_rows.side_effect = (
255+
avro_blocks_2,
256+
avro_blocks_3,
257+
avro_blocks_4,
258+
)
248259

249260
reader = class_under_test(
250261
avro_blocks_1,
@@ -260,16 +271,20 @@ def test_rows_w_reconnect(class_under_test, mock_gapic_client):
260271
itertools.chain.from_iterable(bq_blocks_1),
261272
itertools.chain.from_iterable(bq_blocks_2),
262273
itertools.chain.from_iterable(bq_blocks_3),
274+
itertools.chain.from_iterable(bq_blocks_4),
263275
)
264276
)
265277

266278
assert tuple(got) == expected
267279
mock_gapic_client.read_rows.assert_any_call(
268280
read_stream="teststream", offset=4, metadata={"test-key": "test-value"}
269281
)
270-
mock_gapic_client.read_rows.assert_called_with(
282+
mock_gapic_client.read_rows.assert_any_call(
271283
read_stream="teststream", offset=7, metadata={"test-key": "test-value"}
272284
)
285+
mock_gapic_client.read_rows.assert_called_with(
286+
read_stream="teststream", offset=10, metadata={"test-key": "test-value"}
287+
)
273288

274289

275290
def test_rows_w_reconnect_by_page(class_under_test, mock_gapic_client):

0 commit comments

Comments
 (0)