feat(server): Add GETDEL command (#365)
* Added GETDEL command * fix(server): Implement Del inside OpGet * fix(server): Swapped result for CHECK macro * docs(contributors): Added myself to Contributors
This commit is contained in:
parent
3bf08b803c
commit
ef1f0a9efc
|
@ -8,3 +8,4 @@
|
|||
* **[Ryan Russell](https://github.com/ryanrussell)**
|
||||
* Docs & Code Readability
|
||||
* **[Ali-Akber Saifee](https://github.com/alisaifee)**
|
||||
* **[Elle Y](https://github.com/inohime)**
|
|
@ -191,13 +191,24 @@ OpResult<bool> ExtendOrSkip(const OpArgs& op_args, string_view key, string_view
|
|||
return ExtendExisting(op_args, *it_res, key, val, prepend);
|
||||
}
|
||||
|
||||
OpResult<string> OpGet(const OpArgs& op_args, string_view key) {
|
||||
OpResult<string> OpGet(const OpArgs& op_args, string_view key, bool del_hit = false) {
|
||||
OpResult<PrimeIterator> it_res = op_args.shard->db_slice().Find(op_args.db_cntx, key, OBJ_STRING);
|
||||
if (!it_res.ok())
|
||||
return it_res.status();
|
||||
|
||||
const PrimeValue& pv = it_res.value()->second;
|
||||
|
||||
if (del_hit) {
|
||||
string key_bearer = GetString(op_args.shard, pv);
|
||||
|
||||
DVLOG(1) << "Del: " << key;
|
||||
auto& db_slice = op_args.shard->db_slice();
|
||||
|
||||
CHECK(db_slice.Del(op_args.db_cntx.db_index, it_res.value()));
|
||||
|
||||
return key_bearer;
|
||||
}
|
||||
|
||||
return GetString(op_args.shard, pv);
|
||||
}
|
||||
|
||||
|
@ -597,6 +608,36 @@ void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
}
|
||||
|
||||
void StringFamily::GetDel(CmdArgList args, ConnectionContext* cntx) {
|
||||
get_qps.Inc();
|
||||
|
||||
string_view key = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
bool run_del = true;
|
||||
return OpGet(t->GetOpArgs(shard), key, run_del);
|
||||
};
|
||||
|
||||
DVLOG(1) << "Before Get::ScheduleSingleHopT " << key;
|
||||
|
||||
Transaction* trans = cntx->transaction;
|
||||
OpResult<string> result = trans->ScheduleSingleHopT(std::move(cb));
|
||||
|
||||
if (result) {
|
||||
DVLOG(1) << "GET " << trans->DebugId() << ": " << key << " " << result.value();
|
||||
(*cntx)->SendBulkString(*result);
|
||||
} else {
|
||||
switch (result.status()) {
|
||||
case OpStatus::WRONG_TYPE:
|
||||
(*cntx)->SendError(kWrongTypeErr);
|
||||
break;
|
||||
default:
|
||||
DVLOG(1) << "GET " << key << " nil";
|
||||
(*cntx)->SendNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StringFamily::GetSet(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view value = ArgS(args, 2);
|
||||
|
@ -1038,6 +1079,7 @@ void StringFamily::Register(CommandRegistry* registry) {
|
|||
<< CI{"INCRBYFLOAT", CO::WRITE | CO::DENYOOM | CO::FAST, 3, 1, 1, 1}.HFUNC(IncrByFloat)
|
||||
<< CI{"DECRBY", CO::WRITE | CO::DENYOOM | CO::FAST, 3, 1, 1, 1}.HFUNC(DecrBy)
|
||||
<< CI{"GET", CO::READONLY | CO::FAST, 2, 1, 1, 1}.HFUNC(Get)
|
||||
<< CI{"GETDEL", CO::WRITE | CO::DENYOOM | CO::FAST, 2, 1, 1, 1}.HFUNC(GetDel)
|
||||
<< CI{"GETSET", CO::WRITE | CO::DENYOOM | CO::FAST, 3, 1, 1, 1}.HFUNC(GetSet)
|
||||
<< CI{"MGET", CO::READONLY | CO::FAST | CO::REVERSE_MAPPING, -2, 1, -1, 1}.HFUNC(MGet)
|
||||
<< CI{"MSET", CO::WRITE | CO::DENYOOM, -3, 1, -1, 2}.HFUNC(MSet)
|
||||
|
|
|
@ -57,6 +57,7 @@ class StringFamily {
|
|||
static void Decr(CmdArgList args, ConnectionContext* cntx);
|
||||
static void DecrBy(CmdArgList args, ConnectionContext* cntx);
|
||||
static void Get(CmdArgList args, ConnectionContext* cntx);
|
||||
static void GetDel(CmdArgList args, ConnectionContext* cntx);
|
||||
static void GetRange(CmdArgList args, ConnectionContext* cntx);
|
||||
static void GetSet(CmdArgList args, ConnectionContext* cntx);
|
||||
static void Incr(CmdArgList args, ConnectionContext* cntx);
|
||||
|
|
|
@ -387,4 +387,16 @@ TEST_F(StringFamilyTest, SetPxAtExAt) {
|
|||
EXPECT_EQ(Run({"get", "foo2"}), "abc");
|
||||
}
|
||||
|
||||
TEST_F(StringFamilyTest, GetDel) {
|
||||
auto resp = Run({"set", "foo", "bar"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"getdel", "foo"});
|
||||
// foo's value
|
||||
ASSERT_THAT(resp, ArgType(RespExpr::STRING));
|
||||
|
||||
resp = Run({"get", "foo"});
|
||||
ASSERT_THAT(resp, ArgType(RespExpr::NIL));
|
||||
}
|
||||
|
||||
} // namespace dfly
|
||||
|
|
Loading…
Reference in New Issue