-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(server): Add PUBSUB SHARDCHANNELS/SHARDNUMSUB #4702
Conversation
026e56a
to
11173a4
Compare
@@ -2362,9 +2367,6 @@ void Service::Monitor(CmdArgList args, const CommandContext& cmd_cntx) { | |||
void Service::Pubsub(CmdArgList args, const CommandContext& cmd_cntx) { | |||
auto* rb = static_cast<RedisReplyBuilder*>(cmd_cntx.rb); | |||
|
|||
if (IsClusterEnabled()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldnt we reject all PUBSUB commands on cluster mode? @kostasrim
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No not all, cause PUBSUB
is a family (it has subcommands). So for example https://redis.io/docs/latest/commands/pubsub-shardchannels/#:~:text=An%20active%20shard%20channel%20is,glob%2Dstyle%20pattern%20are%20listed.
PUBSUB SHARDCHANNELS
is fine, since shard channels are a notion of cluster
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, PUBSUB CHANNELS
should be rejected (until we have global pub sub available)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I understand. And the implementaion is just the same..
So if on cluster we allow all commands that subcommand start with "SHARD",
then I think it will be more readable to write the condition
if IsClusterEnabled() && !absl::StartsWith(subcmd, "SHARD") in this function
and remove the bool reject_cluster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I understand. And the implementaion is just the same..
Yes I did not decouple them because we had no design doc for global pub sub so I left it as is on purpose. I did not want to make decisions for the future
+1 for the rest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adiholden thank you for suggestion, but this is problematic because it just checks SHARD prefix of subcommand and if that command is not valid it will still report error instead of returning warning about wrong subcommand (also, per @kostasrim review we need to cover situation when SHARD subcommands is used in non cluster environment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kostasrim I checked now the Redis documentation and it says
PUBSUB's replies in a cluster only report information from the node's Pub/Sub context, rather than the entire cluster.
This means we do support this commands in cluster mode, and the behavior is just like the shard sub command.
see f.e https://redis.io/docs/latest/commands/pubsub-numpat/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First PR! Congratz 👨🍳
Left some minor comments.
Also, plz write a short description in the PR and reference the issue that you are closing by this PR.
For reference see #4696 (comment)
tests/dragonfly/cluster_test.py
Outdated
|
||
with pytest.raises(redis.exceptions.ResponseError) as moved_error: | ||
await c_nodes[0].execute_command("PUBSUB CHANNELS") | ||
assert str(moved_error.value) == f"PUBSUB CHANNELS is not supported in cluster mode yet" | ||
|
||
with pytest.raises(redis.exceptions.ResponseError) as moved_error: | ||
await c_nodes[0].execute_command("PUBSUB NUMSUB") | ||
assert str(moved_error.value) == f"PUBSUB NUMSUB is not supported in cluster mode yet" | ||
|
||
with pytest.raises(redis.exceptions.ResponseError) as moved_error: | ||
await c_nodes[0].execute_command("PUBSUB NUMPAT") | ||
assert str(moved_error.value) == f"PUBSUB NUMPAT is not supported in cluster mode yet" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are somewhat redundant. The unit test your introduced above suffice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I miss read this. Keep these, they are usefull
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They check that CHANNELS, NUMBSUB, NUMPAT
is not available in cluster.
Great!
"data": 1, | ||
} | ||
|
||
message = await c_nodes[0].execute_command("PUBSUB SHARDCHANNELS") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: consider adding a few more channels, then check that they are printed here. Use a filter below, to check that we do actually filter and apply pattern correctly (which existed before and it should be correct but why not 😄 )
@@ -625,7 +625,12 @@ TEST_F(ClusterFamilyTest, ClusterModePubSubNotAllowed) { | |||
ErrArg("PSUBSCRIBE is not supported in cluster mode yet")); | |||
EXPECT_THAT(Run({"PUNSUBSCRIBE", "ch?"}), | |||
ErrArg("PUNSUBSCRIBE is not supported in cluster mode yet")); | |||
EXPECT_THAT(Run({"PUBSUB", "CHANNELS"}), ErrArg("PUBSUB is not supported in cluster mode yet")); | |||
EXPECT_THAT(Run({"PUBSUB", "CHANNELS"}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the opposite checks for non cluster mode. That is PUBSUB SHARDCHANNELS
gets rejected in non cluster mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignore me, I missed that you included those. 💯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using SHARDCHANNELS and SHARDNUMSUB in non cluster mode will work, i'll add this check and update tests
src/server/main_service.cc
Outdated
string_view pattern; | ||
if ((subcmd == "CHANNELS" && IsClusterEnabled()) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small nit: I would store the comparison subcmd == "CHANNELS
and subcmd == "SHARDCHANNELS
into a variable. I would also centralize the checks above in one place:
if (IsClusterEnabled() && (IsChannels || IsNumSub())`
and one for non cluster
if (!IsClusterEnabled() && (IsShardChannels || blah blah))
That way we get checks at the top of the function and we avoid some of the extra checks.
src/server/main_service.cc
Outdated
if (subcmd == "CHANNELS") { | ||
auto cmd_err = [&]() { | ||
auto err = absl::StrCat("PUBSUB ", subcmd, " is not supported", | ||
IsClusterEnabled() ? " in cluster mode yet" : " in non cluster mode"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kostasrim I think that the check should be IsClusterEnabledOrEmulated() right?
cause we should enable cluster commands in emulated mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh we have Emulated() as well. Good catch. We also need to fix sharded pub sub as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkaruza Dragonfly has emulated cluster mode which runs a single shard and in this state cluster and non cluster client are allowed.
This means that we should allow global pubsub command to run both on non cluster and emulated mode and sharded pubsub commands to run on both cluster and emulated mode, hence the check to send the error below should be fixed
864ff85
to
7749f10
Compare
src/server/server_family_test.cc
Outdated
@@ -547,4 +547,18 @@ TEST_F(ServerFamilyTest, CommandDocsOk) { | |||
EXPECT_THAT(Run({"command", "docs"}), "OK"); | |||
} | |||
|
|||
TEST_F(ServerFamilyTest, PubSubCommandErr) { | |||
auto* flag = absl::FindCommandLineFlag("cluster_mode"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto cluster_mode = absl::GetFlag(FLAGS_cluster_mode); cluster_mode == "")
@mkaruza I can see that HllFamilyTest.Promote fail on the CI but its not related to your changes. |
Signed-off-by: mkaruza <mario@dragonflydb.io>
We need to sort results because result is not deterministic
e759608
to
8f622a4
Compare
Add support for
PUB SHARDCHANNELS
andPUB SHARDNUMSUB
and report error back if sub command is not allow to run in non cluster mode.resolves #847