asio-grpc v1.4.0
Asynchronous gRPC with Asio/unified executors
agrpc::detail::RepeatedlyRequestFn Class Reference

Server-side function object to register request handlers. More...

#include <agrpc/repeatedlyRequest.hpp>

Public Member Functions

template<class RPC , class Service , class Request , class Responder , class RequestHandler , class CompletionToken = detail::NoOp>
auto operator() (detail::ServerMultiArgRequest< RPC, Request, Responder > rpc, Service &service, RequestHandler &&request_handler, CompletionToken &&token={}) const
 Overload for unary and server-streaming RPCs.
 
template<class RPC , class Service , class Responder , class RequestHandler , class CompletionToken = detail::NoOp>
auto operator() (detail::ServerSingleArgRequest< RPC, Responder > rpc, Service &service, RequestHandler &&request_handler, CompletionToken &&token={}) const
 Overload for client-streaming and bidirectional RPCs.
 

Detailed Description

Server-side function object to register request handlers.

The examples below are based on the following .proto file:

syntax = "proto3";
package example.v1;
service Example {
rpc ServerStreaming(Request) returns (stream Response) {}
rpc ClientStreaming(stream Request) returns (Response) {}
rpc BidirectionalStreaming(stream Request) returns (stream Response) {}
rpc Unary(Request) returns (Response) {}
}
message Request {
int32 integer = 1;
}
message Response {
int32 integer = 1;
}

This function helps to ensure that there are enough outstanding calls to request to match incoming RPCs. It takes a RPC, a Service, a RequestHandler and a CompletionToken. The RequestHandler determines what to do with a client request, it could e.g. spawn a new coroutine to process it. It must also have an associated executor that refers to a agrpc::GrpcContext. When the client makes a request the RequestHandler is invoked with a agrpc::RepeatedlyRequestContext - a move-only type that provides a stable address to the grpc::ServerContext, the request (if any) and the responder that were used when requesting the RPC. It should be kept alive until the RPC is finished. The RequestHandler or its associated executor may also have an associated allocator to control the allocation needed for each request.

agrpc::repeatedly_request will complete when it was cancelled, the agrpc::GrpcContext was stopped or the grpc::Server been shutdown. It will not wait until all outstanding RPCs that are being processed by the RequestHandler have completed.

When using the special CompletionToken created by agrpc::use_sender the RequestHandler's signature must be:
sender auto operator()(grpc::ServerContext&, Request&, Responder&) for unary and server-streaming requests and
sender auto operator()(grpc::ServerContext&, Responder&) otherwise.
For libunifex this is the only available overload of this function.

auto register_client_streaming_handler(example::v1::Example::AsyncService& service, agrpc::GrpcContext& grpc_context)
{
&example::v1::Example::AsyncService::RequestUnary, service,
[&](grpc::ServerContext&, example::v1::Request& request,
grpc::ServerAsyncResponseWriter<example::v1::Response>& writer)
{
return unifex::let_value(unifex::just(example::v1::Response{}),
[&](auto& response)
{
response.set_integer(request.integer());
return agrpc::finish(writer, response, grpc::Status::OK,
agrpc::use_sender(grpc_context));
});
},
agrpc::use_sender(grpc_context));
}
Execution context based on grpc::CompletionQueue
Definition: grpcContext.hpp:50
constexpr detail::UseSenderFn use_sender
Create sender completion token.
Definition: useSender.hpp:65
constexpr detail::RequestFn request
Start a new RPC.
Definition: rpc.hpp:1394
constexpr detail::FinishFn finish
Finish a RPC.
Definition: rpc.hpp:1430
constexpr detail::RepeatedlyRequestFn repeatedly_request
Register a request handler for a RPC.
Definition: repeatedlyRequest.hpp:140

Another special overload of agrpc::repeatedly_request can be used by passing a RequestHandler with the following signature:
awaitable auto operator()(grpc::ServerContext&, Request&, Responder&) for unary and server-streaming requests and
awaitable auto operator()(grpc::ServerContext&, Responder&) otherwise.

void register_client_streaming_handler(example::v1::Example::AsyncService& service, agrpc::GrpcContext& grpc_context)
{
&example::v1::Example::AsyncService::RequestClientStreaming, service,
asio::bind_executor(
grpc_context,
[&](grpc::ServerContext&,
grpc::ServerAsyncReader<example::v1::Response, example::v1::Request>&) -> asio::awaitable<void>
{
// ...
co_return;
}));
}

The following example shows how to implement a RequestHandler with a custom allocator for simple, high-performance RPC processing:

template <class Executor, class Handler>
struct AssociatedHandler
{
using executor_type = Executor;
Executor executor;
Handler handler;
AssociatedHandler(Executor executor, Handler handler) : executor(std::move(executor)), handler(std::move(handler))
{
}
template <class T>
{
std::invoke(handler, std::move(request_context), executor);
}
[[nodiscard]] executor_type get_executor() const noexcept { return executor; }
};
void repeatedly_request_example(example::v1::Example::AsyncService& service, agrpc::GrpcContext& grpc_context)
{
&example::v1::Example::AsyncService::RequestUnary, service,
AssociatedHandler{
asio::require(grpc_context.get_executor(), asio::execution::allocator(grpc_context.get_allocator())),
[](auto&& request_context, auto&& executor)
{
auto& writer = request_context.responder();
example::v1::Response response;
agrpc::finish(writer, response, grpc::Status::OK,
asio::bind_executor(executor, [c = std::move(request_context)](bool) {}));
}});
}
allocator_type get_allocator() noexcept
Get the associated allocator.
Definition: grpcContext.ipp:92
executor_type get_executor() noexcept
Get the associated executor.
Definition: grpcContext.ipp:88
Context passed to the request handler of repeatedly_request.
Definition: repeatedlyRequestContext.hpp:41
auto operator()(detail::ServerMultiArgRequest< RPC, Request, Responder > rpc, Service &service, RequestHandler &&request_handler, CompletionToken &&token={}) const
Overload for unary and server-streaming RPCs.
Definition: repeatedlyRequest.hpp:113
Parameters
request_handlerAny exception thrown by the invocation of the request handler will be rethrown by GrpcContext::run(). Except for the sender version, where the exception will be send to the receiver.
tokenThe completion signature is void(). If the token has been created by agrpc::use_sender then the request handler must return a sender.