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