userver: userver/ugrpc/client/graceful_stream_finish.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
graceful_stream_finish.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @brief Utilities to gracefully finish streams
5
6#include <cstddef>
7#include <exception>
8#include <optional>
9
10#include <userver/logging/log.hpp>
11#include <userver/ugrpc/client/impl/graceful_stream_finish.hpp>
12#include <userver/ugrpc/client/rpc.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace ugrpc::client {
17
18/// @brief Read all remaining messages from the stream and call `Finish`.
19///
20/// @warning The method will hang indefenitely if the stream
21/// is never interrupted or closed by the server
22///
23/// @return the number of messages received from the stream;
24/// nullopt if the operation failed (i.e. due to task
25/// cancellation, the stream being already closed for reads,
26/// or the server returning an error status)
27template <typename Response>
28std::optional<std::size_t> ReadRemainingAndFinish(InputStream<Response>& stream) noexcept {
29 return impl::ReadRemainingAndFinish<InputStream<Response>, Response>(stream);
30}
31
32/// @brief Announce end-of-input to the server, read all
33/// remaining messages from the stream and call `Finish`.
34///
35/// @warning The method will hang indefenitely if the stream
36/// is never interrupted or closed by the server
37///
38/// @return the number of messages received from the stream;
39/// nullopt if the operation failed (i.e. due to task
40/// cancellation, the stream being already closed for
41/// either reads or writes, or the server returning an error status)
42template <typename Request, typename Response>
43std::optional<std::size_t> ReadRemainingAndFinish(BidirectionalStream<Request, Response>& stream) noexcept {
44 const bool writes_done_success = stream.WritesDone();
45 const std::optional<std::size_t> messages_remaining =
46 impl::ReadRemainingAndFinish<BidirectionalStream<Request, Response>, Response>(stream);
47 return writes_done_success ? messages_remaining : std::nullopt;
48}
49
50/// @brief Gracefully finish a ping-pong style interaction
51///
52/// 1. Announces end-of-output to the server
53/// 2. Ensures there are no more messages to read
54///
55/// @warning The method will hang indefenitely if the stream
56/// is never interrupted or closed by the server
57///
58/// @return true if the operation was successful; false if there are more messages
59/// in the stream to read or if the operation failed (i.e. due to task
60/// cancellation, the stream being already closed for writes,
61/// or the server returning an error status)
62template <typename Request, typename Response>
63[[nodiscard]] bool PingPongFinish(BidirectionalStream<Request, Response>& stream) noexcept {
64 try {
65 const bool writes_done_success = stream.WritesDone();
66
67 Response response;
68 if (!stream.Read(response)) {
69 // As expected, there are no more messages in the stream
70 return writes_done_success;
71 }
72
73 LOG_WARNING() << "PingPongFinish: there are more messages to read from the stream";
74 return false;
75 } catch (const std::exception& e) {
76 LOG_WARNING() << "PingPongFinish: failed to close the stream - " << e;
77 return false;
78 }
79}
80
81} // namespace ugrpc::client
82
83USERVER_NAMESPACE_END