userver: userver/storages/redis/command_control.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
command_control.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @brief @copybrief storages::redis::CommandControl
5
6#include <atomic>
7#include <chrono>
8#include <cstdint>
9#include <optional>
10#include <string>
11
12#include <userver/compiler/impl/three_way_comparison.hpp>
13#include <userver/storages/redis/fwd.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace testsuite {
18struct RedisControl;
19} // namespace testsuite
20
21namespace storages::redis {
22
23inline constexpr std::chrono::milliseconds kDefaultTimeoutSingle{500};
24inline constexpr std::chrono::milliseconds kDefaultTimeoutAll{2000};
25inline constexpr std::size_t kDefaultMaxRetries{4};
26
27/// Opaque Id of Redis server instance / any server instance.
28class ServerId {
29public:
30 /// Default: any server
31 constexpr ServerId() = default;
32
33 bool IsAny() const { return id_ == -1; }
34
35#ifdef USERVER_IMPL_HAS_THREE_WAY_COMPARISON
36 auto operator<=>(const ServerId&) const = default;
37#else
38 bool operator==(const ServerId& other) const { return other.id_ == id_; }
39 bool operator!=(const ServerId& other) const { return !(other == *this); }
40
41 bool operator<(const ServerId& other) const { return id_ < other.id_; }
42#endif
43
44 static ServerId Generate() {
45 ServerId sid;
46 sid.id_ = next_id_++;
47 return sid;
48 }
49
50 static ServerId Invalid() { return invalid_; }
51
52 int64_t GetId() const { return id_; }
53
54 void SetDescription(std::string description) const;
55 void RemoveDescription() const;
56 std::string GetDescription() const;
57
58private:
59 static std::atomic<std::int64_t> next_id_;
60 static ServerId invalid_;
61
62 std::int64_t id_{-1};
63};
64
66 std::size_t operator()(ServerId server_id) const noexcept { return std::hash<std::size_t>{}(server_id.GetId()); }
67};
68
70
71/// Can be used as an additional parameter in some commands to force retries to
72/// master if slave returned a nil reply.
74
75/// Redis command execution options
77 enum class Strategy {
78 /// Same as kEveryDc
80
81 /// Send ~1/N requests to an instance with ping N ms
83
84 /// Send requests to Redis instances located in local DC (by Conductor info)
86
87 /// Send requests to 'best_dc_count' Redis instances with the min ping
89 };
90
91 /// Timeout for a single attempt to execute command
92 std::optional<std::chrono::milliseconds> timeout_single;
93
94 /// Command execution timeout, including retries
95 std::optional<std::chrono::milliseconds> timeout_all;
96
97 /// The maximum number of retries while executing command
98 std::optional<std::size_t> max_retries;
99
100 /// Server instance selection strategy
101 std::optional<Strategy> strategy{};
102
103 /// How many nearest DCs to use
104 std::optional<std::size_t> best_dc_count{};
105
106 /// Force execution on master node
107 std::optional<bool> force_request_to_master{};
108
109 /// Consider ping to nodes in instance selection (true if not specified).
110 /// Setting to false makes the load on the database evenly distributed, but may increase timings
111 std::optional<bool> consider_ping{};
112
113 /// Server latency limit
114 std::optional<std::chrono::milliseconds> max_ping_latency{};
115
116 /// Allow execution of readonly commands on master node along with replica
117 /// nodes to facilitate load distribution
118 std::optional<bool> allow_reads_from_master{};
119
120 /// Controls if the command execution accounted in statistics
121 std::optional<bool> account_in_statistics{};
122
123 /// If set, force execution on specific shard
124 std::optional<std::size_t> force_shard_idx{};
125
126 /// Split execution of multi-key commands (i.e., MGET) to multiple requests
127 std::optional<std::size_t> chunk_size{};
128
129 /// If set, the user wants a specific Redis instance to handle the command.
130 /// Sentinel may not redirect the command to other instances. strategy is
131 /// ignored.
132 std::optional<ServerId> force_server_id{};
133
134 /// If set, command retries are directed to the master instance
136
137 /// Need to be set to if you do manual retries and want retry budget to work.
138 /// If set value other than 0 then request treated as retry.
139 /// 0 - original request, 1 - first retry, 2 - second and so on
140 size_t retry_counter{0};
141
142 constexpr CommandControl() = default;
143 constexpr CommandControl(
144 const std::optional<std::chrono::milliseconds>& timeout_single,
145 const std::optional<std::chrono::milliseconds>& timeout_all,
146 const std::optional<size_t>& max_retries
147 ) noexcept
148 : timeout_single(timeout_single), timeout_all(timeout_all), max_retries(max_retries) {}
149
150#ifdef USERVER_IMPL_HAS_THREE_WAY_COMPARISON
151 auto operator<=>(const CommandControl&) const = default;
152#endif
153
154 CommandControl MergeWith(const CommandControl& b) const;
155 CommandControl MergeWith(const testsuite::RedisControl&) const;
156 CommandControl MergeWith(RetryNilFromMaster) const;
157
158 std::string ToString() const;
159};
160
161/// Returns CommandControl::Strategy from string
163
164/// Returns string representation of CommandControl::Strategy
166
167} // namespace storages::redis
168
169USERVER_NAMESPACE_END