-
Notifications
You must be signed in to change notification settings - Fork 286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: avoid unnecessary API call in QueryJob.result() when job is already finished #1900
Changes from 1 commit
0c9a8a2
07839b5
5112315
6297efd
e5990eb
fddb557
6a43cfd
12fa9fb
5149c25
4ee4975
08373bc
2a587aa
f7f1e81
e42d8ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -970,7 +970,12 @@ def test_result(self): | |
"rows": [{"f": [{"v": "abc"}]}], | ||
} | ||
conn = make_connection( | ||
query_resource, query_resource_done, job_resource_done, query_page_resource | ||
job_resource, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I am tracking the relationship between the make connection inputs versus the assert_has_calls checks. Can you explain how these tests are supposed to work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm guessing your question also relates to "Why this particular set of requests / responses?". I've added some comments explaining why we're expecting this sequence of API calls. I've also updated this test to more explicitly check for a possible cause of customer issue b/332850329. |
||
query_resource, | ||
job_resource, | ||
query_resource_done, | ||
job_resource_done, | ||
query_page_resource, | ||
) | ||
client = _make_client(self.PROJECT, connection=conn) | ||
job = self._get_target_class().from_api_repr(job_resource, client) | ||
|
@@ -1014,7 +1019,14 @@ def test_result(self): | |
timeout=None, | ||
) | ||
conn.api_request.assert_has_calls( | ||
[query_results_call, query_results_call, reload_call, query_page_call] | ||
[ | ||
reload_call, | ||
query_results_call, | ||
reload_call, | ||
query_results_call, | ||
reload_call, | ||
query_page_call, | ||
] | ||
) | ||
|
||
def test_result_dry_run(self): | ||
|
@@ -1254,9 +1266,13 @@ def test_result_w_retry(self): | |
} | ||
|
||
connection = make_connection( | ||
exceptions.NotFound("not normally retriable"), | ||
job_resource, | ||
exceptions.NotFound("not normally retriable"), | ||
query_resource, | ||
exceptions.NotFound("not normally retriable"), | ||
job_resource, | ||
exceptions.NotFound("not normally retriable"), | ||
query_resource_done, | ||
exceptions.NotFound("not normally retriable"), | ||
job_resource_done, | ||
|
@@ -1289,7 +1305,18 @@ def test_result_w_retry(self): | |
) | ||
|
||
connection.api_request.assert_has_calls( | ||
[query_results_call, query_results_call, reload_call] | ||
[ | ||
reload_call, | ||
chalmerlowe marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing here. Can I get some clarity on what we are doing and looking for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added some explanation here as well as above in the |
||
reload_call, | ||
query_results_call, | ||
query_results_call, | ||
reload_call, | ||
reload_call, | ||
query_results_call, | ||
query_results_call, | ||
reload_call, | ||
reload_call, | ||
] | ||
) | ||
|
||
def test_result_w_empty_schema(self): | ||
|
@@ -1316,37 +1343,6 @@ def test_result_w_empty_schema(self): | |
self.assertEqual(result.location, "asia-northeast1") | ||
self.assertEqual(result.query_id, "xyz-abc") | ||
|
||
def test_result_invokes_begins(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As of #967 released in google-cloud-bigquery 3.0.0, the _begin method is no longer used for query jobs. |
||
begun_resource = self._make_resource() | ||
incomplete_resource = { | ||
"jobComplete": False, | ||
"jobReference": {"projectId": self.PROJECT, "jobId": self.JOB_ID}, | ||
"schema": {"fields": [{"name": "col1", "type": "STRING"}]}, | ||
} | ||
query_resource = copy.deepcopy(incomplete_resource) | ||
query_resource["jobComplete"] = True | ||
done_resource = copy.deepcopy(begun_resource) | ||
done_resource["status"] = {"state": "DONE"} | ||
connection = make_connection( | ||
begun_resource, | ||
incomplete_resource, | ||
query_resource, | ||
done_resource, | ||
query_resource, | ||
) | ||
client = _make_client(project=self.PROJECT, connection=connection) | ||
job = self._make_one(self.JOB_ID, self.QUERY, client) | ||
|
||
job.result() | ||
|
||
self.assertEqual(len(connection.api_request.call_args_list), 4) | ||
begin_request = connection.api_request.call_args_list[0] | ||
query_request = connection.api_request.call_args_list[2] | ||
reload_request = connection.api_request.call_args_list[3] | ||
self.assertEqual(begin_request[1]["method"], "POST") | ||
self.assertEqual(query_request[1]["method"], "GET") | ||
self.assertEqual(reload_request[1]["method"], "GET") | ||
|
||
def test_result_w_timeout(self): | ||
import google.cloud.bigquery.client | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh oh, if
jobs.getQueryResults
fails because the job failed it can throw an exception butrestart_query_job
will still beFalse
.But we don't want
restart_query_job = True
because sometimes this can raise an ambiguous exception such as quota exceeded, where we don't know if it's the job quota and it's a failed job or at a higher level (Google Frontend - GFE) where the job might actually still be running and/or succeeded.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the worst way to fail, but it'd be nice to do the
jobs.get
call above in case of an exception to get a chance at retrying this job if the job failed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed #1903 to track improvements to ambiguous errors. 12fa9fb fixes an issue where we weren't actually retrying after an ambiguous failure even though we thought we were.