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
37template <
typename RedisRequestType>
38struct RedisRequestStrategy {
40 using RequestType = RedisRequestType;
41 using ReplyType =
typename RequestType::Reply;
42 using GenF = std::function<std::optional<RequestType>(
int)>;
44 explicit RedisRequestStrategy(GenF gen_callback) : gen_callback_(std::move(gen_callback)) {}
46 RedisRequestStrategy(RedisRequestStrategy&& other)
noexcept =
default;
50 std::optional<RequestType> Create(size_t try_count) {
return gen_callback_(try_count); }
51 std::optional<std::chrono::milliseconds> ProcessReply(RequestType&& request) {
52 reply_ = std::move(request).Get();
55 std::optional<ReplyType> ExtractReply() {
return std::move(reply_); }
56 void Finish(RequestType&&) {}
61 std::optional<ReplyType> reply_;
66template <
typename RedisRequestType>
70 typename RedisRequestType,
72 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
80 auto gen_request = [redis, method, cc{std::move(cc)}, args_tuple{std::tuple(std::move(args)...)}](
int try_count
81 )
mutable -> std::optional<RedisRequestType> {
82 cc.retry_counter = try_count;
86 [redis, method, cc](
auto&&... args) {
return (redis.get()->*method)(args..., cc); }, args_tuple
89 return utils::hedging::HedgeRequestAsync(
90 impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)), hedging_settings
94template <
typename RedisRequestType>
98 typename RedisRequestType,
100 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
108 auto gen_request = [redis, method, cc{std::move(cc)}, args_tuple{std::tuple(std::move(args)...)}](
int try_count
109 )
mutable -> std::optional<RedisRequestType> {
110 cc.retry_counter = try_count;
114 [redis, method, cc](
auto&&... args) {
return (redis.get()->*method)(args..., cc); }, args_tuple
117 return utils::hedging::HedgeRequest(
118 impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)), hedging_settings
126 typename RedisRequestType,
128 typename M = RedisRequestType (storages::redis::Client::*)(Args...,
const redis::
CommandControl&)>
136 std::vector<redis::impl::RedisRequestStrategy<RedisRequestType>> strategies;
137 strategies.reserve(args.size());
139 for (
auto&& arg : args) {
140 auto gen_request = [redis, method, cc{std::move(cc)}, args_tuple{std::move(arg)}](
int try_count
141 )
mutable -> std::optional<RedisRequestType> {
142 cc.retry_counter = try_count;
146 [redis, method, cc](
auto&&... args) {
return (redis.get()->*method)(args..., cc); }, args_tuple
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&)>
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{std::move(cc)}, args_tuple{std::move(arg)}](
int try_count
176 )
mutable -> std::optional<RedisRequestType> {
177 cc.retry_counter = try_count;
181 [redis, method, cc](
auto&&... args) {
return (redis.get()->*method)(args..., cc); }, args_tuple
184 strategies.emplace_back(std::move(gen_request));
187 return utils::hedging::HedgeRequestsBulkAsync<RequestStrategy>(std::move(strategies), hedging_settings);