Skip to content
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
15 changes: 15 additions & 0 deletions generator/generator_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,21 @@ message ServiceConfiguration {
// RPCs. If set to false (the default), a no-op resumption function will be
// generated.
bool omit_streaming_updater = 29;

message BespokeMethod {
string name = 1;
string return_type = 2;
string parameters = 3;
}

// Only added to maintain feature parity when migrating from the handwritten
// Bigtable Table Admin class to the generated class. While some attempts were
// made to generalize this feature, it currently only supports the
// WaitForConsistency method. This functionality can be enhanced later if we
// ever need to use this again.
// The implementation for this method in the ConnectionImpl class is not
// generated and must be handwritten in a separate .cc file.
repeated BespokeMethod bespoke_methods = 30;
}

message DiscoveryDocumentDefinedProduct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ GoldenRestOnlyClient::Noop(google::protobuf::Empty const& request, Options opts)
return connection_->Noop(request);
}

StatusOr<google::protobuf::Empty> GoldenRestOnlyClient::WaitForConsistency(google::protobuf::Empty const& request, Options opts) {
internal::OptionsSpan span(internal::MergeOptions(std::move(opts), options_));
return connection_->WaitForConsistency(request);
}

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
} // namespace golden_v1
} // namespace cloud
Expand Down
31 changes: 31 additions & 0 deletions generator/integration_tests/golden/v1/golden_rest_only_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,37 @@ class GoldenRestOnlyClient {
Status
Noop(google::protobuf::Empty const& request, Options opts = {});


// clang-format off
///
/// Polls a table until it is consistent or the RetryPolicy is exhausted based
/// on a consistency token, that is, if replication has caught up based on the
/// provided conditions specified in the token and the check request.
///
/// @param request Unary RPCs, such as the one wrapped by this
/// function, receive a single `request` proto message which includes all
/// the inputs for the RPC. In this case, the proto message is a
/// [google.bigtable.admin.v2.CheckConsistencyRequest].
/// Proto messages are converted to C++ classes by Protobuf, using the
/// [Protobuf mapping rules].
/// @param opts Optional. Override the class-level options, such as retry and
/// backoff policies.
/// @return the result of the RPC. The response message type
/// ([google.bigtable.admin.v2.CheckConsistencyResponse])
/// is mapped to a C++ class using the [Protobuf mapping rules].
/// If the request fails, the [`StatusOr`] contains the error details.
///
/// [Protobuf mapping rules]: https://protobuf.dev/reference/cpp/cpp-generated/
/// [input iterator requirements]: https://en.cppreference.com/w/cpp/named_req/InputIterator
/// [`std::string`]: https://en.cppreference.com/w/cpp/string/basic_string
/// [`future`]: @ref google::cloud::future
/// [`StatusOr`]: @ref google::cloud::StatusOr
/// [`Status`]: @ref google::cloud::Status
/// [google.bigtable.admin.v2.CheckConsistencyRequest]: @googleapis_reference_link{google/bigtable/admin/v2/bigtable_table_admin.proto#L909}
/// [google.bigtable.admin.v2.CheckConsistencyResponse]: @googleapis_reference_link{google/bigtable/admin/v2/bigtable_table_admin.proto#L948}
///
// clang-format on
StatusOr<google::protobuf::Empty> WaitForConsistency(google::protobuf::Empty const& request, Options opts = {});
private:
std::shared_ptr<GoldenRestOnlyConnection> connection_;
Options options_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ GoldenRestOnlyConnection::Noop(
return Status(StatusCode::kUnimplemented, "not implemented");
}

StatusOr<google::protobuf::Empty> GoldenRestOnlyConnection::WaitForConsistency(google::protobuf::Empty const&) {
return StatusOr<google::protobuf::Empty>(
Status(StatusCode::kUnimplemented, "not implemented"));
}

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
} // namespace golden_v1
} // namespace cloud
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ class GoldenRestOnlyConnection {

virtual Status
Noop(google::protobuf::Empty const& request);

virtual StatusOr<google::protobuf::Empty> WaitForConsistency(google::protobuf::Empty const& request);
};

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
Expand Down
7 changes: 7 additions & 0 deletions generator/integration_tests/golden_config.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ service {
]
override_service_config_yaml_name: "generator/integration_tests/test2.yaml"
endpoint_location_style: LOCATION_OPTIONALLY_DEPENDENT
bespoke_methods : [
{
name: "WaitForConsistency",
return_type: "StatusOr<google::protobuf::Empty>",
parameters: "(google::protobuf::Empty const& request, Options opts = {})"
}
]
}

