Skip to content

Commit

Permalink
[redis proxy]: redis unsupported command message compatibility
Browse files Browse the repository at this point in the history
Signed-off-by: duanhongyi <duanhongyi@doopai.com>
  • Loading branch information
duanhongyi committed Dec 19, 2024
1 parent dce5821 commit 234aa23
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 10 deletions.
2 changes: 1 addition & 1 deletion docs/root/intro/arch_overview/other_protocols/redis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ Envoy can also generate its own errors in response to the client.
the connection."
invalid request, "Command was rejected by the first stage of the command splitter due to
datatype or length."
unsupported command, "The command was not recognized by Envoy and therefore cannot be serviced
ERR unknown command, "The command was not recognized by Envoy and therefore cannot be serviced
because it cannot be hashed to a backend server."
finished with n errors, "Fragmented commands which sum the response (e.g. DEL) will return the
total number of errors received if any were received."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ struct SupportedCommands {
static bool isReadCommand(const std::string& command) {
return !writeCommands().contains(command);
}

static bool isSupportCommand(const std::string& command) {
return (simpleCommands().contains(command) || evalCommands().contains(command) ||
hashMultipleSumResultCommands().contains(command) ||
transactionCommands().contains(command) || auth() == command || echo() == command ||
mget() == command || mset() == command || keys() == command || ping() == command ||
time() == command || quit() == command || select() == command);
}
};

} // namespace Redis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,15 @@ SplitRequestPtr InstanceImpl::makeRequest(Common::Redis::RespValuePtr&& request,
}

std::string command_name = absl::AsciiStrToLower(request->asArray()[0].asString());
// Compatible with redis behavior, if there is an unsupported command, return immediately,
// this action must be performed before verifying auth, some redis clients rely on this behavior.
if (!Common::Redis::SupportedCommands::isSupportCommand(command_name)) {
stats_.unsupported_command_.inc();
callbacks.onResponse(Common::Redis::Utility::makeError(fmt::format(
"ERR unknown command '{}', with args beginning with: {}", request->asArray()[0].asString(),
request->asArray().size() > 1 ? request->asArray()[1].asString() : "")));
return nullptr;
}

if (command_name == Common::Redis::SupportedCommands::auth()) {
if (request->asArray().size() < 2) {
Expand Down Expand Up @@ -836,12 +845,7 @@ SplitRequestPtr InstanceImpl::makeRequest(Common::Redis::RespValuePtr&& request,

// Get the handler for the downstream request
auto handler = handler_lookup_table_.find(command_name.c_str());
if (handler == nullptr) {
stats_.unsupported_command_.inc();
callbacks.onResponse(Common::Redis::Utility::makeError(
fmt::format("unsupported command '{}'", request->asArray()[0].asString())));
return nullptr;
}
ASSERT(handler != nullptr);

// If we are within a transaction, forward all requests to the transaction handler (i.e. handler
// of "multi" command).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ void InstanceImpl::init() {
});
}

//
//
uint16_t InstanceImpl::shardSize() { return tls_->getTyped<ThreadLocalPool>().shardSize(); }

// This method is always called from a InstanceSharedPtr we don't have to worry about tls_->getTyped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ TEST_F(RedisCommandSplitterImplTest, InvalidRequestArrayNotStrings) {
TEST_F(RedisCommandSplitterImplTest, UnsupportedCommand) {
Common::Redis::RespValue response;
response.type(Common::Redis::RespType::Error);
response.asString() = "unsupported command 'newcommand'";
response.asString() = "ERR unknown command 'newcommand', with args beginning with: hello";
EXPECT_CALL(callbacks_, connectionAllowed()).WillOnce(Return(true));
EXPECT_CALL(callbacks_, onResponse_(PointeesEq(&response)));
Common::Redis::RespValuePtr request{new Common::Redis::RespValue()};
Expand Down

0 comments on commit 234aa23

Please sign in to comment.