Skip to content

Commit 0dfde77

Browse files
authored
refactor(common): move longrunning to value functions (#6820)
I am planning to re-use these functions for the non-async case, so it seems reasonable to split them to a separate file.
1 parent baec5f6 commit 0dfde77

8 files changed

Lines changed: 151 additions & 74 deletions

google/cloud/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,6 @@ if (GOOGLE_CLOUD_CPP_ENABLE_GRPC)
390390
grpc_utils/version.h
391391
internal/async_connection_ready.cc
392392
internal/async_connection_ready.h
393-
internal/async_long_running_operation.cc
394393
internal/async_long_running_operation.h
395394
internal/async_polling_loop.cc
396395
internal/async_polling_loop.h
@@ -404,6 +403,8 @@ if (GOOGLE_CLOUD_CPP_ENABLE_GRPC)
404403
internal/completion_queue_impl.h
405404
internal/default_completion_queue_impl.cc
406405
internal/default_completion_queue_impl.h
406+
internal/extract_long_running_result.cc
407+
internal/extract_long_running_result.h
407408
internal/grpc_access_token_authentication.cc
408409
internal/grpc_access_token_authentication.h
409410
internal/grpc_async_access_token_cache.cc
@@ -535,6 +536,7 @@ if (GOOGLE_CLOUD_CPP_ENABLE_GRPC)
535536
internal/async_retry_loop_test.cc
536537
internal/async_retry_unary_rpc_test.cc
537538
internal/background_threads_impl_test.cc
539+
internal/extract_long_running_result_test.cc
538540
internal/grpc_access_token_authentication_test.cc
539541
internal/grpc_async_access_token_cache_test.cc
540542
internal/grpc_channel_credentials_authentication_test.cc

google/cloud/google_cloud_cpp_grpc_utils.bzl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ google_cloud_cpp_grpc_utils_hdrs = [
3838
"internal/background_threads_impl.h",
3939
"internal/completion_queue_impl.h",
4040
"internal/default_completion_queue_impl.h",
41+
"internal/extract_long_running_result.h",
4142
"internal/grpc_access_token_authentication.h",
4243
"internal/grpc_async_access_token_cache.h",
4344
"internal/grpc_channel_credentials_authentication.h",
@@ -63,10 +64,10 @@ google_cloud_cpp_grpc_utils_srcs = [
6364
"grpc_error_delegate.cc",
6465
"grpc_options.cc",
6566
"internal/async_connection_ready.cc",
66-
"internal/async_long_running_operation.cc",
6767
"internal/async_polling_loop.cc",
6868
"internal/background_threads_impl.cc",
6969
"internal/default_completion_queue_impl.cc",
70+
"internal/extract_long_running_result.cc",
7071
"internal/grpc_access_token_authentication.cc",
7172
"internal/grpc_async_access_token_cache.cc",
7273
"internal/grpc_channel_credentials_authentication.cc",

google/cloud/google_cloud_cpp_grpc_utils_unit_tests.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ google_cloud_cpp_grpc_utils_unit_tests = [
2828
"internal/async_retry_loop_test.cc",
2929
"internal/async_retry_unary_rpc_test.cc",
3030
"internal/background_threads_impl_test.cc",
31+
"internal/extract_long_running_result_test.cc",
3132
"internal/grpc_access_token_authentication_test.cc",
3233
"internal/grpc_async_access_token_cache_test.cc",
3334
"internal/grpc_channel_credentials_authentication_test.cc",

google/cloud/internal/async_long_running_operation.h

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "google/cloud/future.h"
2121
#include "google/cloud/internal/async_polling_loop.h"
2222
#include "google/cloud/internal/async_retry_loop.h"
23+
#include "google/cloud/internal/extract_long_running_result.h"
2324
#include "google/cloud/polling_policy.h"
2425
#include "google/cloud/status_or.h"
2526
#include "google/cloud/version.h"
@@ -35,31 +36,6 @@ namespace cloud {
3536
inline namespace GOOGLE_CLOUD_CPP_NS {
3637
namespace internal {
3738

38-
/// Extracts the value (or error) from a completed long-running operation
39-
Status ExtractOperationResultImpl(
40-
StatusOr<google::longrunning::Operation> op,
41-
google::protobuf::Message& result,
42-
absl::FunctionRef<bool(google::protobuf::Any const&)> validate_any,
43-
std::string const& location);
44-
45-
/**
46-
* Extracts the value from a completed long-running operation.
47-
*
48-
* This helper is used in `AsyncLongRunningOperation()` to extract the value (or
49-
* error) from a completed long-running operation.
50-
*/
51-
template <typename ReturnType>
52-
StatusOr<ReturnType> ExtractLongRunningResult(
53-
StatusOr<google::longrunning::Operation> op, std::string const& location) {
54-
ReturnType result;
55-
auto status = ExtractOperationResultImpl(
56-
std::move(op), result,
57-
[](google::protobuf::Any const& any) { return any.Is<ReturnType>(); },
58-
location);
59-
if (!status.ok()) return status;
60-
return result;
61-
}
62-
6339
/**
6440
* Asynchronously starts and polls a long-running operation.
6541
*

google/cloud/internal/async_long_running_operation_test.cc

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ using ::google::bigtable::admin::v2::Instance;
3030
using ::google::cloud::testing_util::IsOk;
3131
using ::google::cloud::testing_util::IsProtoEqual;
3232
using ::google::cloud::testing_util::MockCompletionQueueImpl;
33-
using ::google::cloud::testing_util::StatusIs;
3433
using ::google::longrunning::Operation;
35-
using ::testing::HasSubstr;
3634
using ::testing::Return;
3735

3836
class MockStub {
@@ -70,50 +68,6 @@ std::unique_ptr<BackoffPolicy> TestBackoffPolicy() {
7068
return ExponentialBackoffPolicy(us(100), us(100), 2.0).clone();
7169
}
7270

73-
TEST(AsyncLongRunningTest, ExtractValueDoneWithSuccess) {
74-
Instance expected;
75-
expected.set_name("test-instance-admin");
76-
google::longrunning::Operation op;
77-
op.set_done(true);
78-
op.mutable_metadata()->PackFrom(expected);
79-
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
80-
ASSERT_STATUS_OK(actual);
81-
EXPECT_THAT(*actual, IsProtoEqual(expected));
82-
}
83-
84-
TEST(AsyncLongRunningTest, ExtractValueDoneWithError) {
85-
google::longrunning::Operation op;
86-
op.set_done(true);
87-
op.mutable_error()->set_code(grpc::StatusCode::PERMISSION_DENIED);
88-
op.mutable_error()->set_message("uh-oh");
89-
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
90-
EXPECT_THAT(actual,
91-
StatusIs(StatusCode::kPermissionDenied, HasSubstr("uh-oh")));
92-
}
93-
94-
TEST(AsyncLongRunningTest, ExtractValueDoneWithoutResult) {
95-
google::longrunning::Operation op;
96-
op.set_done(true);
97-
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
98-
EXPECT_THAT(actual, StatusIs(StatusCode::kInternal));
99-
}
100-
101-
TEST(AsyncLongRunningTest, ExtractValueDoneWithInvalidContent) {
102-
google::longrunning::Operation op;
103-
op.set_done(true);
104-
op.mutable_metadata()->PackFrom(google::protobuf::Empty{});
105-
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
106-
EXPECT_THAT(actual, StatusIs(StatusCode::kInternal));
107-
}
108-
109-
TEST(AsyncLongRunningTest, ExtractValueError) {
110-
auto const expected = Status{StatusCode::kPermissionDenied, "uh-oh"};
111-
auto const actual =
112-
ExtractLongRunningResult<Instance>(expected, "test-function");
113-
ASSERT_THAT(actual, Not(IsOk()));
114-
EXPECT_EQ(expected, actual.status());
115-
}
116-
11771
TEST(AsyncLongRunningTest, RequestPollThenSuccess) {
11872
Instance expected;
11973
expected.set_name("test-instance-name");

google/cloud/internal/async_long_running_operation.cc renamed to google/cloud/internal/extract_long_running_result.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "google/cloud/internal/async_long_running_operation.h"
15+
#include "google/cloud/internal/extract_long_running_result.h"
1616
#include "google/cloud/grpc_error_delegate.h"
1717

1818
namespace google {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2021 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+
#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_EXTRACT_LONG_RUNNING_RESULT_H
16+
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_EXTRACT_LONG_RUNNING_RESULT_H
17+
18+
#include "google/cloud/status_or.h"
19+
#include "google/cloud/version.h"
20+
#include "absl/functional/function_ref.h"
21+
#include <google/longrunning/operations.pb.h>
22+
#include <google/protobuf/any.h>
23+
#include <string>
24+
25+
namespace google {
26+
namespace cloud {
27+
inline namespace GOOGLE_CLOUD_CPP_NS {
28+
namespace internal {
29+
30+
/// Extracts the value (or error) from a completed long-running operation
31+
Status ExtractOperationResultImpl(
32+
StatusOr<google::longrunning::Operation> op,
33+
google::protobuf::Message& result,
34+
absl::FunctionRef<bool(google::protobuf::Any const&)> validate_any,
35+
std::string const& location);
36+
37+
/**
38+
* Extracts the value from a completed long-running operation.
39+
*
40+
* This helper is used in `AsyncLongRunningOperation()` to extract the value (or
41+
* error) from a completed long-running operation.
42+
*/
43+
template <typename ReturnType>
44+
StatusOr<ReturnType> ExtractLongRunningResult(
45+
StatusOr<google::longrunning::Operation> op, std::string const& location) {
46+
ReturnType result;
47+
auto status = ExtractOperationResultImpl(
48+
std::move(op), result,
49+
[](google::protobuf::Any const& any) { return any.Is<ReturnType>(); },
50+
location);
51+
if (!status.ok()) return status;
52+
return result;
53+
}
54+
55+
} // namespace internal
56+
} // namespace GOOGLE_CLOUD_CPP_NS
57+
} // namespace cloud
58+
} // namespace google
59+
60+
#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_EXTRACT_LONG_RUNNING_RESULT_H
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2021 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+
#include "google/cloud/internal/extract_long_running_result.h"
16+
#include "google/cloud/testing_util/is_proto_equal.h"
17+
#include "google/cloud/testing_util/mock_completion_queue_impl.h"
18+
#include "google/cloud/testing_util/status_matchers.h"
19+
#include <google/bigtable/admin/v2/bigtable_instance_admin.pb.h>
20+
#include <gmock/gmock.h>
21+
22+
namespace google {
23+
namespace cloud {
24+
inline namespace GOOGLE_CLOUD_CPP_NS {
25+
namespace internal {
26+
namespace {
27+
28+
using ::google::bigtable::admin::v2::Instance;
29+
using ::google::cloud::testing_util::IsOk;
30+
using ::google::cloud::testing_util::IsProtoEqual;
31+
using ::google::cloud::testing_util::StatusIs;
32+
using ::google::longrunning::Operation;
33+
using ::testing::HasSubstr;
34+
35+
TEST(ExtractLongRunningResultTest, DoneWithSuccess) {
36+
Instance expected;
37+
expected.set_name("test-instance-admin");
38+
google::longrunning::Operation op;
39+
op.set_done(true);
40+
op.mutable_metadata()->PackFrom(expected);
41+
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
42+
ASSERT_STATUS_OK(actual);
43+
EXPECT_THAT(*actual, IsProtoEqual(expected));
44+
}
45+
46+
TEST(ExtractLongRunningResultTest, DoneWithError) {
47+
google::longrunning::Operation op;
48+
op.set_done(true);
49+
op.mutable_error()->set_code(grpc::StatusCode::PERMISSION_DENIED);
50+
op.mutable_error()->set_message("uh-oh");
51+
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
52+
EXPECT_THAT(actual,
53+
StatusIs(StatusCode::kPermissionDenied, HasSubstr("uh-oh")));
54+
}
55+
56+
TEST(ExtractLongRunningResultTest, DoneWithoutResult) {
57+
google::longrunning::Operation op;
58+
op.set_done(true);
59+
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
60+
EXPECT_THAT(actual, StatusIs(StatusCode::kInternal));
61+
}
62+
63+
TEST(ExtractLongRunningResultTest, DoneWithInvalidContent) {
64+
google::longrunning::Operation op;
65+
op.set_done(true);
66+
op.mutable_metadata()->PackFrom(google::protobuf::Empty{});
67+
auto const actual = ExtractLongRunningResult<Instance>(op, "test-function");
68+
EXPECT_THAT(actual, StatusIs(StatusCode::kInternal));
69+
}
70+
71+
TEST(ExtractLongRunningResultTest, Error) {
72+
auto const expected = Status{StatusCode::kPermissionDenied, "uh-oh"};
73+
auto const actual =
74+
ExtractLongRunningResult<Instance>(expected, "test-function");
75+
ASSERT_THAT(actual, Not(IsOk()));
76+
EXPECT_EQ(expected, actual.status());
77+
}
78+
79+
} // namespace
80+
} // namespace internal
81+
} // namespace GOOGLE_CLOUD_CPP_NS
82+
} // namespace cloud
83+
} // namespace google

0 commit comments

Comments
 (0)