service {
Expand Down
59 changes: 59 additions & 0 deletions generator/internal/client_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,51 @@
#include "generator/internal/predicate_utils.h"
#include "generator/internal/printer.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "google/api/client.pb.h"
#include <google/protobuf/descriptor.h>

namespace google {
namespace cloud {
namespace generator_internal {
namespace {
std::string FormatBespokeMethodComments(std::string const& method_name) {
if (method_name == "WaitForConsistency") {
return R"""(
// clang-format off
///
/// Polls a table until it is consistent or the RetryPolicy is exhausted based
/// on a consistency token, that is, if replication has caught up based on the
/// provided conditions specified in the token and the check request.
///
/// @param request Unary RPCs, such as the one wrapped by this
/// function, receive a single `request` proto message which includes all
/// the inputs for the RPC. In this case, the proto message is a
/// [google.bigtable.admin.v2.CheckConsistencyRequest].
/// Proto messages are converted to C++ classes by Protobuf, using the
/// [Protobuf mapping rules].
/// @param opts Optional. Override the class-level options, such as retry and
/// backoff policies.
/// @return the result of the RPC. The response message type
/// ([google.bigtable.admin.v2.CheckConsistencyResponse])
/// is mapped to a C++ class using the [Protobuf mapping rules].
/// If the request fails, the [`StatusOr`] contains the error details.
///
/// [Protobuf mapping rules]: https://protobuf.dev/reference/cpp/cpp-generated/
/// [input iterator requirements]: https://en.cppreference.com/w/cpp/named_req/InputIterator
/// [`std::string`]: https://en.cppreference.com/w/cpp/string/basic_string
/// [`future`]: @ref google::cloud::future
/// [`StatusOr`]: @ref google::cloud::StatusOr
/// [`Status`]: @ref google::cloud::Status
/// [google.bigtable.admin.v2.CheckConsistencyRequest]: @googleapis_reference_link{google/bigtable/admin/v2/bigtable_table_admin.proto#L909}
/// [google.bigtable.admin.v2.CheckConsistencyResponse]: @googleapis_reference_link{google/bigtable/admin/v2/bigtable_table_admin.proto#L948}
///
// clang-format on
)""";
}
return "";
}
} // namespace

ClientGenerator::ClientGenerator(
google::protobuf::ServiceDescriptor const* service_descriptor,
Expand Down Expand Up @@ -380,6 +419,13 @@ R"""( std::unique_ptr<::google::cloud::AsyncStreamingReadWriteRpc<
__FILE__, __LINE__);
}

for (auto const& method : bespoke_methods()) {
HeaderPrint("\n");
HeaderPrint(FormatBespokeMethodComments(method.name()));
HeaderPrint(absl::StrCat(method.return_type(), " ", method.name(),
method.parameters(), ";"));
}

HeaderPrint( // clang-format off
"\n"
" private:\n"
Expand Down Expand Up @@ -716,6 +762,19 @@ std::unique_ptr<::google::cloud::AsyncStreamingReadWriteRpc<
__FILE__, __LINE__);
}

for (auto const& method : bespoke_methods()) {
CcPrint("\n");
CcPrint(absl::StrCat(
method.return_type(), R"""( $client_class_name$::)""", method.name(),
absl::StrReplaceAll(method.parameters(), {{" = {}", ""}}),
absl::StrFormat(R"""( {
internal::OptionsSpan span(internal::MergeOptions(std::move(opts), options_));
return connection_->%s(request);
}
)""",
method.name())));
}

CcCloseNamespaces();
return {};
}
Expand Down
6 changes: 6 additions & 0 deletions generator/internal/codegen_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ void ProcessArgOmitRpc(
ProcessRepeated("omit_rpc", "omitted_rpcs", command_line_args);
}

void ProcessArgBespokeMethod(
std::vector<std::pair<std::string, std::string>>& command_line_args) {
ProcessRepeated("bespoke_method", "bespoke_methods", command_line_args);
}

void ProcessArgServiceEndpointEnvVar(
std::vector<std::pair<std::string, std::string>>& command_line_args) {
auto service_endpoint_env_var =
Expand Down Expand Up @@ -269,6 +274,7 @@ ProcessCommandLineArgs(std::string const& parameters) {
ProcessArgCopyrightYear(command_line_args);
ProcessArgOmitService(command_line_args);
ProcessArgOmitRpc(command_line_args);
ProcessArgBespokeMethod(command_line_args);
ProcessArgServiceEndpointEnvVar(command_line_args);
ProcessArgEmulatorEndpointEnvVar(command_line_args);
ProcessArgEndpointLocationStyle(command_line_args);
Expand Down
29 changes: 29 additions & 0 deletions generator/internal/connection_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "generator/internal/pagination.h"
#include "generator/internal/predicate_utils.h"
#include "generator/internal/printer.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/str_split.h"
#include <google/protobuf/descriptor.h>

Expand Down Expand Up @@ -315,6 +316,14 @@ class $connection_class_name$ {
__FILE__, __LINE__);
}

for (auto const& method : bespoke_methods()) {
HeaderPrint("\n");
HeaderPrint(absl::StrCat(
" virtual ", method.return_type(), " ", method.name(),
absl::StrReplaceAll(method.parameters(), {{", Options opts = {}", ""}}),
";\n"));
}

// close abstract interface Connection base class
HeaderPrint("};\n");

Expand Down Expand Up @@ -490,6 +499,26 @@ future<StatusOr<$response_type$>>
__FILE__, __LINE__);
}

for (auto const& method : bespoke_methods()) {
CcPrint("\n");
std::string make_return =
absl::StrContains(method.return_type(), "future")
? absl::StrCat("google::cloud::make_ready_", method.return_type())
: method.return_type();

CcPrint(
absl::StrCat(method.return_type(), R"""( $connection_class_name$::)""",
method.name(),
absl::StrReplaceAll(method.parameters(),
{{" request, Options opts = {}", ""}}),
" {\n",
absl::StrFormat(R"""( return %s(
Status(StatusCode::kUnimplemented, "not implemented"));
}
)""",
make_return)));
}

if (HasGenerateGrpcTransport()) {
EmitFactoryFunctionDefinition(EndpointLocationStyle());
}
Expand Down
9 changes: 9 additions & 0 deletions generator/internal/connection_impl_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "generator/internal/predicate_utils.h"
#include "generator/internal/printer.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include <google/protobuf/descriptor.h>

namespace google {
Expand Down Expand Up @@ -120,6 +121,14 @@ class $connection_class_name$Impl
HeaderPrintMethod(method, __FILE__, __LINE__, AsyncMethodDeclaration());
}

for (auto const& method : bespoke_methods()) {
HeaderPrint("\n");
HeaderPrint(absl::StrCat(
method.return_type(), " ", method.name(),
absl::StrReplaceAll(method.parameters(), {{", Options opts = {}", ""}}),
" override;"));
}

HeaderPrint(R"""(
private:
std::unique_ptr<google::cloud::BackgroundThreads> background_;
Expand Down
14 changes: 14 additions & 0 deletions generator/internal/service_code_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,20 @@ void ServiceCodeGenerator::SetMethods() {
for (auto const& mixin_method : mixin_methods_) {
methods_.emplace_back(mixin_method.method.get());
}

auto bespoke_methods_var = service_vars_.find("bespoke_methods");
if (bespoke_methods_var != service_vars_.end()) {
auto methods = absl::StrSplit(bespoke_methods_var->second, ',');
for (auto const& method : methods) {
std::vector<std::string> pieces = absl::StrSplit(method, "@@");
assert(pieces.size() == 3);
cpp::generator::ServiceConfiguration::BespokeMethod bespoke_method;
bespoke_method.set_name(SafeReplaceAll(pieces[0], "@", ","));
bespoke_method.set_return_type(SafeReplaceAll(pieces[1], "@", ","));
bespoke_method.set_parameters(SafeReplaceAll(pieces[2], "@", ","));
bespoke_methods_.emplace_back(std::move(bespoke_method));
}
}
}

std::string ServiceCodeGenerator::GetPbIncludeByTransport() const {
Expand Down
6 changes: 6 additions & 0 deletions generator/internal/service_code_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ class ServiceCodeGenerator : public GeneratorInterface {
std::string vars(std::string const& key) const;
MethodDescriptorList const& methods() const { return methods_; }
MethodDescriptorList const& async_methods() const { return async_methods_; }
std::vector<cpp::generator::ServiceConfiguration::BespokeMethod> const&
bespoke_methods() const {
return bespoke_methods_;
}
void SetVars(absl::string_view header_path);
VarsDictionary MergeServiceAndMethodVars(
google::protobuf::MethodDescriptor const& method) const;
Expand Down Expand Up @@ -268,6 +272,8 @@ class ServiceCodeGenerator : public GeneratorInterface {
bool pb_h_system_includes_ = false;
MethodDescriptorList methods_;
MethodDescriptorList async_methods_;
std::vector<cpp::generator::ServiceConfiguration::BespokeMethod>
bespoke_methods_;
Printer header_;
Printer cc_;
std::vector<MixinMethod> mixin_methods_;
Expand Down
8 changes: 8 additions & 0 deletions generator/standalone_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ std::vector<std::future<google::cloud::Status>> GenerateCodeFromProtos(
args.emplace_back(absl::StrCat("--cpp_codegen_opt=omit_rpc=",
SafeReplaceAll(omit_rpc, ",", "@")));
}
for (auto const& bespoke_method : service.bespoke_methods()) {
args.emplace_back(absl::StrCat(
"--cpp_codegen_opt=bespoke_method=",
absl::StrJoin({SafeReplaceAll(bespoke_method.name(), ",", "@"),
SafeReplaceAll(bespoke_method.return_type(), ",", "@"),
SafeReplaceAll(bespoke_method.parameters(), ",", "@")},
"@@")));
}
for (auto const& retry_code : service.retryable_status_codes()) {
args.emplace_back("--cpp_codegen_opt=retry_status_code=" + retry_code);
}
Expand Down