7#include <userver/logging/log_extra.hpp>
8#include <userver/utils/assert.hpp>
10#include <userver/storages/redis/base.hpp>
11#include <userver/storages/redis/reply_fwd.hpp>
12#include <userver/storages/redis/reply_status.hpp>
16USERVER_NAMESPACE_BEGIN
18namespace storages::
redis {
20class ReplyData
final {
22 using Array = std::vector<ReplyData>;
34 class KeyValues
final {
36 class KeyValue
final {
38 KeyValue(
const Array& array, size_t index) : array_(array), index_(index) {}
40 std::string Key()
const {
return array_[index_ * 2].GetString(); }
41 std::string Value()
const {
return array_[index_ * 2 + 1].GetString(); }
48 class KeyValueIt
final {
50 KeyValueIt(
const Array& array, size_t index) : array_(array), index_(index) {}
51 KeyValueIt& operator++() {
55 bool operator!=(
const KeyValueIt& r)
const {
return index_ != r.index_; }
56 KeyValue operator*()
const {
return {array_, index_}; }
63 explicit KeyValues(
const Array& array) : array_(array) {}
65 KeyValueIt begin()
const {
return {array_, 0}; }
66 KeyValueIt end()
const {
return {array_, size()}; }
68 size_t size()
const {
return array_.size() / 2; }
74 class MovableKeyValues
final {
76 class MovableKeyValue
final {
78 MovableKeyValue(ReplyData& key_data, ReplyData& value_data)
79 : key_data_(key_data), value_data_(value_data) {}
81 std::string& Key() {
return key_data_.GetString(); }
82 std::string& Value() {
return value_data_.GetString(); }
86 ReplyData& value_data_;
89 class MovableKeyValueIt
final {
91 MovableKeyValueIt(Array& array, size_t index) : array_(array), index_(index) {}
92 MovableKeyValueIt& operator++() {
96 bool operator!=(
const MovableKeyValueIt& r)
const {
return index_ != r.index_; }
97 MovableKeyValue operator*() {
return {array_[index_ * 2], array_[index_ * 2 + 1]}; }
104 explicit MovableKeyValues(Array& array) : array_(array) {}
106 MovableKeyValueIt begin()
const {
return {array_, 0}; }
107 MovableKeyValueIt end()
const {
return {array_, size()}; }
109 size_t size()
const {
return array_.size() / 2; }
115 MovableKeyValues GetMovableKeyValues();
117 ReplyData(
const redisReply* reply);
118 ReplyData(Array&& array);
119 ReplyData(std::string s);
120 ReplyData(
int value);
121 static ReplyData CreateError(std::string&& error_msg);
122 static ReplyData CreateStatus(std::string&& status_msg);
123 static ReplyData CreateNil();
125 explicit operator
bool()
const {
return type_ != Type::kNoReply; }
127 Type GetType()
const {
return type_; }
128 std::string GetTypeString()
const;
130 inline bool IsString()
const {
return type_ == Type::kString; }
131 inline bool IsArray()
const {
return type_ == Type::kArray; }
132 inline bool IsInt()
const {
return type_ == Type::kInteger; }
133 inline bool IsNil()
const {
return type_ == Type::kNil; }
134 inline bool IsStatus()
const {
return type_ == Type::kStatus; }
135 inline bool IsError()
const {
return type_ == Type::kError; }
136 bool IsUnusableInstanceError()
const;
137 bool IsReadonlyError()
const;
138 bool IsUnknownCommandError()
const;
140 bool IsErrorMoved()
const {
return IsError() && !string_.compare(0, 6,
"MOVED "); }
142 bool IsErrorAsk()
const {
return IsError() && !string_.compare(0, 4,
"ASK "); }
144 bool IsErrorClusterdown()
const {
return IsError() && !string_.compare(0, 12,
"CLUSTERDOWN "); }
146 const std::string& GetString()
const {
151 std::string& GetString() {
156 const Array& GetArray()
const {
166 int64_t GetInt()
const {
171 const std::string& GetStatus()
const {
176 std::string& GetStatus() {
181 const std::string& GetError()
const {
186 std::string& GetError() {
191 const ReplyData& operator[](size_t idx)
const {
193 return array_.at(idx);
196 ReplyData& operator[](size_t idx) {
198 return array_.at(idx);
201 size_t GetSize()
const;
203 std::string ToDebugString()
const;
204 KeyValues GetKeyValues()
const;
205 static std::string TypeToString(Type type);
207 void ExpectType(ReplyData::Type type,
const std::string& request_description = {})
const;
209 void ExpectString(
const std::string& request_description = {})
const;
210 void ExpectArray(
const std::string& request_description = {})
const;
211 void ExpectInt(
const std::string& request_description = {})
const;
212 void ExpectNil(
const std::string& request_description = {})
const;
213 void ExpectStatus(
const std::string& request_description = {})
const;
214 void ExpectStatusEqualTo(
const std::string& expected_status_str,
const std::string& request_description = {})
const;
215 void ExpectError(
const std::string& request_description = {})
const;
218 ReplyData() =
default;
220 [[noreturn]]
void ThrowUnexpectedReplyType(ReplyData::Type expected,
const std::string& request_description)
const;
222 Type type_ = Type::kNoReply;
231 Reply(std::string cmd, redisReply* redis_reply,
ReplyStatus status);
232 Reply(std::string cmd, redisReply* redis_reply,
ReplyStatus status, std::string status_string);
233 Reply(std::string cmd, ReplyData&& data);
240 std::string status_string;
244 operator
bool()
const {
return IsOk(); }
247 bool IsLoggableError()
const;
248 bool IsUnusableInstanceError()
const;
249 bool IsReadonlyError()
const;
250 bool IsUnknownCommandError()
const;
251 const logging::LogExtra& GetLogExtra()
const;
252 void FillSpanTags(
tracing::Span& span)
const;
254 void ExpectIsOk(
const std::string& request_description = {})
const;
255 void ExpectType(ReplyData::Type type,
const std::string& request_description = {})
const;
257 void ExpectString(
const std::string& request_description = {})
const;
258 void ExpectArray(
const std::string& request_description = {})
const;
259 void ExpectInt(
const std::string& request_description = {})
const;
260 void ExpectNil(
const std::string& request_description = {})
const;
261 void ExpectStatus(
const std::string& request_description = {})
const;
262 void ExpectStatusEqualTo(
const std::string& expected_status_str,
const std::string& request_description = {})
const;
263 void ExpectError(
const std::string& request_description = {})
const;
265 const std::string& GetRequestDescription(
const std::string& request_description)
const;