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

Commit 5b49464

Browse files
authored
fix: polling policy stops after 'too many' successes (#1427)
1 parent 3fb3832 commit 5b49464

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

google/cloud/spanner/internal/polling_loop.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,23 @@ typename ValueExtractor::ReturnType PollingLoopImpl(
130130
google::longrunning::GetOperationRequest poll_request;
131131
poll_request.set_name(operation.name());
132132
auto update = functor(poll_context, poll_request);
133-
if (!update) {
134-
if (!polling_policy->OnFailure(update.status())) {
135-
return std::move(update).status();
133+
if (update && update->done()) {
134+
// Before updating the polling policy make sure we do not discard a
135+
// successful result that completes the request.
136+
using std::swap;
137+
swap(*update, operation);
138+
break;
139+
}
140+
// Update the polling policy even on successful requests, so we can stop
141+
// after too many polling attempts.
142+
if (!polling_policy->OnFailure(update.status())) {
143+
if (update) {
144+
return Status(StatusCode::kDeadlineExceeded,
145+
"exhausted polling policy with no previous error");
136146
}
137-
} else {
147+
return std::move(update).status();
148+
}
149+
if (update) {
138150
using std::swap;
139151
swap(*update, operation);
140152
}

google/cloud/spanner/internal/polling_loop_test.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,23 @@ TEST(PollingLoopTest, FailureTooManyTransients) {
280280
EXPECT_EQ(StatusCode::kUnavailable, actual.status().code());
281281
}
282282

283+
TEST(PollingLoopTest, FailureTooManySuccesses) {
284+
google::longrunning::Operation operation;
285+
operation.set_name("test-operation");
286+
operation.set_done(false);
287+
288+
StatusOr<google::protobuf::Value> actual =
289+
PollingLoop<PollingLoopResponseExtractor<google::protobuf::Value>>(
290+
TestPollingPolicy(),
291+
[&operation](grpc::ClientContext&,
292+
google::longrunning::GetOperationRequest const&) {
293+
return StatusOr<google::longrunning::Operation>(operation);
294+
},
295+
operation, "location");
296+
EXPECT_EQ(StatusCode::kDeadlineExceeded, actual.status().code());
297+
EXPECT_THAT(actual.status().message(), HasSubstr("exhausted polling policy"));
298+
}
299+
283300
TEST(PollingLoopTest, FailureMissingResponseAndError) {
284301
google::longrunning::Operation operation;
285302
operation.set_name("test-operation");

0 commit comments

Comments
 (0)