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