asio-grpc v1.6.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 [until v1.8.0] / the CompletionToken's completion handler [since v1.8.0]) 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:66
constexpr detail::RequestFn request
Start a new RPC.
Definition: rpc.hpp:1493
constexpr detail::FinishFn finish
Finish a RPC.
Definition: rpc.hpp:1529
constexpr detail::RepeatedlyRequestFn repeatedly_request
Register a request handler for a RPC.
Definition: repeatedlyRequest.hpp:146

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, class Alllocator>
struct AssociatedHandler
{
using executor_type = Executor;
using allocator_type = Alllocator;
Executor executor;
Handler handler;
Alllocator allocator;
AssociatedHandler(Executor executor, Handler handler, Alllocator allocator)
: executor(std::move(executor)), handler(std::move(handler)), allocator(allocator)
{
}
template <class T>
{
std::invoke(handler, std::move(request_context), executor);
}
[[nodiscard]] executor_type get_executor() const noexcept { return executor; }
[[nodiscard]] allocator_type get_allocator() const noexcept { return allocator; }
};
void repeatedly_request_example(example::v1::Example::AsyncService& service, agrpc::GrpcContext& grpc_context)
{
&example::v1::Example::AsyncService::RequestUnary, service,
AssociatedHandler{grpc_context.get_executor(),
[](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) {}));
},
grpc_context.get_allocator()});
}
allocator_type get_allocator() noexcept
Get the associated allocator.
Definition: grpcContext.ipp:91
executor_type get_executor() noexcept
Get the associated executor.
Definition: grpcContext.ipp:87
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:119
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.

Per-Operation Cancellation

All. Upon cancellation, the operation completes after receiving the next request from the client. The next request will still be handled normally.