Skip to content

Commit 54ec4fb

Browse files
impl(bq_driver): add max_retries impl
1 parent fe83580 commit 54ec4fb

16 files changed

Lines changed: 129 additions & 39 deletions

google/cloud/odbc/bq_client_interface/jobs.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,10 @@ StatusRecordOr<Job> GetJob(JobClient& job_client, std::string const& project_id,
120120
get_job_request.set_job_id(job_id);
121121
get_job_request.set_location(location);
122122
LOG(INFO) << "GetJob:: Request body: " << get_job_request.DebugString("");
123-
auto response = RetryLoop(
124-
[&] { return job_client.GetJob(get_job_request, options); }, "GetJob");
123+
auto max_retries = options.get<MaxRetriesOption>();
124+
auto response =
125+
RetryLoop([&] { return job_client.GetJob(get_job_request, options); },
126+
"GetJob", max_retries);
125127

126128
if (!response.ok()) {
127129
LOG(WARNING) << "GetJob:: Request failed: " << response.status();
@@ -248,8 +250,10 @@ StatusRecordOr<Job> InsertJob(JobClient& job_client,
248250
request.set_json_filter_keys(CreateKeysToFilterOut(job));
249251

250252
LOG(INFO) << "InsertJob:: Request body: " << request.DebugString("");
251-
auto response = RetryLoop(
252-
[&] { return job_client.InsertJob(request, options); }, "InsertJob");
253+
auto max_retries = options.get<MaxRetriesOption>();
254+
auto response =
255+
RetryLoop([&] { return job_client.InsertJob(request, options); },
256+
"InsertJob", max_retries);
253257

254258
if (!response.ok()) {
255259
LOG(WARNING) << "InsertJob:: Request failed: " << response.status();
@@ -277,8 +281,10 @@ StatusRecordOr<Job> CancelJob(JobClient& job_client,
277281
request.set_location(location);
278282
}
279283
LOG(INFO) << "CancelJob:: Request body: " << request.DebugString("");
280-
auto response = RetryLoop(
281-
[&] { return job_client.CancelJob(request, options); }, "CancelJob");
284+
auto max_retries = options.get<MaxRetriesOption>();
285+
auto response =
286+
RetryLoop([&] { return job_client.CancelJob(request, options); },
287+
"CancelJob", max_retries);
282288

283289
if (!response.ok()) {
284290
LOG(WARNING) << "CancelJob:: Request failed: " << response.status();
@@ -301,8 +307,10 @@ StatusRecordOr<PostQueryResults> Query(JobClient& job_client,
301307
post_query_request.set_json_filter_keys(CreateKeysToFilterOut(query_request));
302308

303309
LOG(INFO) << "Query:: Request body: " << post_query_request.DebugString("");
304-
auto response = RetryLoop(
305-
[&] { return job_client.Query(post_query_request, options); }, "Query");
310+
auto max_retries = options.get<MaxRetriesOption>();
311+
auto response =
312+
RetryLoop([&] { return job_client.Query(post_query_request, options); },
313+
"Query", max_retries);
306314

307315
if (!response.ok()) {
308316
LOG(WARNING) << "Query:: Request failed: " << response.status();
@@ -406,11 +414,12 @@ StatusRecordOr<GetQueryResults> FilterQueryResults(
406414

407415
LOG(INFO) << "FilterQueryResults:: Request body: "
408416
<< get_query_results_request.DebugString("");
417+
auto max_retries = options.get<MaxRetriesOption>();
409418
auto response = RetryLoop(
410419
[&] {
411420
return job_client.QueryResults(get_query_results_request, options);
412421
},
413-
"QueryResults");
422+
"QueryResults", max_retries);
414423

415424
if (!response.ok()) {
416425
LOG(WARNING) << "FilterQueryResults:: Request failed: "

google/cloud/odbc/bq_client_interface/tables.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ StatusRecordOr<Table> GetTable(TableClient& table_client,
4747

4848
LOG(INFO) << "GetTable:: Request body: " << request.DebugString("");
4949

50-
auto response = RetryLoop(
51-
[&] { return table_client.GetTable(request, options); }, "GetTable");
50+
auto max_retries = options.get<MaxRetriesOption>();
51+
auto response =
52+
RetryLoop([&] { return table_client.GetTable(request, options); },
53+
"GetTable", max_retries);
5254

5355
if (!response.ok()) {
5456
LOG(WARNING) << "GetTable:: Request failed: " << response.status();

google/cloud/odbc/bq_client_interface/utils.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include <string>
2323
#include <thread>
2424

25+
namespace google::cloud::odbc_bigquery_client_interface {
26+
struct MaxRetriesOption {
27+
using Type = int;
28+
};
29+
2530
// URL-encodes a value for safe use as a single path segment.
2631
inline std::string UrlEncodeSegment(std::string const& value) {
2732
std::ostringstream os;
@@ -38,11 +43,10 @@ inline std::string UrlEncodeSegment(std::string const& value) {
3843

3944
template <typename Functor>
4045
auto RetryLoop(Functor&& functor, std::string const& operation_name,
41-
int max_retries = 6, int initial_delay_ms = 500,
46+
int max_retries, int initial_delay_ms = 500,
4247
int max_delay_ms = 20000,
4348
double backoff_multiplier = 2.0) -> decltype(functor()) {
4449
int attempt = 0;
45-
4650
using ReturnType = decltype(functor());
4751
ReturnType response;
4852

@@ -85,5 +89,5 @@ auto RetryLoop(Functor&& functor, std::string const& operation_name,
8589

8690
return response;
8791
}
88-
92+
} // namespace google::cloud::odbc_bigquery_client_interface
8993
#endif // CPP_BIGQUERY_ODBC_GOOGLE_CLOUD_ODBC_BQ_CLIENT_INTERFACE_UTILS_H

google/cloud/odbc/bq_driver/internal/driver_adv_opt_form.cc

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ std::string AdvanceOptions::allow_large_results_;
6262
std::string AdvanceOptions::use_default_large_results_;
6363
std::string AdvanceOptions::encryption_type_ = kDefaultEncryptionType;
6464
std::string AdvanceOptions::max_threads_ = std::to_string(kDefaultMaxThreads);
65+
std::string AdvanceOptions::max_retries_ = std::to_string(kDefaultMaxRetries);
6566

6667
std::string const kLanguageDialect = "SQLDialect";
6768
std::string const kLargeResultsDatasetId = "LargeResultsDatasetId";
@@ -82,6 +83,7 @@ std::string const kUseDefaultLargeResultsDataset =
8283
"UseDefaultLargeResultsDataset";
8384
std::string const kEncryptionType = "EncryptionType";
8485
std::string const kMaxThreads = "MaxThreads";
86+
std::string const kMaxRetries = "MaxRetries";
8587

8688
// Control dimensions and positions
8789
int const kHeight = 20;
@@ -341,6 +343,21 @@ void AdvanceOptions::CreateAdditionalControls(HFONT h_font) {
341343
h_max_threads_edit, GWL_STYLE,
342344
GetWindowLongPtr(h_max_threads_edit, GWL_STYLE) | ES_RIGHT | ES_NUMBER);
343345

346+
// max retries
347+
HWND h_max_retries_label =
348+
CreateLabel(adv_hwnd, "Max Retries:", kXAxis, kYAxis + 390, kWidth * 7,
349+
kHeight, WS_VISIBLE | SS_LEFT);
350+
SendMessage(h_max_retries_label, WM_SETFONT, (WPARAM)h_font, TRUE);
351+
HWND h_max_retries_edit =
352+
CreateEditBox(adv_hwnd, kinputComboBoxXAxis, kYAxis + 390, kEditBoxWidth,
353+
kEditBoxHeight, kIdcMaxRetriesEdit);
354+
SendMessage(h_max_retries_edit, WM_SETFONT, (WPARAM)h_font, TRUE);
355+
SetWindowSubclass(GetDlgItem(adv_hwnd, kIdcMaxRetriesEdit), InputSubclassProc,
356+
0, 0);
357+
SetWindowText(h_max_retries_edit, max_retries_.c_str());
358+
SetWindowLongPtr(
359+
h_max_retries_edit, GWL_STYLE,
360+
GetWindowLongPtr(h_max_retries_edit, GWL_STYLE) | ES_RIGHT | ES_NUMBER);
344361
// TODO(b/497725655): Enable UI feature after public release
345362
// HWND h_variables_checkbox = CreateCheckBox(
346363
// adv_hwnd, "Use SQL_WVARCHAR instead of SQL_VARCHAR", kXAxis, kYAxis +
@@ -351,11 +368,11 @@ void AdvanceOptions::CreateAdditionalControls(HFONT h_font) {
351368
// SetWindowSubclass(GetDlgItem(adv_hwnd, kIdcVariableCheckbox),
352369
// CheckboxSubclassProc, 0, 0);
353370
HWND h_additional_projects_label =
354-
CreateLabel(adv_hwnd, "Additional projects:", kXAxis, kYAxis + 390,
371+
CreateLabel(adv_hwnd, "Additional projects:", kXAxis, kYAxis + 420,
355372
kWidth * 5, kHeight, WS_VISIBLE | SS_LEFT);
356373
SendMessage(h_additional_projects_label, WM_SETFONT, (WPARAM)h_font, TRUE);
357374
HWND h_additional_projects_edit =
358-
CreateScrollableEditBox(adv_hwnd, kXAxis, kYAxis + 410, kWidth + 380,
375+
CreateScrollableEditBox(adv_hwnd, kXAxis, kYAxis + 440, kWidth + 380,
359376
kHeight + 32, kIdcAdditionalProjectsEdit);
360377
SendMessage(h_additional_projects_edit, WM_SETFONT, (WPARAM)h_font, TRUE);
361378

@@ -364,11 +381,11 @@ void AdvanceOptions::CreateAdditionalControls(HFONT h_font) {
364381
InputSubclassProc, 0, 0);
365382

366383
HWND h_query_properties_label =
367-
CreateLabel(adv_hwnd, "Query properties:", kXAxis, kYAxis + 470,
384+
CreateLabel(adv_hwnd, "Query properties:", kXAxis, kYAxis + 500,
368385
kWidth * 5, kHeight, WS_VISIBLE | SS_LEFT);
369386
SendMessage(h_query_properties_label, WM_SETFONT, (WPARAM)h_font, TRUE);
370387
HWND h_query_properties_edit =
371-
CreateScrollableEditBox(adv_hwnd, kXAxis, kYAxis + 485, kWidth + 385,
388+
CreateScrollableEditBox(adv_hwnd, kXAxis, kYAxis + 520, kWidth + 385,
372389
kHeight + 13, kIdcQueryPropertiesEdit);
373390
SendMessage(h_query_properties_edit, WM_SETFONT, (WPARAM)h_font, TRUE);
374391

@@ -392,12 +409,12 @@ void AdvanceOptions::CreateAdditionalControls(HFONT h_font) {
392409
}
393410

394411
void AdvanceOptions::CreateButtons(HFONT h_font) {
395-
HWND h_ok_button = CreateButton(adv_hwnd, "OK", kOkButtonX + 2, kButtonY + 15,
412+
HWND h_ok_button = CreateButton(adv_hwnd, "OK", kOkButtonX + 2, kButtonY + 38,
396413
kButtonWidth, kButtonHeight, kIdcOKButton);
397414
SendMessage(h_ok_button, WM_SETFONT, (WPARAM)h_font, TRUE);
398415

399416
HWND h_cancel_button =
400-
CreateButton(adv_hwnd, "Cancel", kCancelButtonX, kButtonY + 15,
417+
CreateButton(adv_hwnd, "Cancel", kCancelButtonX, kButtonY + 38,
401418
kButtonWidth, kButtonHeight, kIdcCancelButton);
402419
SendMessage(h_cancel_button, WM_SETFONT, (WPARAM)h_font, TRUE);
403420
}
@@ -565,6 +582,20 @@ LRESULT CALLBACK AdvanceOptions::AdvanceOptProc(HWND hwnd, UINT u_msg,
565582
ShowErrorWindow(hwnd, err_msg);
566583
return true;
567584
}
585+
HWND h_max_retries_edit = GetDlgItem(hwnd, kIdcMaxRetriesEdit);
586+
char max_retries_buff[256] = {0};
587+
GetWindowText(h_max_retries_edit, max_retries_buff,
588+
sizeof(max_retries_buff));
589+
if (isValidUint32(max_retries_buff)) {
590+
max_retries_ = max_retries_buff;
591+
} else {
592+
std::string err_msg =
593+
"Invalid number of max retries: Valid values are in range [0," +
594+
std::to_string(UINT32_MAX) + "]";
595+
ShowErrorWindow(hwnd, err_msg);
596+
return true;
597+
}
598+
568599
HWND h_additional_projects_edit =
569600
GetDlgItem(hwnd, kIdcAdditionalProjectsEdit);
570601
char additional_projects_buffer[1024] = {0};
@@ -742,6 +773,7 @@ void AdvanceOptions::SetValues(Section const& attribute_map) {
742773
temp_expiration_ =
743774
GetValueOrDefault(attribute_map, kLargeResultsTempTableExpirationTime);
744775
max_threads_ = GetValueOrDefault(attribute_map, kMaxThreads);
776+
max_retries_ = GetValueOrDefault(attribute_map, kMaxRetries);
745777
session_location_ = GetValueOrDefault(attribute_map, kSessionLocation);
746778
additional_projects_ = GetValueOrDefault(attribute_map, kAdditionalProjects);
747779
query_properties_ = GetValueOrDefault(attribute_map, kQueryProperties);
@@ -766,6 +798,7 @@ void AdvanceOptions::ResetToDefaults() {
766798
rows_per_block_ = kDefaultRowsPerBlock;
767799
default_string_length_ = kDefaultStringLength;
768800
max_threads_ = std::to_string(kDefaultMaxThreads);
801+
max_retries_ = std::to_string(kDefaultMaxRetries);
769802
session_location_.clear();
770803
additional_projects_.clear();
771804
query_properties_.clear();
@@ -798,7 +831,7 @@ void AdvanceOptions::Show(HWND hwnd) {
798831
RegisterClass(&wc_adv);
799832

800833
int window_width = 462;
801-
int window_height = 620;
834+
int window_height = 650;
802835
int screen_width = GetSystemMetrics(SM_CXSCREEN);
803836
int screen_height = GetSystemMetrics(SM_CYSCREEN);
804837
int x_pos = (screen_width - window_width) / 2;

google/cloud/odbc/bq_driver/internal/driver_adv_opt_form.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static int const KIdcLargeResultHeader = 145;
4242
static int const kIdcEncryptionKeyComboBox = 146;
4343
static int const kIdcHyperlink2 = 147;
4444
static int const kIdcMaxThreadsEdit = 148;
45+
static int const kIdcMaxRetriesEdit = 149;
4546

4647
class AdvanceOptions {
4748
public:
@@ -96,6 +97,7 @@ class AdvanceOptions {
9697
return use_default_large_results_;
9798
}
9899
inline std::string const& GetMaxThreads() const { return max_threads_; }
100+
inline std::string const& GetMaxRetries() const { return max_retries_; }
99101
void SetValues(Section const& attributes_map);
100102
void ResetToDefaults();
101103

@@ -124,6 +126,7 @@ class AdvanceOptions {
124126
static std::string use_default_large_results_;
125127
static std::string encryption_type_;
126128
static std::string max_threads_;
129+
static std::string max_retries_;
127130

128131
static LRESULT CALLBACK AdvanceOptProc(HWND hwnd, UINT uMsg, WPARAM w_param,
129132
LPARAM l_param);

google/cloud/odbc/bq_driver/internal/driver_adv_opt_form_test.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ TEST_F(AdvanceOptionsTest, SetValuesValidinput) {
8383
{"AdditionalProjects", "projectA,projectB"},
8484
{"QueryProperties", "property1=value1"},
8585
{"HTAPI_ActivationThreshold", "10000"},
86-
{"MaxThreads", "10"}};
86+
{"MaxThreads", "10"},
87+
{"MaxRetries", "9"}};
8788

8889
AdvanceOptions options;
8990
options.SetValues(attribute_map);
@@ -98,7 +99,8 @@ TEST_F(AdvanceOptionsTest, SetValuesValidinput) {
9899
EXPECT_EQ(options.GetAdditionalProjects(), "projectA,projectB");
99100
EXPECT_EQ(options.GetQueryProperties(), "property1=value1");
100101
EXPECT_EQ(options.GetActivationThreshold(), "10000");
101-
EXPECT_EQ(options.GetMaxThreads(), "8");
102+
EXPECT_EQ(options.GetMaxThreads(), "10");
103+
EXPECT_EQ(options.GetMaxRetries(), "9");
102104
}
103105
TEST_F(AdvanceOptionsTest, SetValuesMissingkeys) {
104106
Section attribute_map = {
@@ -110,6 +112,7 @@ TEST_F(AdvanceOptionsTest, SetValuesMissingkeys) {
110112

111113
EXPECT_EQ(options.GetLanguageDialect(), "GoogleSQL");
112114
EXPECT_EQ(options.GetMaxThreads(), "8");
115+
EXPECT_EQ(options.GetMaxRetries(), "6");
113116
EXPECT_EQ(options.GetDatasetName(), "");
114117
EXPECT_EQ(options.GetEncryptionKey(), "");
115118
EXPECT_EQ(options.GetRowsPerBlock(), "");

google/cloud/odbc/bq_driver/internal/odbc_conn_handle.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ void ConnectionHandle::SetUp(Section& dsn_section,
134134
dsn_.max_threads =
135135
!max_threads.empty() ? std::stoull(max_threads) : kDefaultMaxThreads;
136136

137+
std::string max_retries = dsn_section["MAXRETRIES"];
138+
dsn_.max_retries =
139+
!max_retries.empty() ? std::stoull(max_retries) : kDefaultMaxRetries;
140+
137141
dsn_.pem_file = dsn_section["TRUSTEDCERTS"];
138142
dsn_.kms_key_name = dsn_section["KMSKEYNAME"];
139143
dsn_.session_location = dsn_section["SESSIONLOCATION"];

google/cloud/odbc/bq_driver/internal/odbc_conn_handle.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ using google::cloud::odbc_bigquery_client_interface::ODBCBQClient;
3131

3232
std::string const kDefaultDestDatasetId = "_bqodbc_temp_tables";
3333
std::string const kDefaultLargeResultsTableExpiration = "3600000";
34+
inline int const kDefaultMaxRetries = 6;
3435

3536
// Details of authentication provided in the odbc.ini/Windows Registry
3637
struct Authentication {
@@ -59,6 +60,7 @@ struct Dsn {
5960
// TODO(jsrinnn): Remove this if it is not being used.
6061
std::string refresh_token;
6162
std::uint32_t max_threads;
63+
std::uint32_t max_retries = kDefaultMaxRetries;
6264
bool is_bq_legacy_sql = false;
6365
bool is_job_creation_required = false;
6466
bool sessions_enabled = false;

google/cloud/odbc/bq_driver/internal/odbc_internal_commons.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include "google/cloud/odbc/bq_driver/internal/odbc_internal_commons.h"
16+
#include "google/cloud/odbc/bq_client_interface/utils.h"
1617
#include "google/cloud/odbc/bq_driver/internal/trace_utils.h"
1718
#include "google/cloud/odbc/bq_driver/internal/utils.h"
1819
#include <cmath>
@@ -41,6 +42,7 @@ using ::google::cloud::bigquery_v2_minimal_internal::TableFieldSchema;
4142
using ::google::cloud::bigquery_v2_minimal_internal::TableReference;
4243
#endif // (!defined(_WIN32) || defined(_WIN64)) && !defined(NO_ARROW)
4344
using ::google::cloud::bigquery_v2_minimal_internal::TableSchema;
45+
using google::cloud::odbc_bigquery_client_interface::MaxRetriesOption;
4446
using ::google::cloud::odbc_internal::SQLStates;
4547
using ::google::cloud::odbc_internal::StatusRecord;
4648
using ::google::cloud::odbc_internal::StatusRecordOr;
@@ -808,12 +810,13 @@ StatusRecordOr<Job> CancelBQJob(ConnectionHandle& conn_handle,
808810
}
809811

810812
Options options;
813+
options.set<MaxRetriesOption>(conn_handle.GetDsn().max_retries);
811814
return bq_client->CancelJob(project_id, job_id, location, options);
812815
}
813816

814817
StatusRecordOr<PostQueryResults> PostQueryWithoutResults(
815818
std::shared_ptr<ODBCBQClient> const& bq_client,
816-
PostQueryRequest const& post_query_request) {
819+
PostQueryRequest const& post_query_request, Options const& options) {
817820
if (!bq_client) {
818821
LOG(ERROR)
819822
<< "PostQueryWithoutResults:: Invalid or null BQ Client within the "
@@ -824,7 +827,6 @@ StatusRecordOr<PostQueryResults> PostQueryWithoutResults(
824827
}
825828
// For now , we use default options.
826829
// We can set timeout here as needed later.
827-
Options options;
828830
auto pq_status = bq_client->PostQuery(post_query_request, options);
829831
if (!pq_status) {
830832
LOG(ERROR) << "PostQueryWithoutResults::PostQuery:: "
@@ -843,8 +845,10 @@ StatusRecordOr<PostQueryResults> PostQueryWithoutResults(
843845
return StatusRecord{SQLStates::k_08S01(),
844846
"Connection to the data source is broken"};
845847
}
846-
auto pq_status =
847-
PostQueryWithoutResults(conn_handle.GetClient(), post_query_request);
848+
Options options;
849+
options.set<MaxRetriesOption>(conn_handle.GetDsn().max_retries);
850+
auto pq_status = PostQueryWithoutResults(conn_handle.GetClient(),
851+
post_query_request, options);
848852
if (!pq_status) {
849853
return pq_status.GetStatusRecord();
850854
}

google/cloud/odbc/bq_driver/internal/odbc_internal_commons.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,8 @@ odbc_internal::StatusRecordOr<
542542
PostQueryWithoutResults(
543543
std::shared_ptr<ODBCBQClient> const& bq_client,
544544
google::cloud::bigquery_v2_minimal_internal::PostQueryRequest const&
545-
post_query_request);
545+
post_query_request,
546+
Options const& options);
546547

547548
odbc_internal::StatusRecordOr<
548549
google::cloud::bigquery_v2_minimal_internal::PostQueryResults>

0 commit comments

Comments
 (0)