userver: userver/server/request/response_base.hpp Source File
Loading...
Searching...
No Matches
response_base.hpp
1#pragma once
2
3#include <atomic>
4#include <chrono>
5#include <functional>
6#include <limits>
7#include <optional>
8#include <string>
9#include <unordered_map>
10
11#include <userver/concurrent/striped_counter.hpp>
12#include <userver/utils/fast_pimpl.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace engine::io {
17class RwBase;
18} // namespace engine::io
19
20namespace server::request {
21
22class ResponseDataAccounter final {
23 public:
24 void StartRequest(size_t size,
25 std::chrono::steady_clock::time_point create_time);
26
27 void StopRequest(size_t size,
28 std::chrono::steady_clock::time_point create_time);
29
30 size_t GetCurrentLevel() const { return current_; }
31
32 size_t GetMaxLevel() const { return max_; }
33
34 void SetMaxLevel(size_t size) { max_ = size; }
35
36 std::chrono::milliseconds GetAvgRequestTime() const;
37
38 private:
39 std::atomic<size_t> current_{0};
40 std::atomic<size_t> max_{std::numeric_limits<size_t>::max()};
41 concurrent::StripedCounter count_;
42 concurrent::StripedCounter time_sum_;
43};
44
45/// @brief Base class for all the server responses.
46class ResponseBase {
47 public:
48 explicit ResponseBase(ResponseDataAccounter& data_accounter);
49 ResponseBase(const ResponseBase&) = delete;
50 ResponseBase(ResponseBase&&) = delete;
51 virtual ~ResponseBase() noexcept;
52
53 void SetData(std::string data);
54 const std::string& GetData() const { return data_; }
55
56 virtual bool IsBodyStreamed() const = 0;
57 virtual bool WaitForHeadersEnd() = 0;
58 virtual void SetHeadersEnd() = 0;
59
60 /// @cond
61 // TODO: server internals. remove from public interface
62 void SetReady();
63 void SetReady(std::chrono::steady_clock::time_point now);
64 virtual void SetSendFailed(
65 std::chrono::steady_clock::time_point failure_time);
66 bool IsLimitReached() const;
67
68 bool IsReady() const { return is_ready_; }
69 bool IsSent() const { return is_sent_; }
70 size_t BytesSent() const { return bytes_sent_; }
71 std::chrono::steady_clock::time_point ReadyTime() const {
72 return ready_time_;
73 }
74 std::chrono::steady_clock::time_point SentTime() const { return sent_time_; }
75
76 virtual void SendResponse(engine::io::RwBase& socket) = 0;
77
78 virtual void SetStatusServiceUnavailable() = 0;
79 virtual void SetStatusOk() = 0;
80 virtual void SetStatusNotFound() = 0;
81 /// @endcond
82
83 protected:
84 ResponseBase(ResponseDataAccounter& data_account,
85 std::chrono::steady_clock::time_point now);
86
87 void SetSent(std::size_t bytes_sent,
88 std::chrono::steady_clock::time_point sent_time);
89
90 private:
91 class Guard final {
92 public:
93 Guard(ResponseDataAccounter& accounter,
94 std::chrono::steady_clock::time_point create_time, size_t size)
95 : accounter_(accounter), create_time_(create_time), size_(size) {
96 accounter_.StartRequest(size_, create_time_);
97 }
98
99 ~Guard() { accounter_.StopRequest(size_, create_time_); }
100
101 private:
102 ResponseDataAccounter& accounter_;
103 std::chrono::steady_clock::time_point create_time_;
104 size_t size_;
105 };
106
107 ResponseDataAccounter& accounter_;
108 std::optional<Guard> guard_;
109 std::string data_;
110 std::chrono::steady_clock::time_point create_time_;
111 std::chrono::steady_clock::time_point ready_time_;
112 std::chrono::steady_clock::time_point sent_time_;
113 size_t bytes_sent_ = 0;
114 bool is_ready_ = false;
115 bool is_sent_ = false;
116};
117
118} // namespace server::request
119
120USERVER_NAMESPACE_END