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