28#include <userver/storages/redis/client.hpp>
29#include <userver/storages/redis/command_control.hpp>
30#include <userver/utils/hedged_request.hpp>
32USERVER_NAMESPACE_BEGIN
34namespace storages::
redis {
37template <
typename RedisRequestType>
38struct RedisRequestStrategy {
39 using RequestType = RedisRequestType;
40 using ReplyType =
typename RequestType::Reply;
41 using GenF = std::function<std::optional<RequestType>(
int)>;
43 explicit RedisRequestStrategy(GenF gen_callback)
44 : gen_callback_(std::move(gen_callback))
47 RedisRequestStrategy(RedisRequestStrategy&& other)
noexcept =
default;
51 std::optional<RequestType> Create(size_t try_count) {
return gen_callback_(try_count); }
52 std::optional<std::chrono::milliseconds> ProcessReply(RequestType&& request) {
53 reply_ = std::move(request).Get();
56 std::optional<ReplyType> ExtractReply() {
return std::move(reply_); }
57 void Finish(RequestType&&) {}
62 std::optional<ReplyType> reply_;
67template <
typename RedisRequestType>
71 typename RedisRequestType,
73 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
75 std::shared_ptr<storages::
redis::Client> redis,
81 auto gen_request = [redis, method, cc{std::move(cc)}, ... args = std::move(args)](
int try_count)
mutable
82 -> std::optional<RedisRequestType> {
86 return (redis.get()->*method)(args..., cc);
88 return utils::hedging::HedgeRequestAsync(
89 impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)),
94template <
typename RedisRequestType>
98 typename RedisRequestType,
100 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
102 std::shared_ptr<storages::
redis::Client> redis,
108 auto gen_request = [redis, method, cc{std::move(cc)}, ... args = std::move(args)](
int try_count)
mutable
109 -> std::optional<RedisRequestType> {
113 return (redis.get()->*method)(args..., cc);
115 return utils::hedging::HedgeRequest(
116 impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)),
125 typename RedisRequestType,
127 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
129 std::shared_ptr<storages::
redis::Client> redis,
133 std::vector<std::tuple<Args...>> args
135 std::vector<
redis::impl::RedisRequestStrategy<RedisRequestType>> strategies;
136 strategies.reserve(args.size());
138 for (
auto&& arg : args) {
139 auto gen_request = [redis, method, cc{cc}, args_tuple{std::move(arg)}](
int try_count)
mutable
140 -> std::optional<RedisRequestType> {
145 [redis, method, cc](
auto&&... args) {
return (redis.get()->*method)(args..., cc); },
149 strategies.emplace_back(std::move(gen_request));
152 return utils::hedging::HedgeRequestsBulk(std::move(strategies), hedging_settings);
159 typename RedisRequestType,
161 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
164 std::shared_ptr<storages::
redis::Client> redis,
168 std::vector<std::tuple<Args...>> args
170 using RequestStrategy =
redis::impl::RedisRequestStrategy<RedisRequestType>;
171 std::vector<RequestStrategy> strategies;
172 strategies.reserve(args.size());
174 for (
auto&& arg : args) {
175 auto gen_request = [redis, method, cc{cc}, args_tuple{std::move(arg)}](
int try_count)
mutable
176 -> std::optional<RedisRequestType> {
181 [redis, method, cc](
auto&&... args) {
return (redis.get()->*method)(args..., cc); },
185 strategies.emplace_back(std::move(gen_request));
188 return utils::hedging::HedgeRequestsBulkAsync<RequestStrategy>(std::move(strategies), hedging_settings);