Skip to content

Commit 1fdccc4

Browse files
author
vaninvv
committed
feat redis: add Client::GenericCommand
commit_hash:f314a1bb7763e9836bd75bb6a68628612d702baa
1 parent 8ec88f2 commit 1fdccc4

File tree

9 files changed

+233
-111
lines changed

9 files changed

+233
-111
lines changed

.mapping.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3376,6 +3376,7 @@
33763376
"redis/include/userver/storages/redis/request_data_base.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/request_data_base.hpp",
33773377
"redis/include/userver/storages/redis/request_eval.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/request_eval.hpp",
33783378
"redis/include/userver/storages/redis/request_evalsha.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/request_evalsha.hpp",
3379+
"redis/include/userver/storages/redis/request_generic.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/request_generic.hpp",
33793380
"redis/include/userver/storages/redis/scan_tag.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/scan_tag.hpp",
33803381
"redis/include/userver/storages/redis/subscribe_client.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/subscribe_client.hpp",
33813382
"redis/include/userver/storages/redis/subscription_token.hpp":"taxi/uservices/userver/redis/include/userver/storages/redis/subscription_token.hpp",

redis/include/userver/storages/redis/client.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <userver/storages/redis/request.hpp>
1717
#include <userver/storages/redis/request_eval.hpp>
1818
#include <userver/storages/redis/request_evalsha.hpp>
19+
#include <userver/storages/redis/request_generic.hpp>
1920
#include <userver/storages/redis/transaction.hpp>
2021

2122
USERVER_NAMESPACE_BEGIN
@@ -107,6 +108,22 @@ class Client {
107108
EvalShaCommon(std::move(script_hash), std::move(keys), std::move(args), command_control)};
108109
}
109110

111+
/// @brief Execute a custom Redis command.
112+
/// @param key_index Index of the key in the args vector used to determine the shard
113+
///
114+
/// Sample usage:
115+
/// @snippet redis/src/storages/redis/client_cluster_redistest.cpp Sample generic command usage
116+
template <typename ReplyType>
117+
RequestGeneric<ReplyType> GenericCommand(
118+
std::string command,
119+
std::vector<std::string> args,
120+
size_t key_index,
121+
const CommandControl& command_control
122+
) {
123+
return RequestGeneric<ReplyType>{
124+
GenericCommon(std::move(command), std::move(args), key_index, command_control)};
125+
}
126+
110127
/// @brief Load the script to the server for further execution via EvalSha() member function.
111128
///
112129
/// Sample usage:
@@ -517,6 +534,12 @@ class Client {
517534
std::vector<std::string> args,
518535
const CommandControl& command_control
519536
) = 0;
537+
virtual RequestGenericCommon GenericCommon(
538+
std::string command,
539+
std::vector<std::string> args,
540+
size_t key_index,
541+
const CommandControl& command_control
542+
) = 0;
520543
};
521544

522545
std::string CreateTmpKey(const std::string& key, std::string prefix);

redis/include/userver/storages/redis/request.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class [[nodiscard]] Request final {
5959
template <ScanTag TScanTag>
6060
friend class RequestScanData;
6161

62+
template <typename T1>
63+
friend class RequestGeneric;
64+
6265
private:
6366
ReplyPtr GetRaw() { return impl_->GetRaw(); }
6467

@@ -165,6 +168,7 @@ using RequestDbsize = Request<size_t>;
165168
using RequestDecr = Request<int64_t>;
166169
using RequestDel = Request<size_t>;
167170
using RequestUnlink = Request<size_t>;
171+
using RequestGenericCommon = Request<ReplyData>;
168172
using RequestEvalCommon = Request<ReplyData>;
169173
using RequestEvalShaCommon = Request<ReplyData>;
170174
using RequestScriptLoad = Request<std::string>;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
/// @file
4+
/// @brief @copybrief storages::redis::RequestGeneric
5+
6+
#include <userver/storages/redis/parse_reply.hpp>
7+
#include <userver/storages/redis/reply.hpp>
8+
#include <userver/storages/redis/request.hpp>
9+
10+
USERVER_NAMESPACE_BEGIN
11+
12+
namespace storages::redis {
13+
14+
/// @brief Redis future for generic command responses.
15+
/// Can be used to request custom modules commands or unsupported yet commands
16+
template <typename ReplyType>
17+
class [[nodiscard]] RequestGeneric final {
18+
public:
19+
explicit RequestGeneric(RequestGenericCommon&& request) : request_(std::move(request)) {}
20+
21+
void Wait() { request_.Wait(); }
22+
23+
void IgnoreResult() const { request_.IgnoreResult(); }
24+
25+
ReplyType Get(const std::string& request_description = {}) {
26+
return impl::ParseReply<ReplyType, ReplyType>(request_.GetRaw(), request_description);
27+
}
28+
29+
/// @cond
30+
/// Internal helper for WaitAny/WaitAll
31+
engine::impl::ContextAccessor* TryGetContextAccessor() noexcept { return request_.TryGetContextAccessor(); }
32+
/// @endcond
33+
34+
private:
35+
RequestGenericCommon request_;
36+
};
37+
38+
} // namespace storages::redis
39+
40+
USERVER_NAMESPACE_END

redis/src/storages/redis/client_impl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,18 @@ RequestEvalShaCommon ClientImpl::EvalShaCommon(
181181
));
182182
}
183183

