userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
hedged_request.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/storages/redis/hedged_request.hpp
4
/// @brief Classes and functions for performing hedged requests.
5
///
6
/// Use MakeHedgedRedisRequest method to perform hedged redis request.
7
///
8
/// Example(Sync):
9
/// auto result =
10
/// ::redis::MakeHedgedRedisRequest<storages::redis::RequestHGet>(
11
/// redis_client_shared_ptr,
12
/// &storages::redis::Client::Hget,
13
/// redis_cc, hedging_settings,
14
/// key, field);
15
/// Example(Async):
16
/// auto future =
17
/// ::redis::MakeHedgedRedisRequestAsync<storages::redis::RequestHGet>(
18
/// redis_client_shared_ptr,
19
/// &storages::redis::Client::Hget,
20
/// redis_cc, hedging_settings,
21
/// key, field);
22
/// auto result = future.Get();
23
///
24
25
#
include
<
optional
>
26
#
include
<
tuple
>
27
28
#
include
<
userver
/
storages
/
redis
/
client
.
hpp
>
29
#
include
<
userver
/
storages
/
redis
/
command_control
.
hpp
>
30
#
include
<
userver
/
utils
/
hedged_request
.
hpp
>
31
32
USERVER_NAMESPACE_BEGIN
33
34
namespace
storages::
redis
{
35
namespace
impl {
36
37
template
<
typename
RedisRequestType>
38
struct
RedisRequestStrategy {
39
using
RequestType = RedisRequestType;
40
using
ReplyType =
typename
RequestType::Reply;
41
using
GenF = std::function<std::optional<RequestType>(
int
)>;
42
43
explicit
RedisRequestStrategy(GenF gen_callback)
44
: gen_callback_(std::move(gen_callback))
45
{}
46
47
RedisRequestStrategy(RedisRequestStrategy&& other)
noexcept
=
default
;
48
49
/// @{
50
/// Methods needed by HedgingStrategy
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();
54
return
std::nullopt;
55
}
56
std::optional<ReplyType> ExtractReply() {
return
std::move(reply_); }
57
void
Finish(RequestType&&) {}
58
/// @}
59
60
private
:
61
GenF gen_callback_;
62
std::optional<ReplyType> reply_;
63
};
64
65
}
// namespace impl
66
67
template
<
typename
RedisRequestType>
68
using
HedgedRedisRequest =
utils
::hedging::
HedgedRequestFuture
<impl::RedisRequestStrategy<RedisRequestType>>;
69
70
template
<
71
typename
RedisRequestType,
72
typename
... Args,
73
typename
M = RedisRequestType (storages::redis::Client::*)(Args...,
const
redis
::
CommandControl
&)>
74
HedgedRedisRequest<RedisRequestType>
MakeHedgedRedisRequestAsync
(
75
std::shared_ptr<storages::
redis
::
Client
> redis,
76
M method,
77
const
redis
::
CommandControl
& cc,
78
utils
::hedging::
HedgingSettings
hedging_settings,
79
Args... args
80
) {
81
auto
gen_request = [redis, method, cc{std::move(cc)}, ... args = std::move(args)](
int
try_count)
mutable
82
-> std::optional<RedisRequestType> {
83
cc
.
retry_counter
= try_count;
84
cc
.
max_retries
= 1;
///< We do retries ourselves
85
86
return
(redis.get()->*method)(args..., cc);
87
};
88
return
utils
::hedging::HedgeRequestAsync(
89
impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)),
90
hedging_settings
91
);
92
}
93
94
template
<
typename
RedisRequestType>
95
using
HedgedRedisRequest =
utils
::hedging::
HedgedRequestFuture
<impl::RedisRequestStrategy<RedisRequestType>>;
96
97
template
<
98
typename
RedisRequestType,
99
typename
... Args,
100
typename
M = RedisRequestType (storages::redis::Client::*)(Args...,
const
redis
::
CommandControl
&)>
101
std::optional<
typename
RedisRequestType::
Reply
>
MakeHedgedRedisRequest
(
102
std::shared_ptr<storages::
redis
::
Client
> redis,
103
M method,
104
const
redis
::
CommandControl
& cc,
105
utils
::hedging::
HedgingSettings
hedging_settings,
106
Args... args
107
) {
108
auto
gen_request = [redis, method, cc{std::move(cc)}, ... args = std::move(args)](
int
try_count)
mutable
109
-> std::optional<RedisRequestType> {
110
cc
.
retry_counter
= try_count;
111
cc
.
max_retries
= 1;
///< We do retries ourselves
112
113
return
(redis.get()->*method)(args..., cc);
114
};
115
return
utils
::hedging::HedgeRequest(
116
impl::RedisRequestStrategy<RedisRequestType>(std::move(gen_request)),
117
hedging_settings
118
);
119
}
120
121
/// Same as MakeHedgedRedisRequest but accepting a vector of argument tuples
122
/// instead of a single set of arguments. And return vector of replies
123
/// corresponding to input args.
124
template
<
125
typename
RedisRequestType,
126
typename
... Args,
127
typename
M = RedisRequestType (storages::redis::Client::*)(Args...,
const
redis
::
CommandControl
&)>
128
std::vector<std::optional<
typename
RedisRequestType::
Reply
>>
MakeBulkHedgedRedisRequest
(
129
std::shared_ptr<storages::
redis
::
Client
> redis,
130
M method,
131
const
redis
::
CommandControl
& cc,
132
utils
::hedging::
HedgingSettings
hedging_settings,
133
std::vector<std::tuple<Args...>> args
134
) {
135
std::vector<
redis
::impl::RedisRequestStrategy<RedisRequestType>> strategies;
136
strategies.reserve(args.size());
137
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> {
141
cc
.
retry_counter
= try_count;
142
cc
.
max_retries
= 1;
///< We do retries ourselves
143
144
return
std::apply(
145
[redis, method, cc](
auto
&&... args) {
return
(redis.get()->*method)(args..., cc); },
146
args_tuple
147
);
148
};
149
strategies.emplace_back(std::move(gen_request));
150
}
151
152
return
utils
::hedging::HedgeRequestsBulk(std::move(strategies), hedging_settings);
153
}
154
155
/// Same as MakeHedgedRedisRequestAsync but accepting a vector of argument
156
/// tuples instead of a single set of arguments. And return vector of replies
157
/// corresponding to input args.
158
template
<
159
typename
RedisRequestType,
160
typename
... Args,
161
typename
M = RedisRequestType (storages::redis::Client::*)(Args...,
const
redis
::
CommandControl
&)>
162
utils
::hedging::
HedgedRequestBulkFuture
<
redis
::impl::RedisRequestStrategy<RedisRequestType>>
163
MakeBulkHedgedRedisRequestAsync
(
164
std::shared_ptr<storages::
redis
::
Client
> redis,
165
M method,
166
const
redis
::
CommandControl
& cc,
167
utils
::hedging::
HedgingSettings
hedging_settings,
168
std::vector<std::tuple<Args...>> args
169
) {
170
using
RequestStrategy =
redis
::impl::RedisRequestStrategy<RedisRequestType>;
171
std::vector<RequestStrategy> strategies;
172
strategies.reserve(args.size());
173
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> {
177
cc
.
retry_counter
= try_count;
178
cc
.
max_retries
= 1;
///< We do retries ourselves
179
180
return
std::apply(
181
[redis, method, cc](
auto
&&... args) {
return
(redis.get()->*method)(args..., cc); },
182
args_tuple
183
);
184
};
185
strategies.emplace_back(std::move(gen_request));
186
}
187
188
return
utils
::hedging::HedgeRequestsBulkAsync<RequestStrategy>(std::move(strategies), hedging_settings);
189
}
190
191
}
// namespace storages::redis
192
193
USERVER_NAMESPACE_END
userver
storages
redis
hedged_request.hpp
Generated on
for userver by
Doxygen
1.17.0