Skip to content

Commit

Permalink
support Redis function (#598)
Browse files Browse the repository at this point in the history
  • Loading branch information
sewenew authored Oct 2, 2024
1 parent caeb5e3 commit 90e3267
Show file tree
Hide file tree
Showing 11 changed files with 588 additions and 0 deletions.
88 changes: 88 additions & 0 deletions src/sw/redis++/async_redis.h
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,94 @@ class AsyncRedis {
return evalsha<Result>(script, keys.begin(), keys.end(), args.begin(), args.end(), std::forward<Callback>(cb));
}

template <typename Result, typename Keys, typename Args>
Future<Result> fcall(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
return _command<Result>(fmt::fcall<Keys, Args>,
func, keys_first, keys_last, args_first, args_last);
}

template <typename Result, typename Keys, typename Args, typename Callback>
auto fcall(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last,
Callback &&cb)
-> typename std::enable_if<IsInvocable<typename std::decay<Callback>::type, Future<Result> &&>::value, void>::type {
_callback_fmt_command<Result>(std::forward<Callback>(cb), fmt::fcall<Keys, Args>,
func, keys_first, keys_last, args_first, args_last);
}

template <typename Result>
Future<Result> fcall(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args) {
return fcall<Result>(func,
keys.begin(), keys.end(),
args.begin(), args.end());
}

template <typename Result, typename Callback>
auto fcall(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args,
Callback &&cb)
-> typename std::enable_if<IsInvocable<typename std::decay<Callback>::type, Future<Result> &&>::value, void>::type {
return fcall<Result>(func, keys.begin(), keys.end(), args.begin(), args.end(), std::forward<Callback>(cb));
}

template <typename Result, typename Keys, typename Args>
Future<Result> fcall_ro(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
return _command<Result>(fmt::fcall_ro<Keys, Args>,
func, keys_first, keys_last, args_first, args_last);
}

template <typename Result, typename Keys, typename Args, typename Callback>
auto fcall_ro(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last,
Callback &&cb)
-> typename std::enable_if<IsInvocable<typename std::decay<Callback>::type, Future<Result> &&>::value, void>::type {
_callback_fmt_command<Result>(std::forward<Callback>(cb), fmt::fcall_ro<Keys, Args>,
func, keys_first, keys_last, args_first, args_last);
}

template <typename Result>
Future<Result> fcall_ro(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args) {
return fcall_ro<Result>(func,
keys.begin(), keys.end(),
args.begin(), args.end());
}

template <typename Result, typename Callback>
auto fcall_ro(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args,
Callback &&cb)
-> typename std::enable_if<IsInvocable<typename std::decay<Callback>::type, Future<Result> &&>::value, void>::type {
return fcall_ro<Result>(func, keys.begin(), keys.end(), args.begin(), args.end(), std::forward<Callback>(cb));
}

Future<std::string> function_load(const StringView &code, bool replace = false) {
return _command<std::string>(fmt::function_load, code, replace);
}

Future<void> function_delete(const StringView &lib_name) {
return _command<void>(fmt::function_delete, lib_name);
}

// PUBSUB commands.

Future<long long> publish(const StringView &channel, const StringView &message) {
Expand Down
48 changes: 48 additions & 0 deletions src/sw/redis++/async_redis_cluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,54 @@ class AsyncRedisCluster {
args.begin(), args.end());
}

template <typename Result, typename Keys, typename Args>
Future<Result> fcall(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
if (keys_first == keys_last) {
throw Error("DO NOT support function without key");
}

return _generic_command<Result>(fmt::fcall<Keys, Args>, *keys_first, func,
keys_first, keys_last,
args_first, args_last);
}

template <typename Result>
Future<Result> fcall(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args) {
return fcall<Result>(func,
keys.begin(), keys.end(),
args.begin(), args.end());
}

template <typename Result, typename Keys, typename Args>
Future<Result> fcall_ro(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
if (keys_first == keys_last) {
throw Error("DO NOT support function without key");
}

return _generic_command<Result>(fmt::fcall_ro<Keys, Args>, *keys_first, func,
keys_first, keys_last,
args_first, args_last);
}

template <typename Result>
Future<Result> fcall_ro(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args) {
return fcall_ro<Result>(func,
keys.begin(), keys.end(),
args.begin(), args.end());
}

// PUBSUB commands.

Future<long long> publish(const StringView &channel, const StringView &message) {
Expand Down
50 changes: 50 additions & 0 deletions src/sw/redis++/cmd_formatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,56 @@ FormattedCommand evalsha(const StringView &script,
return format_cmd(args);
}

template <typename Keys, typename Args>
FormattedCommand fcall(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
CmdArgs args;
auto keys_num = std::distance(keys_first, keys_last);

args << "FCALL" << func << keys_num
<< std::make_pair(keys_first, keys_last)
<< std::make_pair(args_first, args_last);

return format_cmd(args);
}

template <typename Keys, typename Args>
FormattedCommand fcall_ro(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
CmdArgs args;
auto keys_num = std::distance(keys_first, keys_last);

args << "FCALL_RO" << func << keys_num
<< std::make_pair(keys_first, keys_last)
<< std::make_pair(args_first, args_last);

return format_cmd(args);
}

inline FormattedCommand function_load(const StringView &code, bool replace) {
CmdArgs cmd_args;

cmd_args << "FUNCTION" << "LOAD";

if (replace) {
cmd_args << "REPLACE";
}

cmd_args << code;

return format_cmd(cmd_args);
}

inline FormattedCommand function_delete(const StringView &lib_name) {
return format_cmd("FUNCTION DELETE %b", lib_name.data(), lib_name.size());
}

// PUBSUB commands.

inline FormattedCommand psubscribe(const StringView &pattern) {
Expand Down
56 changes: 56 additions & 0 deletions src/sw/redis++/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,62 @@ inline void script_load(Connection &connection, const StringView &script) {
connection.send("SCRIPT LOAD %b", script.data(), script.size());
}

template <typename Keys, typename Args>
inline void fcall(Connection &connection,
const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
CmdArgs cmd_args;

auto keys_num = std::distance(keys_first, keys_last);

cmd_args << "FCALL" << func << keys_num
<< std::make_pair(keys_first, keys_last)
<< std::make_pair(args_first, args_last);

connection.send(cmd_args);
}

template <typename Keys, typename Args>
inline void fcall_ro(Connection &connection,
const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last) {
CmdArgs cmd_args;

auto keys_num = std::distance(keys_first, keys_last);

cmd_args << "FCALL_RO" << func << keys_num
<< std::make_pair(keys_first, keys_last)
<< std::make_pair(args_first, args_last);

connection.send(cmd_args);
}

inline void function_load(Connection &connection,
const StringView &code,
bool replace) {
CmdArgs cmd_args;

cmd_args << "FUNCTION" << "LOAD";

if (replace) {
cmd_args << "REPLACE";
}

cmd_args << code;

connection.send(cmd_args);
}

inline void function_delete(Connection &connection, const StringView &lib_name) {
connection.send("FUNCTION DELETE %b", lib_name.data(), lib_name.size());
}

// PUBSUB commands.

inline void psubscribe(Connection &connection, const StringView &pattern) {
Expand Down
12 changes: 12 additions & 0 deletions src/sw/redis++/redis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,18 @@ std::string Redis::script_load(const StringView &script) {
return reply::parse<std::string>(*reply);
}

std::string Redis::function_load(const StringView &code, bool replace) {
auto reply = command(cmd::function_load, code, replace);

return reply::parse<std::string>(*reply);
}

void Redis::function_delete(const StringView &lib_name) {
auto reply = command(cmd::function_delete, lib_name);

reply::parse<void>(*reply);
}

// PUBSUB commands.

long long Redis::publish(const StringView &channel, const StringView &message) {
Expand Down
56 changes: 56 additions & 0 deletions src/sw/redis++/redis.h
Original file line number Diff line number Diff line change
Expand Up @@ -3247,6 +3247,62 @@ class Redis {

std::string script_load(const StringView &script);

template <typename Result, typename Keys, typename Args>
Result fcall(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last);

template <typename Result>
Result fcall(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args);

template <typename Keys, typename Args, typename Output>
void fcall(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last,
Output output);

template <typename Output>
void fcall(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args,
Output output);

template <typename Result, typename Keys, typename Args>
Result fcall_ro(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last);

template <typename Result>
Result fcall_ro(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args);

template <typename Keys, typename Args, typename Output>
void fcall_ro(const StringView &func,
Keys keys_first,
Keys keys_last,
Args args_first,
Args args_last,
Output output);

template <typename Output>
void fcall_ro(const StringView &func,
std::initializer_list<StringView> keys,
std::initializer_list<StringView> args,
Output output);

std::string function_load(const StringView &code, bool replace = false);

void function_delete(const StringView &lib_name);

// PUBSUB commands.

long long publish(const StringView &channel, const StringView &message);
Expand Down
Loading

0 comments on commit 90e3267

Please sign in to comment.