8#include <google/protobuf/message.h>
10#include <userver/utils/assert.hpp>
12#include <userver/ugrpc/client/impl/async_stream_methods.hpp>
13#include <userver/ugrpc/client/impl/call_state.hpp>
14#include <userver/ugrpc/client/impl/middleware_pipeline.hpp>
16USERVER_NAMESPACE_BEGIN
18namespace ugrpc::client {
21template <
typename RawStream>
26 impl::StreamingCallState& state,
28 const google::protobuf::Message* recv_message
56 impl::StreamingCallState* state_{};
58 const google::protobuf::Message* recv_message_;
61template <
typename RawStream>
63 impl::StreamingCallState& state,
65 const google::protobuf::Message* recv_message
67 : state_{&state}, stream_{&stream}, recv_message_{recv_message} {}
69template <
typename RawStream>
72 : state_{std::exchange(other.state_,
nullptr)}, stream_{other.stream_}, recv_message_{other.recv_message_} {}
74template <
typename RawStream>
76 if (
this == &other)
return *
this;
77 [[maybe_unused]]
auto for_destruction = std::move(*
this);
79 state_ = std::exchange(other.state_,
nullptr);
80 stream_ = other.stream_;
81 recv_message_ = other.recv_message_;
85template <
typename RawStream>
89 impl::FinishAbandoned(*stream_, *state_);
93template <
typename RawStream>
95 UINVARIANT(state_,
"'Get' must be called only once");
96 const impl::StreamingCallState::AsyncMethodInvocationGuard guard(*state_);
97 auto*
const state = std::exchange(state_,
nullptr);
98 const auto result = impl::WaitAndTryCancelIfNeeded(state->GetAsyncMethodInvocation(), state->GetClientContext());
99 if (result == ugrpc::impl::AsyncMethodInvocation::WaitStatus::kCancelled) {
100 state->GetStatsScope().OnCancelled();
101 state->GetStatsScope().Flush();
102 }
else if (result == ugrpc::impl::AsyncMethodInvocation::WaitStatus::kError) {
105 impl::Finish(*stream_, *state,
nullptr,
true);
108 RunMiddlewarePipeline(*state, impl::RecvMessageHooks(*recv_message_));
111 return result == ugrpc::impl::AsyncMethodInvocation::WaitStatus::kOk;
114template <
typename RawStream>
116 UINVARIANT(state_,
"IsReady should be called only before 'Get'");
117 auto& method = state_->GetAsyncMethodInvocation();
118 return method.IsReady();