userver: userver/storages/redis/impl/reply.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
reply.hpp
1#pragma once
2
3#include <cassert>
4#include <string>
5#include <vector>
6
7#include <userver/logging/log_extra.hpp>
8#include <userver/utils/assert.hpp>
9
10#include <userver/storages/redis/impl/base.hpp>
11#include <userver/storages/redis/reply_status.hpp>
12
13struct redisReply;
14
15USERVER_NAMESPACE_BEGIN
16
17namespace redis {
18
19class ReplyData final {
20 public:
21 using Array = std::vector<ReplyData>;
22
23 enum class Type {
24 kNoReply,
25 kString,
26 kArray,
27 kInteger,
28 kNil,
29 kStatus,
30 kError,
31 };
32
33 class KeyValues final {
34 public:
35 class KeyValue final {
36 public:
37 KeyValue(const Array& array, size_t index)
38 : array_(array), index_(index) {}
39
40 std::string Key() const { return array_[index_ * 2].GetString(); }
41 std::string Value() const { return array_[index_ * 2 + 1].GetString(); }
42
43 private:
44 const Array& array_;
45 size_t index_;
46 };
47
48 class KeyValueIt final {
49 public:
50 KeyValueIt(const Array& array, size_t index)
51 : array_(array), index_(index) {}
52 KeyValueIt& operator++() {
53 ++index_;
54 return *this;
55 }
56 bool operator!=(const KeyValueIt& r) const { return index_ != r.index_; }
57 KeyValue operator*() const { return {array_, index_}; }
58
59 private:
60 const Array& array_;
61 size_t index_;
62 };
63
64 explicit KeyValues(const Array& array) : array_(array) {}
65
66 KeyValueIt begin() const { return {array_, 0}; }
67 KeyValueIt end() const { return {array_, size()}; }
68
69 size_t size() const { return array_.size() / 2; }
70
71 private:
72 const Array& array_;
73 };
74
75 class MovableKeyValues final {
76 public:
77 class MovableKeyValue final {
78 public:
79 MovableKeyValue(ReplyData& key_data, ReplyData& value_data)
80 : key_data_(key_data), value_data_(value_data) {}
81
82 std::string& Key() { return key_data_.GetString(); }
83 std::string& Value() { return value_data_.GetString(); }
84
85 private:
86 ReplyData& key_data_;
87 ReplyData& value_data_;
88 };
89
90 class MovableKeyValueIt final {
91 public:
92 MovableKeyValueIt(Array& array, size_t index)
93 : array_(array), index_(index) {}
94 MovableKeyValueIt& operator++() {
95 ++index_;
96 return *this;
97 }
98 bool operator!=(const MovableKeyValueIt& r) const {
99 return index_ != r.index_;
100 }
101 MovableKeyValue operator*() {
102 return {array_[index_ * 2], array_[index_ * 2 + 1]};
103 }
104
105 private:
106 Array& array_;
107 size_t index_;
108 };
109
110 explicit MovableKeyValues(Array& array) : array_(array) {}
111
112 MovableKeyValueIt begin() const { return {array_, 0}; }
113 MovableKeyValueIt end() const { return {array_, size()}; }
114
115 size_t size() const { return array_.size() / 2; }
116
117 private:
118 Array& array_;
119 };
120
121 MovableKeyValues GetMovableKeyValues();
122
123 ReplyData(const redisReply* reply);
124 ReplyData(Array&& array);
125 ReplyData(std::string s);
126 ReplyData(int value);
127 static ReplyData CreateError(std::string&& error_msg);
128 static ReplyData CreateStatus(std::string&& status_msg);
129 static ReplyData CreateNil();
130
131 explicit operator bool() const { return type_ != Type::kNoReply; }
132
133 Type GetType() const { return type_; }
134 std::string GetTypeString() const;
135
136 inline bool IsString() const { return type_ == Type::kString; }
137 inline bool IsArray() const { return type_ == Type::kArray; }
138 inline bool IsInt() const { return type_ == Type::kInteger; }
139 inline bool IsNil() const { return type_ == Type::kNil; }
140 inline bool IsStatus() const { return type_ == Type::kStatus; }
141 inline bool IsError() const { return type_ == Type::kError; }
142 bool IsUnusableInstanceError() const;
143 bool IsReadonlyError() const;
144 bool IsUnknownCommandError() const;
145
146 bool IsErrorMoved() const {
147 return IsError() && !string_.compare(0, 6, "MOVED ");
148 }
149
150 bool IsErrorAsk() const {
151 return IsError() && !string_.compare(0, 4, "ASK ");
152 }
153
154 const std::string& GetString() const {
155 UASSERT(IsString());
156 return string_;
157 }
158
159 std::string& GetString() {
160 UASSERT(IsString());
161 return string_;
162 }
163
164 const Array& GetArray() const {
165 UASSERT(IsArray());
166 return array_;
167 }
168
169 Array& GetArray() {
170 UASSERT(IsArray());
171 return array_;
172 }
173
174 int64_t GetInt() const {
175 UASSERT(IsInt());
176 return integer_;
177 }
178
179 const std::string& GetStatus() const {
180 UASSERT(IsStatus());
181 return string_;
182 }
183
184 std::string& GetStatus() {
185 UASSERT(IsStatus());
186 return string_;
187 }
188
189 const std::string& GetError() const {
190 UASSERT(IsError());
191 return string_;
192 }
193
194 std::string& GetError() {
195 UASSERT(IsError());
196 return string_;
197 }
198
199 const ReplyData& operator[](size_t idx) const {
200 UASSERT(IsArray());
201 return array_.at(idx);
202 }
203
204 ReplyData& operator[](size_t idx) {
205 UASSERT(IsArray());
206 return array_.at(idx);
207 }
208
209 size_t GetSize() const;
210
211 std::string ToDebugString() const;
212 KeyValues GetKeyValues() const;
213 static std::string TypeToString(Type type);
214
215 void ExpectType(ReplyData::Type type,
216 const std::string& request_description = {}) const;
217
218 void ExpectString(const std::string& request_description = {}) const;
219 void ExpectArray(const std::string& request_description = {}) const;
220 void ExpectInt(const std::string& request_description = {}) const;
221 void ExpectNil(const std::string& request_description = {}) const;
222 void ExpectStatus(const std::string& request_description = {}) const;
223 void ExpectStatusEqualTo(const std::string& expected_status_str,
224 const std::string& request_description = {}) const;
225 void ExpectError(const std::string& request_description = {}) const;
226
227 private:
228 ReplyData() = default;
229
230 [[noreturn]] void ThrowUnexpectedReplyType(
231 ReplyData::Type expected, const std::string& request_description) const;
232
233 Type type_ = Type::kNoReply;
234
235 int64_t integer_{};
236 Array array_;
237 std::string string_;
238};
239
240class Reply final {
241 public:
242 Reply(std::string cmd, redisReply* redis_reply, ReplyStatus status);
243 Reply(std::string cmd, redisReply* redis_reply, ReplyStatus status,
244 std::string status_string);
245 Reply(std::string cmd, ReplyData&& data);
246
247 std::string server;
248 ServerId server_id;
249 std::string cmd;
250 ReplyData data;
251 ReplyStatus status;
252 std::string status_string;
253 double time = 0.0;
254 logging::LogExtra log_extra;
255
256 operator bool() const { return IsOk(); }
257
258 bool IsOk() const;
259 bool IsLoggableError() const;
260 bool IsUnusableInstanceError() const;
261 bool IsReadonlyError() const;
262 bool IsUnknownCommandError() const;
263 const logging::LogExtra& GetLogExtra() const;
264 void FillSpanTags(tracing::Span& span) const;
265
266 void ExpectIsOk(const std::string& request_description = {}) const;
267 void ExpectType(ReplyData::Type type,
268 const std::string& request_description = {}) const;
269
270 void ExpectString(const std::string& request_description = {}) const;
271 void ExpectArray(const std::string& request_description = {}) const;
272 void ExpectInt(const std::string& request_description = {}) const;
273 void ExpectNil(const std::string& request_description = {}) const;
274 void ExpectStatus(const std::string& request_description = {}) const;
275 void ExpectStatusEqualTo(const std::string& expected_status_str,
276 const std::string& request_description = {}) const;
277 void ExpectError(const std::string& request_description = {}) const;
278
279 const std::string& GetRequestDescription(
280 const std::string& request_description) const;
281};
282
283} // namespace redis
284
285USERVER_NAMESPACE_END