6#include <unordered_map>
7#include <unordered_set>
10#include <userver/engine/impl/context_accessor.hpp>
11#include <userver/storages/redis/exception.hpp>
12#include <userver/storages/redis/reply_types.hpp>
13#include <userver/storages/redis/request_data_base.hpp>
14#include <userver/storages/redis/scan_tag.hpp>
16USERVER_NAMESPACE_BEGIN
18namespace storages::
redis {
20template <ScanTag scan_tag>
23template <
typename Result,
typename ReplyType = Result>
24class [[nodiscard]] Request final {
26 using Reply = ReplyType;
28 explicit Request(std::unique_ptr<RequestDataBase<ReplyType>>&& impl) : impl_(std::move(impl)) {}
30 void Wait() { impl_->Wait(); }
32 void IgnoreResult()
const {}
34 ReplyType Get(
const std::string& request_description = {}) {
return impl_->Get(request_description); }
38 engine::
impl::ContextAccessor* TryGetContextAccessor()
noexcept {
return impl_->TryGetContextAccessor(); }
41 template <
typename T1,
typename T2>
42 friend class RequestEval;
44 template <
typename T1,
typename T2>
45 friend class RequestEvalSha;
47 template <ScanTag scan_tag>
48 friend class RequestScanData;
51 ReplyPtr GetRaw() {
return impl_->GetRaw(); }
53 std::unique_ptr<RequestDataBase<ReplyType>> impl_;
56template <ScanTag scan_tag>
57class ScanRequest final {
59 using ReplyElem =
typename ScanReplyElem<scan_tag>::type;
61 explicit ScanRequest(std::unique_ptr<RequestScanDataBase<scan_tag>>&& impl) : impl_(std::move(impl)) {}
63 template <
typename T = std::vector<ReplyElem>>
64 T GetAll(std::string request_description) {
65 SetRequestDescription(std::move(request_description));
69 template <
typename T = std::vector<ReplyElem>>
71 return T{begin(), end()};
74 void SetRequestDescription(std::string request_description) {
75 impl_->SetRequestDescription(std::move(request_description));
80 using iterator_category = std::input_iterator_tag;
82 using value_type = ReplyElem;
83 using reference = value_type&;
84 using pointer = value_type*;
86 explicit Iterator(ScanRequest* stream) : stream_(stream) {
87 if (stream_ && !stream_->HasMore()) stream_ =
nullptr;
92 ReplyElemHolder(value_type reply_elem) : reply_elem_(std::move(reply_elem)) {}
94 value_type& operator*() {
return reply_elem_; }
97 value_type reply_elem_;
108 if (!stream_->HasMore()) stream_ =
nullptr;
112 reference operator*() {
return stream_->Current(); }
114 pointer operator->() {
return &**
this; }
116 bool operator==(
const Iterator& rhs)
const {
return stream_ == rhs.stream_; }
118 bool operator!=(
const Iterator& rhs)
const {
return !(*
this == rhs); }
121 ScanRequest* stream_;
129 using USERVER_NAMESPACE::redis::
Exception::Exception;
133 ReplyElem& Current() {
return impl_->Current(); }
135 ReplyElem Get() {
return impl_->Get(); }
137 bool HasMore() {
return !impl_->Eof(); }
141 std::unique_ptr<RequestScanDataBase<scan_tag>> impl_;
153using RequestExec = Request<ReplyData,
void>;
170using RequestHmset = Request<StatusOk,
void>;
171using RequestHscan = ScanRequest<ScanTag::kHscan>;
184using RequestLtrim = Request<StatusOk,
void>;
186using RequestMset = Request<StatusOk,
void>;
189using RequestPing = Request<StatusPong,
void>;
192using RequestRename = Request<StatusOk,
void>;
197using RequestScan = ScanRequest<ScanTag::kScan>;
199using RequestSet = Request<StatusOk,
void>;
200using RequestSetIfExist = Request<std::optional<StatusOk>,
bool>;
201using RequestSetIfNotExist = Request<std::optional<StatusOk>,
bool>;
203using RequestSetex = Request<StatusOk,
void>;
209using RequestSscan = ScanRequest<ScanTag::kSscan>;
226using RequestZscan = ScanRequest<ScanTag::kZscan>;