diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index af599353..0ddb512d 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -4,6 +4,8 @@ branchProtectionRules: # Identifies the protection rule pattern. Name of the branch to be protected. # Defaults to `master` - pattern: master + requiresCodeOwnerReviews: true + requiresStrictStatusChecks: true requiredStatusCheckContexts: - 'Kokoro' - 'cla/google' diff --git a/CHANGELOG.md b/CHANGELOG.md index 72f0f26a..07971c0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ [1]: https://pypi.org/project/google-cloud-bigquery-storage/#history +### [2.6.3](https://www.github.com/googleapis/python-bigquery-storage/compare/v2.6.2...v2.6.3) (2021-08-06) + + +### Bug Fixes + +* resume read stream on `Unknown` transport-layer exception ([#263](https://www.github.com/googleapis/python-bigquery-storage/issues/263)) ([127caa0](https://www.github.com/googleapis/python-bigquery-storage/commit/127caa06144b9cec04b23914b561be6a264bcb36)) + ### [2.6.2](https://www.github.com/googleapis/python-bigquery-storage/compare/v2.6.1...v2.6.2) (2021-07-28) diff --git a/google/cloud/bigquery_storage_v1/reader.py b/google/cloud/bigquery_storage_v1/reader.py index a8cd226c..fd6e630c 100644 --- a/google/cloud/bigquery_storage_v1/reader.py +++ b/google/cloud/bigquery_storage_v1/reader.py @@ -39,7 +39,12 @@ pyarrow = None -_STREAM_RESUMPTION_EXCEPTIONS = (google.api_core.exceptions.ServiceUnavailable,) +_STREAM_RESUMPTION_EXCEPTIONS = ( + google.api_core.exceptions.ServiceUnavailable, + # Caused by transport-level error. No status code was received. + # https://github.com/googleapis/python-bigquery-storage/issues/262 + google.api_core.exceptions.Unknown, +) # The Google API endpoint can unexpectedly close long-running HTTP/2 streams. # Unfortunately, this condition is surfaced to the caller as an internal error diff --git a/samples/quickstart/requirements.txt b/samples/quickstart/requirements.txt index ca069335..204c2729 100644 --- a/samples/quickstart/requirements.txt +++ b/samples/quickstart/requirements.txt @@ -1,2 +1,2 @@ fastavro -google-cloud-bigquery-storage==2.6.0 +google-cloud-bigquery-storage==2.6.2 diff --git a/samples/to_dataframe/requirements.txt b/samples/to_dataframe/requirements.txt index 1435a6fc..6a851c9c 100644 --- a/samples/to_dataframe/requirements.txt +++ b/samples/to_dataframe/requirements.txt @@ -1,7 +1,7 @@ google-auth==1.34.0 -google-cloud-bigquery-storage==2.6.0 -google-cloud-bigquery==2.23.0 -pyarrow==4.0.1 +google-cloud-bigquery-storage==2.6.2 +google-cloud-bigquery==2.23.2 +pyarrow==5.0.0 ipython==7.24.0; python_version > '3.6' ipython==7.16.1; python_version <= '3.6' pandas==1.2.5; python_version > '3.6' diff --git a/setup.py b/setup.py index 2bef8ac6..6c34f388 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ name = "google-cloud-bigquery-storage" description = "BigQuery Storage API API client library" -version = "2.6.2" +version = "2.6.3" release_status = "Development Status :: 5 - Production/Stable" dependencies = [ # NOTE: Maintainers, please do not require google-api-core>=2.x.x diff --git a/tests/unit/test_reader_v1.py b/tests/unit/test_reader_v1.py index 838ef51a..94d63c0c 100644 --- a/tests/unit/test_reader_v1.py +++ b/tests/unit/test_reader_v1.py @@ -103,6 +103,12 @@ def _pages_w_unavailable(pages): raise google.api_core.exceptions.ServiceUnavailable("test: please reconnect") +def _pages_w_unknown(pages): + for page in pages: + yield page + raise google.api_core.exceptions.Unknown("No status received") + + def _avro_blocks_w_deadline(avro_blocks): for block in avro_blocks: yield block @@ -237,14 +243,19 @@ def test_rows_w_reconnect(class_under_test, mock_gapic_client): ] avro_blocks_1 = _pages_w_unavailable(_bq_to_avro_blocks(bq_blocks_1, avro_schema)) bq_blocks_2 = [[{"int_col": 1024}, {"int_col": 512}], [{"int_col": 256}]] - avro_blocks_2 = _bq_to_avro_blocks(bq_blocks_2, avro_schema) avro_blocks_2 = _pages_w_resumable_internal_error( _bq_to_avro_blocks(bq_blocks_2, avro_schema) ) - bq_blocks_3 = [[{"int_col": 567}, {"int_col": 789}], [{"int_col": 890}]] - avro_blocks_3 = _bq_to_avro_blocks(bq_blocks_3, avro_schema) - - mock_gapic_client.read_rows.side_effect = (avro_blocks_2, avro_blocks_3) + bq_blocks_3 = [[{"int_col": -1}, {"int_col": -2}], [{"int_col": -4}]] + avro_blocks_3 = _pages_w_unknown(_bq_to_avro_blocks(bq_blocks_3, avro_schema)) + bq_blocks_4 = [[{"int_col": 567}, {"int_col": 789}], [{"int_col": 890}]] + avro_blocks_4 = _bq_to_avro_blocks(bq_blocks_4, avro_schema) + + mock_gapic_client.read_rows.side_effect = ( + avro_blocks_2, + avro_blocks_3, + avro_blocks_4, + ) reader = class_under_test( avro_blocks_1, @@ -260,6 +271,7 @@ def test_rows_w_reconnect(class_under_test, mock_gapic_client): itertools.chain.from_iterable(bq_blocks_1), itertools.chain.from_iterable(bq_blocks_2), itertools.chain.from_iterable(bq_blocks_3), + itertools.chain.from_iterable(bq_blocks_4), ) ) @@ -267,9 +279,12 @@ def test_rows_w_reconnect(class_under_test, mock_gapic_client): mock_gapic_client.read_rows.assert_any_call( read_stream="teststream", offset=4, metadata={"test-key": "test-value"} ) - mock_gapic_client.read_rows.assert_called_with( + mock_gapic_client.read_rows.assert_any_call( read_stream="teststream", offset=7, metadata={"test-key": "test-value"} ) + mock_gapic_client.read_rows.assert_called_with( + read_stream="teststream", offset=10, metadata={"test-key": "test-value"} + ) def test_rows_w_reconnect_by_page(class_under_test, mock_gapic_client):