userver: userver/ugrpc/server/generic_service_base.hpp Source File
Loading...
Searching...
No Matches
generic_service_base.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/ugrpc/server/generic_service_base.hpp
4/// @brief @copybrief ugrpc::server::GenericServiceBase
5
6#include <grpcpp/support/byte_buffer.h>
7
8#include <userver/ugrpc/server/call_context.hpp>
9#include <userver/ugrpc/server/result.hpp>
10#include <userver/ugrpc/server/service_component_base.hpp>
11#include <userver/ugrpc/server/stream.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace ugrpc::server {
16
17/// @brief Allows to handle RPCs with dynamic method names.
18///
19/// To use:
20///
21/// 1. inherit from this class in e.g. `YourGenericService`;
22/// 2. put `YourGenericService` in a descendent of @ref ServiceComponentBase,
23/// e.g. `YourGenericServiceComponent`
24///
25/// Alternatively, just inherit from @ref GenericServiceBase::Component, with
26/// the disadvantage that the service will not be unit-testable.
27///
28/// The API is mainly intended for proxies, where the request-response body is
29/// passed unchanged, with settings taken solely from the RPC metadata.
30/// In cases where the code needs to operate on the actual messages,
31/// serialization of requests and responses is left as an exercise to the user.
32///
33/// Middlewares are customizable and are applied as usual, except that no
34/// message hooks are called, meaning that there won't be any logs of messages
35/// from the default middleware.
36///
37/// Statically-typed services, if registered, take priority over generic
38/// services. It only makes sense to register at most 1 generic service.
39///
40/// ## Generic gRPC service metrics
41///
42/// Metrics are accounted for `"Generic/Generic"` fake call name by default.
43/// This is the safe choice that avoids potential OOMs.
44/// To use the real dynamic RPC name for metrics, use
45/// @ref CallAnyBase::SetMetricsCallName in conjunction with
46/// @ref CallAnyBase::GetCallName.
47///
48/// @warning If the microservice serves as a proxy and has untrusted clients, it
49/// is a good idea to avoid having per-RPC metrics to avoid the
50/// situations where an upstream client can spam various RPCs with non-existent
51/// names, which leads to this microservice spamming RPCs with non-existent
52/// names, which leads to creating storage for infinite metrics and causes OOM.
53///
54/// ## Example GenericServiceBase usage with known message types
55///
56/// @snippet grpc/tests/generic_server_test.cpp sample
57///
58/// For a more complete sample, see @ref grpc_generic_api.
60public:
61 /// Inherits from both @ref GenericServiceBase and @ref ServiceComponentBase.
62 /// Allows to implement the service directly in a component.
63 /// The disadvantage is that such services are not unit-testable.
64 using Component = impl::ServiceComponentBase<GenericServiceBase>;
65
66 using GenericCallContext = ugrpc::server::GenericCallContext;
67
68 using GenericReaderWriter = ugrpc::server::ReaderWriter<grpc::ByteBuffer, grpc::ByteBuffer>;
69 using GenericResult = ugrpc::server::StreamingResult<grpc::ByteBuffer>;
70
71 GenericServiceBase(GenericServiceBase&&) = delete;
72 GenericServiceBase& operator=(GenericServiceBase&&) = delete;
73 virtual ~GenericServiceBase();
74
75 /// @brief Override this method in the derived class to handle all RPCs.
76 /// RPC name can be obtained through @ref GenericCallContext::GetCallName.
77 virtual GenericResult Handle(GenericCallContext& context, GenericReaderWriter& stream) = 0;
78
79protected:
80 GenericServiceBase() = default;
81};
82
83} // namespace ugrpc::server
84
85USERVER_NAMESPACE_END