mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-10 18:05:44 +02:00
* feat(pubsub): implement pubsub command * fix(pubsub): code review * fix(pubsub): code review * fix(pubsub): code review
This commit is contained in:
parent
c8fe7ba28b
commit
25becd2d43
6 changed files with 87 additions and 2 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,3 +10,4 @@ genfiles/*
|
||||||
*.pyc
|
*.pyc
|
||||||
/CMakeLists.txt.user
|
/CMakeLists.txt.user
|
||||||
_deps
|
_deps
|
||||||
|
releases
|
||||||
|
|
|
@ -72,7 +72,7 @@ auto ChannelSlice::FetchSubscribers(string_view channel) -> vector<Subscriber> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelSlice::CopySubscribers(const SubscribeMap& src, const std::string& pattern,
|
void ChannelSlice::CopySubscribers(const SubscribeMap& src, const std::string& pattern,
|
||||||
vector<Subscriber>* dest) {
|
vector<Subscriber>* dest) {
|
||||||
for (const auto& sub : src) {
|
for (const auto& sub : src) {
|
||||||
ConnectionContext* cntx = sub.first;
|
ConnectionContext* cntx = sub.first;
|
||||||
CHECK(cntx->conn_state.subscribe_info);
|
CHECK(cntx->conn_state.subscribe_info);
|
||||||
|
@ -85,4 +85,21 @@ void ChannelSlice::CopySubscribers(const SubscribeMap& src, const std::string& p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<string> ChannelSlice::ListChannels(const string_view pattern) const {
|
||||||
|
vector<string> res;
|
||||||
|
for (const auto& k_v : channels_) {
|
||||||
|
const string& channel = k_v.first;
|
||||||
|
|
||||||
|
if (pattern.empty() || stringmatchlen(pattern.data(), pattern.size(), channel.data(), channel.size(), 0) == 1) {
|
||||||
|
res.push_back(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ChannelSlice::PatternCount() const {
|
||||||
|
return patterns_.size();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -40,6 +40,9 @@ class ChannelSlice {
|
||||||
void AddGlobPattern(std::string_view pattern, ConnectionContext* me, uint32_t thread_id);
|
void AddGlobPattern(std::string_view pattern, ConnectionContext* me, uint32_t thread_id);
|
||||||
void RemoveGlobPattern(std::string_view pattern, ConnectionContext* me);
|
void RemoveGlobPattern(std::string_view pattern, ConnectionContext* me);
|
||||||
|
|
||||||
|
std::vector<std::string> ListChannels(const std::string_view pattern) const;
|
||||||
|
size_t PatternCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SubscriberInternal {
|
struct SubscriberInternal {
|
||||||
uint32_t thread_id; // proactor thread id.
|
uint32_t thread_id; // proactor thread id.
|
||||||
|
|
|
@ -52,6 +52,9 @@ class CommandId {
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Command Id object
|
* @brief Construct a new Command Id object
|
||||||
*
|
*
|
||||||
|
* When creating a new command use the https://github.com/redis/redis/tree/unstable/src/commands
|
||||||
|
* files to find the right arguments.
|
||||||
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @param mask
|
* @param mask
|
||||||
* @param arity - positive if command has fixed number of required arguments
|
* @param arity - positive if command has fixed number of required arguments
|
||||||
|
|
|
@ -1038,6 +1038,62 @@ void Service::Function(CmdArgList args, ConnectionContext* cntx) {
|
||||||
return (*cntx)->SendError(err, kSyntaxErrType);
|
return (*cntx)->SendError(err, kSyntaxErrType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Service::PubsubChannels(string_view pattern, ConnectionContext* cntx) {
|
||||||
|
vector<vector<string>> result_set(shard_set->size());
|
||||||
|
|
||||||
|
shard_set->RunBriefInParallel([&](EngineShard* shard) {
|
||||||
|
result_set[shard->shard_id()] = shard->channel_slice().ListChannels(pattern);
|
||||||
|
});
|
||||||
|
|
||||||
|
vector<string> union_set;
|
||||||
|
for (auto&& v : result_set) {
|
||||||
|
union_set.insert(union_set.end(), v.begin(), v.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
(*cntx)->SendStringArr(union_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::PubsubPatterns(ConnectionContext* cntx) {
|
||||||
|
size_t pattern_count = shard_set->Await(0, [&] { return EngineShard::tlocal()->channel_slice().PatternCount(); });
|
||||||
|
(*cntx)->SendLong(pattern_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) {
|
||||||
|
if (args.size() < 2) {
|
||||||
|
(*cntx)->SendError(WrongNumArgsError(ArgS(args, 0)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_view subcmd = ArgS(args, 1);
|
||||||
|
|
||||||
|
if (subcmd == "HELP") {
|
||||||
|
string_view help_arr[] = {
|
||||||
|
"PUBSUB <subcommand> [<arg> [value] [opt] ...]. Subcommands are:",
|
||||||
|
"CHANNELS [<pattern>]",
|
||||||
|
"\tReturn the currently active channels matching a <pattern> (default: '*').",
|
||||||
|
"NUMPAT",
|
||||||
|
"\tReturn number of subscriptions to patterns.",
|
||||||
|
"HELP",
|
||||||
|
"\tPrints this help."};
|
||||||
|
|
||||||
|
(*cntx)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subcmd == "CHANNELS") {
|
||||||
|
string pattern;
|
||||||
|
if (args.size() > 2) {
|
||||||
|
pattern = ArgS(args, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
PubsubChannels(pattern, cntx);
|
||||||
|
} else if (subcmd == "NUMPAT") {
|
||||||
|
PubsubPatterns(cntx);
|
||||||
|
} else {
|
||||||
|
(*cntx)->SendError(UnknownSubCmd(subcmd, "PUBSUB"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VarzValue::Map Service::GetVarzStats() {
|
VarzValue::Map Service::GetVarzStats() {
|
||||||
VarzValue::Map res;
|
VarzValue::Map res;
|
||||||
|
|
||||||
|
@ -1095,7 +1151,8 @@ void Service::RegisterCommands() {
|
||||||
<< CI{"UNSUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -1, 0, 0, 0}.MFUNC(Unsubscribe)
|
<< CI{"UNSUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -1, 0, 0, 0}.MFUNC(Unsubscribe)
|
||||||
<< CI{"PSUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -2, 0, 0, 0}.MFUNC(PSubscribe)
|
<< CI{"PSUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -2, 0, 0, 0}.MFUNC(PSubscribe)
|
||||||
<< CI{"PUNSUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -1, 0, 0, 0}.MFUNC(PUnsubscribe)
|
<< CI{"PUNSUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -1, 0, 0, 0}.MFUNC(PUnsubscribe)
|
||||||
<< CI{"FUNCTION", CO::NOSCRIPT, 2, 0, 0, 0}.MFUNC(Function);
|
<< CI{"FUNCTION", CO::NOSCRIPT, 2, 0, 0, 0}.MFUNC(Function)
|
||||||
|
<< CI{"PUBSUB", CO::LOADING | CO::FAST, -1, 0, 0, 0}.MFUNC(Pubsub);
|
||||||
|
|
||||||
StreamFamily::Register(®istry_);
|
StreamFamily::Register(®istry_);
|
||||||
StringFamily::Register(®istry_);
|
StringFamily::Register(®istry_);
|
||||||
|
|
|
@ -98,6 +98,10 @@ class Service : public facade::ServiceInterface {
|
||||||
void PUnsubscribe(CmdArgList args, ConnectionContext* cntx);
|
void PUnsubscribe(CmdArgList args, ConnectionContext* cntx);
|
||||||
void Function(CmdArgList args, ConnectionContext* cntx);
|
void Function(CmdArgList args, ConnectionContext* cntx);
|
||||||
|
|
||||||
|
void Pubsub(CmdArgList args, ConnectionContext* cntx);
|
||||||
|
void PubsubChannels(std::string_view pattern, ConnectionContext* cntx);
|
||||||
|
void PubsubPatterns(ConnectionContext* cntx);
|
||||||
|
|
||||||
struct EvalArgs {
|
struct EvalArgs {
|
||||||
std::string_view sha; // only one of them is defined.
|
std::string_view sha; // only one of them is defined.
|
||||||
CmdArgList keys, args;
|
CmdArgList keys, args;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue