Skip to content
This repository has been archived by the owner on Dec 8, 2021. It is now read-only.

feat: allow users to configure retry policies #1111

Merged
merged 2 commits into from
Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion google/cloud/spanner/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,22 @@ StatusOr<PartitionedDmlResult> Client::ExecutePartitionedDml(

std::shared_ptr<Connection> MakeConnection(Database const& db,
ConnectionOptions const& options) {
return MakeConnection(db, options, internal::DefaultConnectionRetryPolicy(),
internal::DefaultConnectionBackoffPolicy());
}

std::shared_ptr<Connection> MakeConnection(
Database const& db, ConnectionOptions const& options,
std::unique_ptr<RetryPolicy> retry_policy,
std::unique_ptr<BackoffPolicy> backoff_policy) {
std::vector<std::shared_ptr<internal::SpannerStub>> stubs;
int num_channels = std::min(options.num_channels(), 1);
stubs.reserve(num_channels);
for (int channel_id = 0; channel_id < num_channels; ++channel_id) {
stubs.push_back(internal::CreateDefaultSpannerStub(options, channel_id));
}
return internal::MakeConnection(db, std::move(stubs));
return internal::MakeConnection(db, std::move(stubs), std::move(retry_policy),
std::move(backoff_policy));
}

} // namespace SPANNER_CLIENT_NS
Expand Down
14 changes: 14 additions & 0 deletions google/cloud/spanner/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,20 @@ class Client {
std::shared_ptr<Connection> MakeConnection(
Database const& db, ConnectionOptions const& options = ConnectionOptions());

/**
* @copydoc MakeConnection(Database const&, ConnectionOptions const&)
*
* @param retry_policy override the default `RetryPolicy`, controls for how long
* does the returned `Connection` object retry requests on transient
* failures.
* @param backoff_policy override the default `BackoffPolicy`, controls for how
* long does the `Connection` object waits before retrying a failed request.
*/
std::shared_ptr<Connection> MakeConnection(
Database const& db, ConnectionOptions const& options,
std::unique_ptr<RetryPolicy> retry_policy,
std::unique_ptr<BackoffPolicy> backoff_policy);

} // namespace SPANNER_CLIENT_NS
} // namespace spanner
} // namespace cloud
Expand Down
2 changes: 2 additions & 0 deletions google/cloud/spanner/doc/spanner-main.dox
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ The default policies are to continue retrying for up to 15 minutes, and to
use truncated (at 5 minutes) exponential backoff, doubling the maximum backoff
period between retries.

@snippet samples.cc custom-retry-policy

@see [LimitedTimeRetryPolicy](@ref google::cloud::spanner::v0::LimitedTimeRetryPolicy)
and [LimitedErrorCountRetryPolicy](@ref google::cloud::spanner::v0::LimitedErrorCountRetryPolicy)
for alternative retry policies.
Expand Down
43 changes: 43 additions & 0 deletions google/cloud/spanner/samples/samples.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,44 @@ void ExampleStatusOr(google::cloud::spanner::Client client) {
(std::move(client));
}

void CustomRetryPolicy(std::vector<std::string> argv) {
if (argv.size() != 3) {
throw std::runtime_error(
"custom-retry-policy <project-id> <instance-id> <database-id>");
}
//! [custom-retry-policy]
namespace spanner = google::cloud::spanner;
[](std::string const& project_id, std::string const& instance_id,
std::string const& database_id) {
auto client = spanner::Client(spanner::MakeConnection(
spanner::Database(project_id, instance_id, database_id),
spanner::ConnectionOptions{},
// Retry for at most 25 minutes.
spanner::LimitedTimeRetryPolicy(
/*maximum_duration=*/std::chrono::minutes(25))
.clone(),
// Use an truncated exponential backoff with jitter to wait between
// retries:
// https://en.wikipedia.org/wiki/Exponential_backoff
// https://cloud.google.com/storage/docs/exponential-backoff
spanner::ExponentialBackoffPolicy(
/*initial_delay=*/std::chrono::seconds(2),
/*maximum_delay=*/std::chrono::minutes(10),
/*scaling=*/1.5)
.clone()));

auto rows =
client.ExecuteQuery(spanner::SqlStatement("SELECT 'Hello World'"));

for (auto const& row : spanner::StreamOf<std::tuple<std::string>>(rows)) {
if (!row) throw std::runtime_error(row.status().message());
std::cout << std::get<0>(*row) << "\n";
}
}
//! [custom-retry-policy]
(argv[0], argv[1], argv[2]);
}

class RemoteConnectionFake {
public:
void SendBinaryStringData(std::string const& serialized_partition) {
Expand Down Expand Up @@ -1835,6 +1873,7 @@ int RunOneCommand(std::vector<std::string> argv) {
make_command_entry("partition-read", &PartitionRead),
make_command_entry("partition-query", &PartitionQuery),
make_command_entry("example-status-or", &ExampleStatusOr),
{"custom-retry-policy", &CustomRetryPolicy},
};

static std::string usage_msg = [&argv, &commands] {
Expand Down Expand Up @@ -2086,6 +2125,10 @@ void RunAll() {
std::cout << "\nRunning example-status-or sample\n";
ExampleStatusOr(client);

std::cout << "\nRunning custom-retry-policy sample\n";
RunOneCommand(
{"", "custom-retry-policy", project_id, instance_id, database_id});

std::cout << "\nRunning spanner_dml_partitioned_update sample\n";
DmlPartitionedUpdate(client);

Expand Down