184+
RequestGenericCommon ClientImpl::GenericCommon(
185+
std::string command,
186+
std::vector<std::string> args,
187+
size_t key_index,
188+
const CommandControl& command_control
189+
) {
190+
size_t shard = ShardByKey(args.at(key_index), command_control);
191+
return CreateRequest<RequestGenericCommon>(
192+
MakeRequest(CmdArgs{command, std::move(args)}, shard, true, GetCommandControl(command_control))
193+
);
194+
}
195+
184196
RequestScriptLoad ClientImpl::ScriptLoad(std::string script, size_t shard, const CommandControl& command_control) {
185197
return CreateRequest<RequestScriptLoad>(
186198
MakeRequest(CmdArgs{"script", "load", std::move(script)}, shard, true, GetCommandControl(command_control))

redis/src/storages/redis/client_impl.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ class ClientImpl final : public Client, public std::enable_shared_from_this<Clie
8989
std::vector<std::string> args,
9090
const CommandControl& command_control
9191
) override;
92+
RequestGenericCommon GenericCommon(
93+
std::string command,
94+
std::vector<std::string> args,
95+
size_t key_index,
96+
const CommandControl& command_control
97+
) override;
9298
RequestScriptLoad ScriptLoad(std::string script, size_t shard, const CommandControl& command_control) override;
9399

94100
RequestExists Exists(std::string key, const CommandControl& command_control) override;

redis/src/storages/redis/client_redistest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ UTEST_F(RedisClientTest, EvalSha) {
238238
EXPECT_EQ(result_array[0], "key1");
239239
}
240240

241+
UTEST_F(RedisClientTest, Generic) {
242+
auto client = GetClient();
243+
const storages::redis::CommandControl kCommandControl{};
244+
constexpr size_t kKeyIndex = 0;
245+
UEXPECT_NO_THROW(client->GenericCommand<void>("set", {"key0", "foo"}, kKeyIndex, kCommandControl).Wait());
246+
EXPECT_EQ(client->GenericCommand<std::string>("get", {"key0"}, kKeyIndex, kCommandControl).Get(), "foo");
247+
EXPECT_EQ(
248+
client->GenericCommand<int64_t>("LPUSH", {"list", "1", "2", "3", "4"}, kKeyIndex, kCommandControl).Get(), 4
249+
);
250+
const std::vector<std::string> kExpected{"4", "3", "2", "1"};
251+
EXPECT_EQ(
252+
client->GenericCommand<std::vector<std::string>>("LRANGE", {"list", "0", "-1"}, kKeyIndex, kCommandControl)
253+
.Get(),
254+
kExpected
255+
);
256+
}
257+
241258
UTEST_F(RedisClientTest, Exists) {
242259
auto client = GetClient();
243260
client->Set("key1", "Hello", {}).Get();

redis/testing/include/userver/storages/redis/mock_client_base.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ class MockClientBase : public Client, public std::enable_shared_from_this<MockCl
8787
std::vector<std::string> args,
8888
const CommandControl& command_control
8989
) override;
90+
RequestGenericCommon GenericCommon(
91+
std::string command,
92+
std::vector<std::string> args,
93+
size_t key_index,
94+
const CommandControl& command_control
95+
) override;
9096

9197
RequestScriptLoad ScriptLoad(std::string script, size_t shard, const CommandControl& command_control) override;
9298

0 commit comments

Comments
 (0)