mirror of https://github.com/grpc/grpc.git
[generic API] separate callback from cq in generic stub/service (#36447)
See https://github.com/grpc/proposal/pull/426
<!--
If you know who should review your pull request, please assign it to that
person, otherwise the pull request would get assigned randomly.
If your pull request is for a specific language, please add the appropriate
lang label.
-->
Closes #36447
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36447 from yousukseung:generic-stub-service-refactor 1cc0cbdc4b
PiperOrigin-RevId: 642774012
pull/36817/head^2
parent
f7ce3ee9d5
commit
568fbfff8c
11 changed files with 326 additions and 125 deletions
@ -0,0 +1,84 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef GRPCPP_GENERIC_CALLBACK_GENERIC_SERVICE_H |
||||
#define GRPCPP_GENERIC_CALLBACK_GENERIC_SERVICE_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
#include <grpcpp/impl/server_callback_handlers.h> |
||||
#include <grpcpp/support/byte_buffer.h> |
||||
#include <grpcpp/support/server_callback.h> |
||||
|
||||
struct grpc_server; |
||||
|
||||
namespace grpc { |
||||
|
||||
/// \a ServerGenericBidiReactor is the reactor class for bidi streaming RPCs
|
||||
/// invoked on a CallbackGenericService. It is just a ServerBidi reactor with
|
||||
/// ByteBuffer arguments.
|
||||
using ServerGenericBidiReactor = ServerBidiReactor<ByteBuffer, ByteBuffer>; |
||||
|
||||
class GenericCallbackServerContext final : public grpc::CallbackServerContext { |
||||
public: |
||||
const std::string& method() const { return method_; } |
||||
const std::string& host() const { return host_; } |
||||
|
||||
private: |
||||
friend class grpc::Server; |
||||
|
||||
std::string method_; |
||||
std::string host_; |
||||
}; |
||||
|
||||
/// \a CallbackGenericService is the base class for generic services implemented
|
||||
/// using the callback API and registered through the ServerBuilder using
|
||||
/// RegisterCallbackGenericService.
|
||||
class CallbackGenericService { |
||||
public: |
||||
CallbackGenericService() {} |
||||
virtual ~CallbackGenericService() {} |
||||
|
||||
/// The "method handler" for the generic API. This function should be
|
||||
/// overridden to provide a ServerGenericBidiReactor that implements the
|
||||
/// application-level interface for this RPC. Unimplemented by default.
|
||||
virtual ServerGenericBidiReactor* CreateReactor( |
||||
GenericCallbackServerContext* /*ctx*/) { |
||||
class Reactor : public ServerGenericBidiReactor { |
||||
public: |
||||
Reactor() { this->Finish(Status(StatusCode::UNIMPLEMENTED, "")); } |
||||
void OnDone() override { delete this; } |
||||
}; |
||||
return new Reactor; |
||||
} |
||||
|
||||
private: |
||||
friend class grpc::Server; |
||||
|
||||
internal::CallbackBidiHandler<ByteBuffer, ByteBuffer>* Handler() { |
||||
return new internal::CallbackBidiHandler<ByteBuffer, ByteBuffer>( |
||||
[this](grpc::CallbackServerContext* ctx) { |
||||
return CreateReactor(static_cast<GenericCallbackServerContext*>(ctx)); |
||||
}); |
||||
} |
||||
|
||||
grpc::Server* server_{nullptr}; |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCPP_GENERIC_CALLBACK_GENERIC_SERVICE_H
|
@ -0,0 +1,44 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef GRPCPP_GENERIC_GENERIC_STUB_CALLBACK_H |
||||
#define GRPCPP_GENERIC_GENERIC_STUB_CALLBACK_H |
||||
|
||||
#include <grpcpp/impl/generic_stub_internal.h> |
||||
#include <grpcpp/support/byte_buffer.h> |
||||
|
||||
namespace grpc { |
||||
|
||||
/// Generic stubs provide a type-unaware interface to call gRPC methods
|
||||
/// by name. In practice, the Request and Response types should be basic
|
||||
/// types like grpc::ByteBuffer or proto::MessageLite (the base protobuf).
|
||||
template <class RequestType, class ResponseType> |
||||
class TemplatedGenericStubCallback final |
||||
: public internal::TemplatedGenericStubCallbackInternal<RequestType, |
||||
ResponseType> { |
||||
public: |
||||
using internal::TemplatedGenericStubCallbackInternal< |
||||
RequestType, ResponseType>::TemplatedGenericStubCallbackInternal; |
||||
}; |
||||
|
||||
typedef TemplatedGenericStubCallback<grpc::ByteBuffer, grpc::ByteBuffer> |
||||
GenericStubCallback; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCPP_GENERIC_GENERIC_STUB_CALLBACK_H
|
@ -0,0 +1,125 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef GRPCPP_IMPL_GENERIC_STUB_INTERNAL_H |
||||
#define GRPCPP_IMPL_GENERIC_STUB_INTERNAL_H |
||||
|
||||
#include <functional> |
||||
|
||||
#include <grpcpp/client_context.h> |
||||
#include <grpcpp/impl/rpc_method.h> |
||||
#include <grpcpp/support/byte_buffer.h> |
||||
#include <grpcpp/support/client_callback.h> |
||||
#include <grpcpp/support/status.h> |
||||
#include <grpcpp/support/stub_options.h> |
||||
|
||||
namespace grpc { |
||||
|
||||
template <class RequestType, class ResponseType> |
||||
class TemplatedGenericStub; |
||||
template <class RequestType, class ResponseType> |
||||
class TemplatedGenericStubCallback; |
||||
|
||||
namespace internal { |
||||
|
||||
/// Generic stubs provide a type-unaware interface to call gRPC methods
|
||||
/// by name. In practice, the Request and Response types should be basic
|
||||
/// types like grpc::ByteBuffer or proto::MessageLite (the base protobuf).
|
||||
template <class RequestType, class ResponseType> |
||||
class TemplatedGenericStubCallbackInternal { |
||||
public: |
||||
explicit TemplatedGenericStubCallbackInternal( |
||||
std::shared_ptr<grpc::ChannelInterface> channel) |
||||
: channel_(channel) {} |
||||
|
||||
/// Setup and start a unary call to a named method \a method using
|
||||
/// \a context and specifying the \a request and \a response buffers.
|
||||
void UnaryCall(ClientContext* context, const std::string& method, |
||||
StubOptions options, const RequestType* request, |
||||
ResponseType* response, |
||||
std::function<void(grpc::Status)> on_completion) { |
||||
UnaryCallInternal(context, method, options, request, response, |
||||
std::move(on_completion)); |
||||
} |
||||
|
||||
/// Setup a unary call to a named method \a method using
|
||||
/// \a context and specifying the \a request and \a response buffers.
|
||||
/// Like any other reactor-based RPC, it will not be activated until
|
||||
/// StartCall is invoked on its reactor.
|
||||
void PrepareUnaryCall(ClientContext* context, const std::string& method, |
||||
StubOptions options, const RequestType* request, |
||||
ResponseType* response, ClientUnaryReactor* reactor) { |
||||
PrepareUnaryCallInternal(context, method, options, request, response, |
||||
reactor); |
||||
} |
||||
|
||||
/// Setup a call to a named method \a method using \a context and tied to
|
||||
/// \a reactor . Like any other bidi streaming RPC, it will not be activated
|
||||
/// until StartCall is invoked on its reactor.
|
||||
void PrepareBidiStreamingCall( |
||||
ClientContext* context, const std::string& method, StubOptions options, |
||||
ClientBidiReactor<RequestType, ResponseType>* reactor) { |
||||
PrepareBidiStreamingCallInternal(context, method, options, reactor); |
||||
} |
||||
|
||||
private: |
||||
template <class Req, class Resp> |
||||
friend class grpc::TemplatedGenericStub; |
||||
template <class Req, class Resp> |
||||
friend class grpc::TemplatedGenericStubCallback; |
||||
std::shared_ptr<grpc::ChannelInterface> channel_; |
||||
|
||||
void UnaryCallInternal(ClientContext* context, const std::string& method, |
||||
StubOptions options, const RequestType* request, |
||||
ResponseType* response, |
||||
std::function<void(grpc::Status)> on_completion) { |
||||
internal::CallbackUnaryCall( |
||||
channel_.get(), |
||||
grpc::internal::RpcMethod(method.c_str(), options.suffix_for_stats(), |
||||
grpc::internal::RpcMethod::NORMAL_RPC), |
||||
context, request, response, std::move(on_completion)); |
||||
} |
||||
|
||||
void PrepareUnaryCallInternal(ClientContext* context, |
||||
const std::string& method, StubOptions options, |
||||
const RequestType* request, |
||||
ResponseType* response, |
||||
ClientUnaryReactor* reactor) { |
||||
internal::ClientCallbackUnaryFactory::Create<RequestType, ResponseType>( |
||||
channel_.get(), |
||||
grpc::internal::RpcMethod(method.c_str(), options.suffix_for_stats(), |
||||
grpc::internal::RpcMethod::NORMAL_RPC), |
||||
context, request, response, reactor); |
||||
} |
||||
|
||||
void PrepareBidiStreamingCallInternal( |
||||
ClientContext* context, const std::string& method, StubOptions options, |
||||
ClientBidiReactor<RequestType, ResponseType>* reactor) { |
||||
internal::ClientCallbackReaderWriterFactory<RequestType, ResponseType>:: |
||||
Create(channel_.get(), |
||||
grpc::internal::RpcMethod( |
||||
method.c_str(), options.suffix_for_stats(), |
||||
grpc::internal::RpcMethod::BIDI_STREAMING), |
||||
context, reactor); |
||||
} |
||||
}; |
||||
|
||||
} // namespace internal
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCPP_IMPL_GENERIC_STUB_INTERNAL_H
|
Loading…
Reference in new issue