fix: loading state error type to be compatible with redis (#2629)

* add -LOADING prefix for loading errors
* replace -ERR with -LOADING for loading errors
This commit is contained in:
Kostas Kyrimis 2024-02-20 14:45:41 +02:00 committed by GitHub
parent 75eaeb32db
commit a1950038b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 20 additions and 10 deletions

View file

@ -31,6 +31,7 @@ extern const char kIndexOutOfRange[];
extern const char kOutOfMemory[];
extern const char kInvalidNumericResult[];
extern const char kClusterNotConfigured[];
extern const char kLoadingErr[];
extern const char kSyntaxErrType[];
extern const char kScriptErrType[];

View file

@ -90,6 +90,7 @@ const char kIndexOutOfRange[] = "index out of range";
const char kOutOfMemory[] = "Out of memory";
const char kInvalidNumericResult[] = "result is not a number";
const char kClusterNotConfigured[] = "Cluster is not yet configured";
const char kLoadingErr[] = "-LOADING Dragonfly is loading the dataset in memory";
const char kSyntaxErrType[] = "syntax_error";
const char kScriptErrType[] = "script_error";

View file

@ -303,10 +303,11 @@ void RedisReplyBuilder::SendError(string_view str, string_view err_type) {
if (str[0] == '-') {
iovec v[] = {IoVec(str), IoVec(kCRLF)};
Send(v, ABSL_ARRAYSIZE(v));
} else {
iovec v[] = {IoVec(kErrPref), IoVec(str), IoVec(kCRLF)};
Send(v, ABSL_ARRAYSIZE(v));
return;
}
iovec v[] = {IoVec(kErrPref), IoVec(str), IoVec(kCRLF)};
Send(v, ABSL_ARRAYSIZE(v));
}
void RedisReplyBuilder::SendProtocolError(std::string_view str) {

View file

@ -988,7 +988,8 @@ std::optional<ErrorReply> Service::VerifyCommandState(const CommandId* cid, CmdA
// Check if the command is allowed to execute under this global state
bool allowed_by_state = true;
switch (etl.gstate()) {
const GlobalState gstate = etl.gstate();
switch (gstate) {
case GlobalState::LOADING:
allowed_by_state = dfly_cntx.journal_emulated || (cid->opt_mask() & CO::LOADING);
break;
@ -1004,8 +1005,13 @@ std::optional<ErrorReply> Service::VerifyCommandState(const CommandId* cid, CmdA
if (!allowed_by_state) {
VLOG(1) << "Command " << cid->name() << " not executed because global state is "
<< GlobalStateName(etl.gstate());
return ErrorReply{StrCat("Can not execute during ", GlobalStateName(etl.gstate()))};
<< GlobalStateName(gstate);
if (gstate == GlobalState::LOADING) {
return ErrorReply(kLoadingErr);
}
return ErrorReply{StrCat("Can not execute during ", GlobalStateName(gstate))};
}
string_view cmd_name{cid->name()};

View file

@ -2196,7 +2196,7 @@ void ServerFamily::ReplicaOfInternal(string_view host, string_view port_sv, Conn
// We should not execute replica of command while loading from snapshot.
if (ServerState::tlocal()->is_master && service_.GetGlobalState() == GlobalState::LOADING) {
cntx->SendError("Can not execute during LOADING");
cntx->SendError(kLoadingErr);
return;
}

View file

@ -1862,8 +1862,8 @@ async def test_replicaof_reject_on_load(df_local_factory, df_seeder_factory):
try:
await c_replica.execute_command(f"REPLICAOF localhost {master.port}")
assert False
except aioredis.ResponseError as e:
assert "Can not execute during LOADING" in str(e)
except aioredis.BusyLoadingError as e:
assert "Dragonfly is loading the dataset in memory" in str(e)
# Check one we finish loading snapshot replicaof success
await wait_available_async(c_replica)
await c_replica.execute_command(f"REPLICAOF localhost {master.port}")

View file

@ -52,7 +52,8 @@ async def wait_available_async(client: aioredis.Redis, timeout=10):
if "MOVED" in str(e):
# MOVED means we *can* serve traffic, but 'key' does not belong to an owned slot
return
assert "Can not execute during LOADING" in str(e)
except aioredis.BusyLoadingError as e:
assert "Dragonfly is loading the dataset in memory" in str(e)
# Print W to indicate test is waiting for replica
print("W", end="", flush=True)