userver: ugrpc::server::GenericServiceBase Class Reference
Loading...
Searching...
No Matches
ugrpc::server::GenericServiceBase Class Referenceabstract

#include <userver/ugrpc/server/generic_service_base.hpp>

Detailed Description

Allows to handle RPCs with dynamic method names.

To use:

  1. inherit from this class in e.g. YourGenericService;
  2. put YourGenericService in a descendent of ServiceComponentBase, e.g. YourGenericServiceComponent

Alternatively, just inherit from GenericServiceBase::Component, with the disadvantage that the service will not be unit-testable.

The API is mainly intended for proxies, where the request-response body is passed unchanged, with settings taken solely from the RPC metadata. In cases where the code needs to operate on the actual messages, serialization of requests and responses is left as an exercise to the user.

Middlewares are customizable and are applied as usual, except that no message hooks are called, meaning that there won't be any logs of messages from the default middleware.

Statically-typed services, if registered, take priority over generic services. It only makes sense to register at most 1 generic service.

Generic gRPC service metrics

Metrics are accounted for "Generic/Generic" fake call name by default. This is the safe choice that avoids potential OOMs. To use the real dynamic RPC name for metrics, use CallAnyBase::SetMetricsCallName in conjunction with CallAnyBase::GetCallName.

Warning
If the microservice serves as a proxy and has untrusted clients, it is a good idea to avoid having per-RPC metrics to avoid the situations where an upstream client can spam various RPCs with non-existent names, which leads to this microservice spamming RPCs with non-existent names, which leads to creating storage for infinite metrics and causes OOM.

Example GenericServiceBase usage with known message types

constexpr std::string_view kSayHelloCallName = "sample.ugrpc.UnitTestService/SayHello";
class SampleGenericService final : public ugrpc::server::GenericServiceBase {
public:
GenericResult Handle(GenericCallContext& context, GenericReaderWriter& stream) override {
EXPECT_EQ(context.GetCallName(), kSayHelloCallName);
grpc::ByteBuffer request_bytes;
EXPECT_TRUE(stream.Read(request_bytes));
sample::ugrpc::GreetingRequest request;
if (!ugrpc::ParseFromByteBuffer(std::move(request_bytes), request)) {
return grpc::Status{grpc::StatusCode::INVALID_ARGUMENT, "Failed to parse request"};
}
sample::ugrpc::GreetingResponse response;
response.set_name("Hello " + request.name());
return ugrpc::SerializeToByteBuffer(response);
}
};

For a more complete sample, see grpc_generic_api.

Definition at line 59 of file generic_service_base.hpp.

Public Types

using Component = impl::ServiceComponentBase<GenericServiceBase>
 
using GenericCallContext = ugrpc::server::GenericCallContext
 
using GenericReaderWriter = ugrpc::server::ReaderWriter<grpc::ByteBuffer, grpc::ByteBuffer>
 
using GenericResult = ugrpc::server::StreamingResult<grpc::ByteBuffer>
 

Public Member Functions

 GenericServiceBase (GenericServiceBase &&)=delete
 
GenericServiceBaseoperator= (GenericServiceBase &&)=delete
 
virtual GenericResult Handle (GenericCallContext &context, GenericReaderWriter &stream)=0
 Override this method in the derived class to handle all RPCs. RPC name can be obtained through GenericCallContext::GetCallName.
 

Member Typedef Documentation

◆ Component

Inherits from both GenericServiceBase and ServiceComponentBase. Allows to implement the service directly in a component. The disadvantage is that such services are not unit-testable.

Definition at line 64 of file generic_service_base.hpp.

◆ GenericCallContext

◆ GenericReaderWriter

Definition at line 68 of file generic_service_base.hpp.

◆ GenericResult


The documentation for this class was generated from the following file: