We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
bug: client doesn't retry "Job exceeded rate limits" for DDL query jobs that exceed quota for table update operations 
In https://github.com/googleapis/python-bigquery-sqlalchemy/pull/1009#discussion_r1457644849 it seems that the query in https://btx-internal.corp.google.com/invocations/ffafb866-6bc0-423f-a86b-df69fb270d57/targets/cloud-devrel%2Fclient-libraries%2Fpython%2Fgoogleapis%2Fpython-bigquery-sqlalchemy%2Fpresubmit%2Fprerelease-deps;config=default/log with rate limits exceeded errors are not retried.

#### Environment details

  - OS type and version:
  - Python version: `python --version`
  - pip version: `pip --version`
  - `google-cloud-bigquery` version: `pip show google-cloud-bigquery`

#### Steps to reproduce

Run a DDL query more than 5 times in 10 seconds, violating the five table metadata update operations per 10 seconds per table limit (https://cloud.google.com/bigquery/quotas#standard_tables).

#### Code example

```python
import google.cloud.bigquery
bqclient = google.cloud.bigquery.Client()
sql = "ALTER TABLE `swast-scratch.my_dataset.my_table` ADD COLUMN IF NOT EXISTS my_string_col STRING"
for _ in range(100):
    bqclient.query_and_wait(sql)
```

#### Stack trace

```
BadRequest                                Traceback (most recent call last)
Input In [4], in <cell line: 1>()
      1 for _ in range(100):
----> 2     bqclient.query_and_wait(sql)

File ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/client.py:3503, in Client.query_and_wait(self, query, job_config, location, project, api_timeout, wait_timeout, retry, job_retry, page_size, max_results)
   3497     _verify_job_config_type(job_config, QueryJobConfig)
   3499 job_config = _job_helpers.job_config_with_defaults(
   3500     job_config, self._default_query_job_config
   3501 )
-> 3503 return _job_helpers.query_and_wait(
   3504     self,
   3505     query,
   3506     job_config=job_config,
   3507     location=location,
   3508     project=project,
   3509     api_timeout=api_timeout,
   3510     wait_timeout=wait_timeout,
   3511     retry=retry,
   3512     job_retry=job_retry,
   3513     page_size=page_size,
   3514     max_results=max_results,
   3515 )

File ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/_job_helpers.py:498, in query_and_wait(client, query, job_config, location, project, api_timeout, wait_timeout, retry, job_retry, page_size, max_results)
    481     return table.RowIterator(
    482         client=client,
    483         api_request=functools.partial(client._call_api, retry, timeout=api_timeout),
   (...)
    494         num_dml_affected_rows=query_results.num_dml_affected_rows,
    495     )
    497 if job_retry is not None:
--> 498     return job_retry(do_query)()
    499 else:
    500     return do_query()

File /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:349, in Retry.__call__.<locals>.retry_wrapped_func(*args, **kwargs)
    345 target = functools.partial(func, *args, **kwargs)
    346 sleep_generator = exponential_sleep_generator(
    347     self._initial, self._maximum, multiplier=self._multiplier
    348 )
--> 349 return retry_target(
    350     target,
    351     self._predicate,
    352     sleep_generator,
    353     self._timeout,
    354     on_error=on_error,
    355 )

File /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:191, in retry_target(target, predicate, sleep_generator, timeout, on_error, **kwargs)
    189 for sleep in sleep_generator:
    190     try:
--> 191         return target()
    193     # pylint: disable=broad-except
    194     # This function explicitly must deal with broad exceptions.
    195     except Exception as exc:

File ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/_job_helpers.py:439, in query_and_wait.<locals>.do_query()
    437 # For easier testing, handle the retries ourselves.
    438 if retry is not None:
--> 439     response = retry(client._call_api)(
    440         retry=None,  # We're calling the retry decorator ourselves.
    441         span_name="BigQuery.query",
    442         span_attributes=span_attributes,
    443         method="POST",
    444         path=path,
    445         data=request_body,
    446         timeout=api_timeout,
    447     )
    448 else:
    449     response = client._call_api(
    450         retry=None,
    451         span_name="BigQuery.query",
   (...)
    456         timeout=api_timeout,
    457     )

File /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:349, in Retry.__call__.<locals>.retry_wrapped_func(*args, **kwargs)
    345 target = functools.partial(func, *args, **kwargs)
    346 sleep_generator = exponential_sleep_generator(
    347     self._initial, self._maximum, multiplier=self._multiplier
    348 )
--> 349 return retry_target(
    350     target,
    351     self._predicate,
    352     sleep_generator,
    353     self._timeout,
    354     on_error=on_error,
    355 )

File /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:191, in retry_target(target, predicate, sleep_generator, timeout, on_error, **kwargs)
    189 for sleep in sleep_generator:
    190     try:
--> 191         return target()
    193     # pylint: disable=broad-except
    194     # This function explicitly must deal with broad exceptions.
    195     except Exception as exc:

File ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/client.py:827, in Client._call_api(self, retry, span_name, span_attributes, job_ref, headers, **kwargs)
    823 if span_name is not None:
    824     with create_span(
    825         name=span_name, attributes=span_attributes, client=self, job_ref=job_ref
    826     ):
--> 827         return call()
    829 return call()

File /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/cloud/_http/__init__.py:494, in JSONConnection.api_request(self, method, path, query_params, data, content_type, headers, api_base_url, api_version, expect_json, _target_object, timeout, extra_api_info)
    482 response = self._make_request(
    483     method=method,
    484     url=url,
   (...)
    490     extra_api_info=extra_api_info,
    491 )
    493 if not 200 <= response.status_code < 300:
--> 494     raise exceptions.from_http_response(response)
    496 if expect_json and response.content:
    497     return response.json()

BadRequest: 400 POST https://bigquery.googleapis.com/bigquery/v2/projects/swast-scratch/queries?prettyPrint=false: Job exceeded rate limits: Your table exceeded quota for table update operations. For more information, see https://cloud.google.com/bigquery/docs/troubleshoot-quotas

In [5]: import sys

In [6]: exc = sys.last_value

In [7]: exc
Out[7]: google.api_core.exceptions.BadRequest('POST https://bigquery.googleapis.com/bigquery/v2/projects/swast-scratch/queries?prettyPrint=false: Job exceeded rate limits: Your table exceeded quota for table update operations. For more information, see https://cloud.google.com/bigquery/docs/troubleshoot-quotas')

In [8]: exc.reason

In [9]: exc.errors
Out[9]: 
[{'message': 'Job exceeded rate limits: Your table exceeded quota for table update operations. For more information, see https://cloud.google.com/bigquery/docs/troubleshoot-quotas',
  'domain': 'global',
  'reason': 'jobRateLimitExceeded'}]

In [10]: exc.errors[0]["reason"]
Out[10]: 'jobRateLimitExceeded'
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `google/cloud/bigquery/retry.py`
Content:
```
1 # Copyright 2018 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 #     http://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 from google.api_core import exceptions
16 from google.api_core import retry
17 from google.auth import exceptions as auth_exceptions  # type: ignore
18 import requests.exceptions
19 
20 
21 _RETRYABLE_REASONS = frozenset(
22     ["rateLimitExceeded", "backendError", "internalError", "badGateway"]
23 )
24 
25 _UNSTRUCTURED_RETRYABLE_TYPES = (
26     ConnectionError,
27     exceptions.TooManyRequests,
28     exceptions.InternalServerError,
29     exceptions.BadGateway,
30     exceptions.ServiceUnavailable,
31     requests.exceptions.ChunkedEncodingError,
32     requests.exceptions.ConnectionError,
33     requests.exceptions.Timeout,
34     auth_exceptions.TransportError,
35 )
36 
37 _DEFAULT_RETRY_DEADLINE = 10.0 * 60.0  # 10 minutes
38 
39 # Allow for a few retries after the API request times out. This relevant for
40 # rateLimitExceeded errors, which can be raised either by the Google load
41 # balancer or the BigQuery job server.
42 _DEFAULT_JOB_DEADLINE = 3.0 * _DEFAULT_RETRY_DEADLINE
43 
44 
45 def _should_retry(exc):
46     """Predicate for determining when to retry.
47 
48     We retry if and only if the 'reason' is 'backendError'
49     or 'rateLimitExceeded'.
50     """
51     if not hasattr(exc, "errors") or len(exc.errors) == 0:
52         # Check for unstructured error returns, e.g. from GFE
53         return isinstance(exc, _UNSTRUCTURED_RETRYABLE_TYPES)
54 
55     reason = exc.errors[0]["reason"]
56     return reason in _RETRYABLE_REASONS
57 
58 
59 DEFAULT_RETRY = retry.Retry(predicate=_should_retry, deadline=_DEFAULT_RETRY_DEADLINE)
60 """The default retry object.
61 
62 Any method with a ``retry`` parameter will be retried automatically,
63 with reasonable defaults. To disable retry, pass ``retry=None``.
64 To modify the default retry behavior, call a ``with_XXX`` method
65 on ``DEFAULT_RETRY``. For example, to change the deadline to 30 seconds,
66 pass ``retry=bigquery.DEFAULT_RETRY.with_deadline(30)``.
67 """
68 
69 DEFAULT_TIMEOUT = None
70 """The default API timeout.
71 
72 This is the time to wait per request. To adjust the total wait time, set a
73 deadline on the retry object.
74 """
75 
76 job_retry_reasons = "rateLimitExceeded", "backendError"
77 
78 
79 def _job_should_retry(exc):
80     if not hasattr(exc, "errors") or len(exc.errors) == 0:
81         return False
82 
83     reason = exc.errors[0]["reason"]
84     return reason in job_retry_reasons
85 
86 
87 DEFAULT_JOB_RETRY = retry.Retry(
88     predicate=_job_should_retry, deadline=_DEFAULT_JOB_DEADLINE
89 )
90 """
91 The default job retry object.
92 """
93
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/google/cloud/bigquery/retry.py b/google/cloud/bigquery/retry.py
--- a/google/cloud/bigquery/retry.py
+++ b/google/cloud/bigquery/retry.py
@@ -73,7 +73,7 @@
 deadline on the retry object.
 """
 
-job_retry_reasons = "rateLimitExceeded", "backendError"
+job_retry_reasons = "rateLimitExceeded", "backendError", "jobRateLimitExceeded"
 
 
 def _job_should_retry(exc):

{"golden_diff": "diff --git a/google/cloud/bigquery/retry.py b/google/cloud/bigquery/retry.py\n--- a/google/cloud/bigquery/retry.py\n+++ b/google/cloud/bigquery/retry.py\n@@ -73,7 +73,7 @@\n deadline on the retry object.\n \"\"\"\n \n-job_retry_reasons = \"rateLimitExceeded\", \"backendError\"\n+job_retry_reasons = \"rateLimitExceeded\", \"backendError\", \"jobRateLimitExceeded\"\n \n \n def _job_should_retry(exc):\n", "issue": "bug: client doesn't retry \"Job exceeded rate limits\" for DDL query jobs that exceed quota for table update operations \nIn https://github.com/googleapis/python-bigquery-sqlalchemy/pull/1009#discussion_r1457644849 it seems that the query in https://btx-internal.corp.google.com/invocations/ffafb866-6bc0-423f-a86b-df69fb270d57/targets/cloud-devrel%2Fclient-libraries%2Fpython%2Fgoogleapis%2Fpython-bigquery-sqlalchemy%2Fpresubmit%2Fprerelease-deps;config=default/log with rate limits exceeded errors are not retried.\r\n\r\n#### Environment details\r\n\r\n  - OS type and version:\r\n  - Python version: `python --version`\r\n  - pip version: `pip --version`\r\n  - `google-cloud-bigquery` version: `pip show google-cloud-bigquery`\r\n\r\n#### Steps to reproduce\r\n\r\nRun a DDL query more than 5 times in 10 seconds, violating the five table metadata update operations per 10 seconds per table limit (https://cloud.google.com/bigquery/quotas#standard_tables).\r\n\r\n#### Code example\r\n\r\n```python\r\nimport google.cloud.bigquery\r\nbqclient = google.cloud.bigquery.Client()\r\nsql = \"ALTER TABLE `swast-scratch.my_dataset.my_table` ADD COLUMN IF NOT EXISTS my_string_col STRING\"\r\nfor _ in range(100):\r\n    bqclient.query_and_wait(sql)\r\n```\r\n\r\n#### Stack trace\r\n\r\n```\r\nBadRequest                                Traceback (most recent call last)\r\nInput In [4], in <cell line: 1>()\r\n      1 for _ in range(100):\r\n----> 2     bqclient.query_and_wait(sql)\r\n\r\nFile ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/client.py:3503, in Client.query_and_wait(self, query, job_config, location, project, api_timeout, wait_timeout, retry, job_retry, page_size, max_results)\r\n   3497     _verify_job_config_type(job_config, QueryJobConfig)\r\n   3499 job_config = _job_helpers.job_config_with_defaults(\r\n   3500     job_config, self._default_query_job_config\r\n   3501 )\r\n-> 3503 return _job_helpers.query_and_wait(\r\n   3504     self,\r\n   3505     query,\r\n   3506     job_config=job_config,\r\n   3507     location=location,\r\n   3508     project=project,\r\n   3509     api_timeout=api_timeout,\r\n   3510     wait_timeout=wait_timeout,\r\n   3511     retry=retry,\r\n   3512     job_retry=job_retry,\r\n   3513     page_size=page_size,\r\n   3514     max_results=max_results,\r\n   3515 )\r\n\r\nFile ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/_job_helpers.py:498, in query_and_wait(client, query, job_config, location, project, api_timeout, wait_timeout, retry, job_retry, page_size, max_results)\r\n    481     return table.RowIterator(\r\n    482         client=client,\r\n    483         api_request=functools.partial(client._call_api, retry, timeout=api_timeout),\r\n   (...)\r\n    494         num_dml_affected_rows=query_results.num_dml_affected_rows,\r\n    495     )\r\n    497 if job_retry is not None:\r\n--> 498     return job_retry(do_query)()\r\n    499 else:\r\n    500     return do_query()\r\n\r\nFile /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:349, in Retry.__call__.<locals>.retry_wrapped_func(*args, **kwargs)\r\n    345 target = functools.partial(func, *args, **kwargs)\r\n    346 sleep_generator = exponential_sleep_generator(\r\n    347     self._initial, self._maximum, multiplier=self._multiplier\r\n    348 )\r\n--> 349 return retry_target(\r\n    350     target,\r\n    351     self._predicate,\r\n    352     sleep_generator,\r\n    353     self._timeout,\r\n    354     on_error=on_error,\r\n    355 )\r\n\r\nFile /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:191, in retry_target(target, predicate, sleep_generator, timeout, on_error, **kwargs)\r\n    189 for sleep in sleep_generator:\r\n    190     try:\r\n--> 191         return target()\r\n    193     # pylint: disable=broad-except\r\n    194     # This function explicitly must deal with broad exceptions.\r\n    195     except Exception as exc:\r\n\r\nFile ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/_job_helpers.py:439, in query_and_wait.<locals>.do_query()\r\n    437 # For easier testing, handle the retries ourselves.\r\n    438 if retry is not None:\r\n--> 439     response = retry(client._call_api)(\r\n    440         retry=None,  # We're calling the retry decorator ourselves.\r\n    441         span_name=\"BigQuery.query\",\r\n    442         span_attributes=span_attributes,\r\n    443         method=\"POST\",\r\n    444         path=path,\r\n    445         data=request_body,\r\n    446         timeout=api_timeout,\r\n    447     )\r\n    448 else:\r\n    449     response = client._call_api(\r\n    450         retry=None,\r\n    451         span_name=\"BigQuery.query\",\r\n   (...)\r\n    456         timeout=api_timeout,\r\n    457     )\r\n\r\nFile /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:349, in Retry.__call__.<locals>.retry_wrapped_func(*args, **kwargs)\r\n    345 target = functools.partial(func, *args, **kwargs)\r\n    346 sleep_generator = exponential_sleep_generator(\r\n    347     self._initial, self._maximum, multiplier=self._multiplier\r\n    348 )\r\n--> 349 return retry_target(\r\n    350     target,\r\n    351     self._predicate,\r\n    352     sleep_generator,\r\n    353     self._timeout,\r\n    354     on_error=on_error,\r\n    355 )\r\n\r\nFile /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/api_core/retry.py:191, in retry_target(target, predicate, sleep_generator, timeout, on_error, **kwargs)\r\n    189 for sleep in sleep_generator:\r\n    190     try:\r\n--> 191         return target()\r\n    193     # pylint: disable=broad-except\r\n    194     # This function explicitly must deal with broad exceptions.\r\n    195     except Exception as exc:\r\n\r\nFile ~/src/github.com/googleapis/python-bigquery/google/cloud/bigquery/client.py:827, in Client._call_api(self, retry, span_name, span_attributes, job_ref, headers, **kwargs)\r\n    823 if span_name is not None:\r\n    824     with create_span(\r\n    825         name=span_name, attributes=span_attributes, client=self, job_ref=job_ref\r\n    826     ):\r\n--> 827         return call()\r\n    829 return call()\r\n\r\nFile /opt/miniconda3/envs/dev-3.10/lib/python3.10/site-packages/google/cloud/_http/__init__.py:494, in JSONConnection.api_request(self, method, path, query_params, data, content_type, headers, api_base_url, api_version, expect_json, _target_object, timeout, extra_api_info)\r\n    482 response = self._make_request(\r\n    483     method=method,\r\n    484     url=url,\r\n   (...)\r\n    490     extra_api_info=extra_api_info,\r\n    491 )\r\n    493 if not 200 <= response.status_code < 300:\r\n--> 494     raise exceptions.from_http_response(response)\r\n    496 if expect_json and response.content:\r\n    497     return response.json()\r\n\r\nBadRequest: 400 POST https://bigquery.googleapis.com/bigquery/v2/projects/swast-scratch/queries?prettyPrint=false: Job exceeded rate limits: Your table exceeded quota for table update operations. For more information, see https://cloud.google.com/bigquery/docs/troubleshoot-quotas\r\n\r\nIn [5]: import sys\r\n\r\nIn [6]: exc = sys.last_value\r\n\r\nIn [7]: exc\r\nOut[7]: google.api_core.exceptions.BadRequest('POST https://bigquery.googleapis.com/bigquery/v2/projects/swast-scratch/queries?prettyPrint=false: Job exceeded rate limits: Your table exceeded quota for table update operations. For more information, see https://cloud.google.com/bigquery/docs/troubleshoot-quotas')\r\n\r\nIn [8]: exc.reason\r\n\r\nIn [9]: exc.errors\r\nOut[9]: \r\n[{'message': 'Job exceeded rate limits: Your table exceeded quota for table update operations. For more information, see https://cloud.google.com/bigquery/docs/troubleshoot-quotas',\r\n  'domain': 'global',\r\n  'reason': 'jobRateLimitExceeded'}]\r\n\r\nIn [10]: exc.errors[0][\"reason\"]\r\nOut[10]: 'jobRateLimitExceeded'\r\n```\n", "before_files": [{"content": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom google.api_core import exceptions\nfrom google.api_core import retry\nfrom google.auth import exceptions as auth_exceptions  # type: ignore\nimport requests.exceptions\n\n\n_RETRYABLE_REASONS = frozenset(\n    [\"rateLimitExceeded\", \"backendError\", \"internalError\", \"badGateway\"]\n)\n\n_UNSTRUCTURED_RETRYABLE_TYPES = (\n    ConnectionError,\n    exceptions.TooManyRequests,\n    exceptions.InternalServerError,\n    exceptions.BadGateway,\n    exceptions.ServiceUnavailable,\n    requests.exceptions.ChunkedEncodingError,\n    requests.exceptions.ConnectionError,\n    requests.exceptions.Timeout,\n    auth_exceptions.TransportError,\n)\n\n_DEFAULT_RETRY_DEADLINE = 10.0 * 60.0  # 10 minutes\n\n# Allow for a few retries after the API request times out. This relevant for\n# rateLimitExceeded errors, which can be raised either by the Google load\n# balancer or the BigQuery job server.\n_DEFAULT_JOB_DEADLINE = 3.0 * _DEFAULT_RETRY_DEADLINE\n\n\ndef _should_retry(exc):\n    \"\"\"Predicate for determining when to retry.\n\n    We retry if and only if the 'reason' is 'backendError'\n    or 'rateLimitExceeded'.\n    \"\"\"\n    if not hasattr(exc, \"errors\") or len(exc.errors) == 0:\n        # Check for unstructured error returns, e.g. from GFE\n        return isinstance(exc, _UNSTRUCTURED_RETRYABLE_TYPES)\n\n    reason = exc.errors[0][\"reason\"]\n    return reason in _RETRYABLE_REASONS\n\n\nDEFAULT_RETRY = retry.Retry(predicate=_should_retry, deadline=_DEFAULT_RETRY_DEADLINE)\n\"\"\"The default retry object.\n\nAny method with a ``retry`` parameter will be retried automatically,\nwith reasonable defaults. To disable retry, pass ``retry=None``.\nTo modify the default retry behavior, call a ``with_XXX`` method\non ``DEFAULT_RETRY``. For example, to change the deadline to 30 seconds,\npass ``retry=bigquery.DEFAULT_RETRY.with_deadline(30)``.\n\"\"\"\n\nDEFAULT_TIMEOUT = None\n\"\"\"The default API timeout.\n\nThis is the time to wait per request. To adjust the total wait time, set a\ndeadline on the retry object.\n\"\"\"\n\njob_retry_reasons = \"rateLimitExceeded\", \"backendError\"\n\n\ndef _job_should_retry(exc):\n    if not hasattr(exc, \"errors\") or len(exc.errors) == 0:\n        return False\n\n    reason = exc.errors[0][\"reason\"]\n    return reason in job_retry_reasons\n\n\nDEFAULT_JOB_RETRY = retry.Retry(\n    predicate=_job_should_retry, deadline=_DEFAULT_JOB_DEADLINE\n)\n\"\"\"\nThe default job retry object.\n\"\"\"\n", "path": "google/cloud/bigquery/retry.py"}], "after_files": [{"content": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom google.api_core import exceptions\nfrom google.api_core import retry\nfrom google.auth import exceptions as auth_exceptions  # type: ignore\nimport requests.exceptions\n\n\n_RETRYABLE_REASONS = frozenset(\n    [\"rateLimitExceeded\", \"backendError\", \"internalError\", \"badGateway\"]\n)\n\n_UNSTRUCTURED_RETRYABLE_TYPES = (\n    ConnectionError,\n    exceptions.TooManyRequests,\n    exceptions.InternalServerError,\n    exceptions.BadGateway,\n    exceptions.ServiceUnavailable,\n    requests.exceptions.ChunkedEncodingError,\n    requests.exceptions.ConnectionError,\n    requests.exceptions.Timeout,\n    auth_exceptions.TransportError,\n)\n\n_DEFAULT_RETRY_DEADLINE = 10.0 * 60.0  # 10 minutes\n\n# Allow for a few retries after the API request times out. This relevant for\n# rateLimitExceeded errors, which can be raised either by the Google load\n# balancer or the BigQuery job server.\n_DEFAULT_JOB_DEADLINE = 3.0 * _DEFAULT_RETRY_DEADLINE\n\n\ndef _should_retry(exc):\n    \"\"\"Predicate for determining when to retry.\n\n    We retry if and only if the 'reason' is 'backendError'\n    or 'rateLimitExceeded'.\n    \"\"\"\n    if not hasattr(exc, \"errors\") or len(exc.errors) == 0:\n        # Check for unstructured error returns, e.g. from GFE\n        return isinstance(exc, _UNSTRUCTURED_RETRYABLE_TYPES)\n\n    reason = exc.errors[0][\"reason\"]\n    return reason in _RETRYABLE_REASONS\n\n\nDEFAULT_RETRY = retry.Retry(predicate=_should_retry, deadline=_DEFAULT_RETRY_DEADLINE)\n\"\"\"The default retry object.\n\nAny method with a ``retry`` parameter will be retried automatically,\nwith reasonable defaults. To disable retry, pass ``retry=None``.\nTo modify the default retry behavior, call a ``with_XXX`` method\non ``DEFAULT_RETRY``. For example, to change the deadline to 30 seconds,\npass ``retry=bigquery.DEFAULT_RETRY.with_deadline(30)``.\n\"\"\"\n\nDEFAULT_TIMEOUT = None\n\"\"\"The default API timeout.\n\nThis is the time to wait per request. To adjust the total wait time, set a\ndeadline on the retry object.\n\"\"\"\n\njob_retry_reasons = \"rateLimitExceeded\", \"backendError\", \"jobRateLimitExceeded\"\n\n\ndef _job_should_retry(exc):\n    if not hasattr(exc, \"errors\") or len(exc.errors) == 0:\n        return False\n\n    reason = exc.errors[0][\"reason\"]\n    return reason in job_retry_reasons\n\n\nDEFAULT_JOB_RETRY = retry.Retry(\n    predicate=_job_should_retry, deadline=_DEFAULT_JOB_DEADLINE\n)\n\"\"\"\nThe default job retry object.\n\"\"\"\n", "path": "google/cloud/bigquery/retry.py"}]}