userver: userver/storages/redis/hedged_request.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
hedged_request.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/redis/hedged_request.hpp
4/// @brief
5/// Classes and functions for performing hedged requests.
6///
7/// Use MakeHedgedRedisRequest method to perform hedged redis request.
8///
9/// Example(Sync):
10/// auto result =
11/// ::redis::MakeHedgedRedisRequest<storages::redis::RequestHGet>(
12/// redis_client_shared_ptr,
13/// &storages::redis::Client::Hget,
14/// redis_cc, hedging_settings,
15/// key, field);
16/// Example(Async):
17/// auto future =
18/// ::redis::MakeHedgedRedisRequestAsync<storages::redis::RequestHGet>(
19/// redis_client_shared_ptr,
20/// &storages::redis::Client::Hget,
21/// redis_cc, hedging_settings,
22/// key, field);
23/// auto result = future.Get();
24///
25
26#include <optional>
27
28#include <userver/storages/redis/client.hpp>
29#include <userver/storages/redis/command_control.hpp>
30#include <userver/utils/hedged_request.hpp>
31
32USERVER_NAMESPACE_BEGIN
33
34namespace redis {
35namespace impl {
36
37template <typename RedisRequestType>
38struct RedisRequestStrategy {
39 public:
40 using RequestType = RedisRequestType;
41 using ReplyType = RequestType::Reply;
42 using GenF = std::function<std::optional<RequestType>(int)>;
43
44 explicit RedisRequestStrategy(GenF gen_callback)
45 : gen_callback_(std::move(gen_callback)) {}
46
47 RedisRequestStrategy(RedisRequestStrategy&& other) noexcept = default;
48
49 /// @{
50 /// Methods needed by HedgingStrategy
51 std::optional<RequestType> Create(size_t try_count) {
52 return gen_callback_(try_count);
53 }
54 std::optional<std::chrono::milliseconds> ProcessReply(RequestType&& request) {
55 reply_ = std::move(request).Get();
56 return std::nullopt;
57 }
58 std::optional<ReplyType> ExtractReply() { return std::move(reply_); }
59 void Finish(RequestType&&) {}
60 /// @}
61
62 private:
63 GenF gen_callback_;
64 std::optional<ReplyType> reply_;
65};
66
67} // namespace impl
68
69template <typename RedisRequestType>
70using HedgedRedisRequest = utils::hedging::HedgedRequestFuture<
71 impl::RedisRequestStrategy<RedisRequestType>>;
72
73template <typename RedisRequestType, typename... Args,
74 typename M = RedisRequestType (storages::redis::Client::*)(
75 Args..., const redis::CommandControl&)>
78 const redis::CommandControl& cc,
80 auto gen_request =
81 [redis, method, cc{std::move(cc)},
82 args_tuple{std::tuple(std::move(args)...)}](
83 int try_count) mutable -> std::optional<RedisRequestType> {
84 cc.retry_counter = try_count;
85 cc.max_retries = 1; ///< We do retries ourselves
86
87 return std::apply(
88 [redis, method, cc](auto&&... args) {
89 return (redis.get()->*method)(args..., cc);
90 },
91 args_tuple);
92 };
93 return utils::hedging::HedgeRequestAsync(
94 impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)),
95 hedging_settings);
96}
97
98template <typename RedisRequestType>
99using HedgedRedisRequest = utils::hedging::HedgedRequestFuture<
100 impl::RedisRequestStrategy<RedisRequestType>>;
101
102template <typename RedisRequestType, typename... Args,
103 typename M = RedisRequestType (storages::redis::Client::*)(
104 Args..., const redis::CommandControl&)>
105RedisRequestType MakeHedgedRedisRequest(
106 std::shared_ptr<storages::redis::Client> redis, M method,
107 const redis::CommandControl& cc,
108 utils::hedging::HedgingSettings hedging_settings, Args... args) {
109 auto gen_request =
110 [redis, method, cc{std::move(cc)},
111 args_tuple{std::tuple(std::move(args)...)}](
112 int try_count) mutable -> std::optional<RedisRequestType> {
113 cc.retry_counter = try_count;
114 cc.max_retries = 1; ///< We do retries ourselves
115
116 return std::apply(
117 [redis, method, cc](auto&&... args) {
118 return (redis.get()->*method)(args..., cc);
119 },
120 args_tuple);
121 };
122 return utils::hedging::HedgeRequest(
123 impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)),
124 hedging_settings);
125}
126
127} // namespace redis
128
129USERVER_NAMESPACE_END