userver: userver/storages/redis/request.hpp Source File
Loading...
Searching...
No Matches
request.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @brief Valkey/Redis futures for storages::redis::Client and storages::redis::Transaction.
5
6#include <memory>
7#include <optional>
8#include <string>
9#include <unordered_map>
10#include <unordered_set>
11#include <vector>
12
13#include <userver/engine/impl/context_accessor.hpp>
14#include <userver/storages/redis/exception.hpp>
15#include <userver/storages/redis/fwd.hpp>
16#include <userver/storages/redis/reply_types.hpp>
17#include <userver/storages/redis/request_data_base.hpp>
18#include <userver/storages/redis/scan_tag.hpp>
19
20USERVER_NAMESPACE_BEGIN
21
22namespace storages::redis {
23
24template <ScanTag TScanTag>
25class RequestScanData;
26
27/// @brief Valkey or Redis future for a non-scan and non-eval responses.
28///
29/// Member functions of classes storages::redis::Client and storages::redis::Transaction that do send request to the
30/// Redis return this type or storages::redis::ScanRequest.
31template <typename ResultType, typename ReplyType>
32class [[nodiscard]] Request final {
33public:
34 using Result = ResultType;
35 using Reply = ReplyType;
36
37 explicit Request(std::unique_ptr<RequestDataBase<ReplyType>>&& impl) : impl_(std::move(impl)) {}
38
39 /// Wait for the request to finish on Redis server
40 void Wait() { impl_->Wait(); }
41
42 /// Ignore the query result and do not wait for the Redis server to finish executing it
43 void IgnoreResult() const noexcept {}
44
45 /// Wait for the request to finish on Redis server and get the result
46 ReplyType Get(const std::string& request_description = {}) { return impl_->Get(request_description); }
47
48 /// @cond
49 /// Internal helper for WaitAny/WaitAll
50 engine::impl::ContextAccessor* TryGetContextAccessor() noexcept { return impl_->TryGetContextAccessor(); }
51 /// @endcond
52
53 template <typename T1, typename T2>
54 friend class RequestEval;
55
56 template <typename T1, typename T2>
57 friend class RequestEvalSha;
58
59 template <ScanTag TScanTag>
60 friend class RequestScanData;
61
62 template <typename T1>
63 friend class RequestGeneric;
64
65private:
66 ReplyPtr GetRaw() { return impl_->GetRaw(); }
67
68 std::unique_ptr<RequestDataBase<ReplyType>> impl_;
69};
70
71/// @brief Redis future for a SCAN-like responses.
72///
73/// Member functions of classes storages::redis::Client and storages::redis::Transaction that do send SCAN-like request
74/// to the Redis return this type or storages::redis::ScanRequest.
75template <ScanTag TScanTag>
76class ScanRequest final {
77public:
78 using ReplyElem = typename ScanReplyElem<TScanTag>::type;
79
80 explicit ScanRequest(std::unique_ptr<RequestScanDataBase<TScanTag>>&& impl) : impl_(std::move(impl)) {}
81
82 template <typename T = std::vector<ReplyElem>>
83 T GetAll(std::string request_description) {
84 SetRequestDescription(std::move(request_description));
85 return GetAll<T>();
86 }
87
88 template <typename T = std::vector<ReplyElem>>
89 T GetAll() {
90 return T{begin(), end()};
91 }
92
93 void SetRequestDescription(std::string request_description) {
94 impl_->SetRequestDescription(std::move(request_description));
95 }
96
97 class Iterator {
98 public:
99 using iterator_category = std::input_iterator_tag;
100 using difference_type = ptrdiff_t;
101 using value_type = ReplyElem;
102 using reference = value_type&;
103 using pointer = value_type*;
104
105 explicit Iterator(ScanRequest* stream) : stream_(stream) {
106 if (stream_ && !stream_->HasMore()) stream_ = nullptr;
107 }
108
110 public:
111 ReplyElemHolder(value_type reply_elem) : reply_elem_(std::move(reply_elem)) {}
112
113 value_type& operator*() { return reply_elem_; }
114
115 private:
116 value_type reply_elem_;
117 };
118
119 ReplyElemHolder operator++(int) {
120 ReplyElemHolder old_value(stream_->Current());
121 ++*this;
122 return old_value;
123 }
124
125 Iterator& operator++() {
126 stream_->Get();
127 if (!stream_->HasMore()) stream_ = nullptr;
128 return *this;
129 }
130
131 reference operator*() { return stream_->Current(); }
132
133 pointer operator->() { return &**this; }
134
135 bool operator==(const Iterator& rhs) const { return stream_ == rhs.stream_; }
136
137 bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
138
139 private:
140 ScanRequest* stream_;
141 };
142
143 Iterator begin() { return Iterator(this); }
144 Iterator end() { return Iterator(nullptr); }
145
147 public:
148 using Exception::Exception;
149 };
150
151private:
152 ReplyElem& Current() { return impl_->Current(); }
153
154 ReplyElem Get() { return impl_->Get(); }
155
156 bool HasMore() { return !impl_->Eof(); }
157
158 friend class Iterator;
159
160 std::unique_ptr<RequestScanDataBase<TScanTag>> impl_;
161};
162
163/// @name Valkey/Redis futures aliases
164/// @{
165using RequestAppend = Request<size_t>;
166using RequestBitop = Request<size_t>;
167using RequestDbsize = Request<size_t>;
168using RequestDecr = Request<int64_t>;
169using RequestDel = Request<size_t>;
170using RequestUnlink = Request<size_t>;
171using RequestGenericCommon = Request<ReplyData>;
172using RequestEvalCommon = Request<ReplyData>;
173using RequestEvalShaCommon = Request<ReplyData>;
174using RequestScriptLoad = Request<std::string>;
175using RequestExec = Request<ReplyData, void>;
176using RequestExists = Request<size_t>;
177using RequestExpire = Request<ExpireReply>;
178using RequestGeoadd = Request<size_t>;
179using RequestGeopos = Request<std::vector<std::optional<Point>>>;
180using RequestGeoradius = Request<std::vector<GeoPoint>>;
181using RequestGeosearch = Request<std::vector<GeoPoint>>;
182using RequestGet = Request<std::optional<std::string>>;
183using RequestGetset = Request<std::optional<std::string>>;
184using RequestHdel = Request<size_t>;
185using RequestHexists = Request<size_t>;
186using RequestHget = Request<std::optional<std::string>>;
187using RequestHgetall = Request<std::unordered_map<std::string, std::string>>;
188using RequestHincrby = Request<int64_t>;
189using RequestHincrbyfloat = Request<double>;
190using RequestHkeys = Request<std::vector<std::string>>;
191using RequestHlen = Request<size_t>;
192using RequestHmget = Request<std::vector<std::optional<std::string>>>;
193using RequestHmset = Request<StatusOk, void>;
194using RequestHscan = ScanRequest<ScanTag::kHscan>;
195using RequestHset = Request<HsetReply>;
196using RequestHsetnx = Request<size_t, bool>;
197using RequestHvals = Request<std::vector<std::string>>;
198using RequestIncr = Request<int64_t>;
199using RequestKeys = Request<std::vector<std::string>>;
200using RequestLindex = Request<std::optional<std::string>>;
201using RequestLlen = Request<size_t>;
202using RequestLpop = Request<std::optional<std::string>>;
203using RequestLpush = Request<size_t>;
204using RequestLpushx = Request<size_t>;
205using RequestLrange = Request<std::vector<std::string>>;
206using RequestLrem = Request<size_t>;
207using RequestLtrim = Request<StatusOk, void>;
208using RequestMget = Request<std::vector<std::optional<std::string>>>;
209using RequestMset = Request<StatusOk, void>;
210using RequestPersist = Request<PersistReply>;
211using RequestPexpire = Request<ExpireReply>;
212using RequestPing = Request<StatusPong, void>;
213using RequestPingMessage = Request<std::string>;
214using RequestPublish = Request<size_t>;
215using RequestRename = Request<StatusOk, void>;
216using RequestRpop = Request<std::optional<std::string>>;
217using RequestRpush = Request<size_t>;
218using RequestRpushx = Request<size_t>;
219using RequestSadd = Request<size_t>;
220using RequestScan = ScanRequest<ScanTag::kScan>;
221using RequestScard = Request<size_t>;
222using RequestSet = Request<StatusOk, void>;
223using RequestSetIfExist = Request<std::optional<StatusOk>, bool>;
224using RequestSetIfNotExist = Request<std::optional<StatusOk>, bool>;
225using RequestSetIfNotExistOrGet = Request<std::optional<std::string>>;
226using RequestSetOptions = Request<SetReply>;
227using RequestSetex = Request<StatusOk, void>;
228using RequestSismember = Request<size_t>;
229using RequestSmembers = Request<std::unordered_set<std::string>>;
230using RequestSrandmember = Request<std::optional<std::string>>;
231using RequestSrandmembers = Request<std::vector<std::string>>;
232using RequestSrem = Request<size_t>;
233using RequestSscan = ScanRequest<ScanTag::kSscan>;
234using RequestStrlen = Request<size_t>;
235using RequestTime = Request<std::chrono::system_clock::time_point>;
236using RequestTtl = Request<TtlReply>;
237using RequestType = Request<KeyType>;
238using RequestZadd = Request<size_t>;
239using RequestZaddIncr = Request<double>;
240using RequestZaddIncrExisting = Request<std::optional<double>>;
241using RequestZcard = Request<size_t>;
242using RequestZcount = Request<size_t>;
243using RequestZrange = Request<std::vector<std::string>>;
244using RequestZrangeWithScores = Request<std::vector<MemberScore>>;
245using RequestZrangebyscore = Request<std::vector<std::string>>;
246using RequestZrangebyscoreWithScores = Request<std::vector<MemberScore>>;
247using RequestZrem = Request<size_t>;
248using RequestZremrangebyrank = Request<size_t>;
249using RequestZremrangebyscore = Request<size_t>;
250using RequestZscan = ScanRequest<ScanTag::kZscan>;
251using RequestZscore = Request<std::optional<double>>;
252/// @}
253
254} // namespace storages::redis
255
256USERVER_NAMESPACE_END