feat(server): support for persist command #345 (#354)

fix(server): support for persist command #345

Co-authored-by: Boaz Sade <boaz@dragonflydb.io>
This commit is contained in:
Boaz Sade 2022-10-04 15:53:18 +03:00 committed by GitHub
parent bfc073b59d
commit 8f5500af16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 11 deletions

View File

@ -177,7 +177,7 @@ with respect to Memcached and Redis APIs.
- [X] EVAL
- [X] EVALSHA
- [ ] OBJECT
- [ ] PERSIST
- [x] PERSIST
- [X] PTTL
- [ ] RESTORE
- [X] SCRIPT LOAD/EXISTS

View File

@ -29,6 +29,8 @@ using namespace facade;
namespace {
OpStatus OpPersist(const OpArgs& op_args, string_view key);
class Renamer {
public:
Renamer(ShardId source_id) : src_sid_(source_id) {
@ -177,6 +179,22 @@ struct ScanOpts {
unsigned bucket_id = UINT_MAX;
};
OpStatus OpPersist(const OpArgs& op_args, string_view key) {
auto& db_slice = op_args.shard->db_slice();
auto [it, expire_it] = db_slice.FindExt(op_args.db_cntx, key);
if (!IsValid(it)) {
return OpStatus::KEY_NOTFOUND;
} else {
if (IsValid(expire_it)) {
// The SKIPPED not really used, just placeholder for error
return db_slice.UpdateExpire(op_args.db_cntx.db_index, it, 0) ? OpStatus::OK
: OpStatus::SKIPPED;
}
return OpStatus::OK; // fall though - this is the default
}
}
bool ScanCb(const OpArgs& op_args, PrimeIterator it, const ScanOpts& opts, StringVec* res) {
auto& db_slice = op_args.shard->db_slice();
if (it->second.HasExpire()) {
@ -348,6 +366,15 @@ void GenericFamily::Exists(CmdArgList args, ConnectionContext* cntx) {
return (*cntx)->SendLong(result.load(memory_order_release));
}
void GenericFamily::Persist(CmdArgList args, ConnectionContext* cntx) {
string_view key = ArgS(args, 1);
auto cb = [&](Transaction* t, EngineShard* shard) { return OpPersist(t->GetOpArgs(shard), key); };
OpStatus status = cntx->transaction->ScheduleSingleHop(move(cb));
(*cntx)->SendLong(status == OpStatus::OK);
}
void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) {
string_view key = ArgS(args, 1);
string_view sec = ArgS(args, 2);
@ -1036,6 +1063,7 @@ void GenericFamily::Register(CommandRegistry* registry) {
<< CI{"EXISTS", CO::READONLY | CO::FAST, -2, 1, -1, 1}.HFUNC(Exists)
<< CI{"EXPIRE", CO::WRITE | CO::FAST, 3, 1, 1, 1}.HFUNC(Expire)
<< CI{"EXPIREAT", CO::WRITE | CO::FAST, 3, 1, 1, 1}.HFUNC(ExpireAt)
<< CI{"PERSIST", CO::WRITE | CO::FAST, 2, 1, 1, 1}.HFUNC(Persist)
<< CI{"KEYS", CO::READONLY, 2, 0, 0, 0}.HFUNC(Keys)
<< CI{"PEXPIREAT", CO::WRITE | CO::FAST, 3, 1, 1, 1}.HFUNC(PexpireAt)
<< CI{"RENAME", CO::WRITE, 3, 1, 2, 1}.HFUNC(Rename)

View File

@ -46,6 +46,7 @@ class GenericFamily {
static void Exists(CmdArgList args, ConnectionContext* cntx);
static void Expire(CmdArgList args, ConnectionContext* cntx);
static void ExpireAt(CmdArgList args, ConnectionContext* cntx);
static void Persist(CmdArgList args, ConnectionContext* cntx);
static void Keys(CmdArgList args, ConnectionContext* cntx);
static void PexpireAt(CmdArgList args, ConnectionContext* cntx);
static void Stick(CmdArgList args, ConnectionContext* cntx);

View File

@ -282,21 +282,28 @@ TEST_F(GenericFamilyTest, Sort) {
// numeric
ASSERT_THAT(Run({"sort", "list-1"}).GetVec(), ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
// string
ASSERT_THAT(Run({"sort", "list-1", "ALPHA"}).GetVec(), ElementsAre("1.2", "10.1", "2.20", "200", "3.5"));
ASSERT_THAT(Run({"sort", "list-1", "ALPHA"}).GetVec(),
ElementsAre("1.2", "10.1", "2.20", "200", "3.5"));
// desc numeric
ASSERT_THAT(Run({"sort", "list-1", "DESC"}).GetVec(), ElementsAre("200", "10.1", "3.5", "2.20", "1.2"));
ASSERT_THAT(Run({"sort", "list-1", "DESC"}).GetVec(),
ElementsAre("200", "10.1", "3.5", "2.20", "1.2"));
// desc strig
ASSERT_THAT(Run({"sort", "list-1", "DESC", "ALPHA"}).GetVec(), ElementsAre("3.5", "200", "2.20", "10.1", "1.2"));
ASSERT_THAT(Run({"sort", "list-1", "DESC", "ALPHA"}).GetVec(),
ElementsAre("3.5", "200", "2.20", "10.1", "1.2"));
// limits
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "0", "5"}).GetVec(), ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "0", "10"}).GetVec(), ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "0", "5"}).GetVec(),
ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "0", "10"}).GetVec(),
ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "2", "2"}).GetVec(), ElementsAre("3.5", "10.1"));
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "1", "1"}), "2.20");
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "4", "2"}), "200");
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "5", "2"}), ArrLen(0));
// limits desc
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "0", "5"}).GetVec(), ElementsAre("200", "10.1", "3.5", "2.20", "1.2"));
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "2", "2"}).GetVec(), ElementsAre("3.5", "2.20"));
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "0", "5"}).GetVec(),
ElementsAre("200", "10.1", "3.5", "2.20", "1.2"));
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "2", "2"}).GetVec(),
ElementsAre("3.5", "2.20"));
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "1", "1"}), "10.1");
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "5", "2"}), ArrLen(0));
@ -304,9 +311,12 @@ TEST_F(GenericFamilyTest, Sort) {
Run({"del", "set-1"});
Run({"sadd", "set-1", "5.3", "4.4", "60", "99.9", "100", "9"});
ASSERT_THAT(Run({"sort", "set-1"}).GetVec(), ElementsAre("4.4", "5.3", "9", "60", "99.9", "100"));
ASSERT_THAT(Run({"sort", "set-1", "ALPHA"}).GetVec(), ElementsAre("100", "4.4", "5.3", "60", "9", "99.9"));
ASSERT_THAT(Run({"sort", "set-1", "DESC"}).GetVec(), ElementsAre("100", "99.9", "60", "9", "5.3", "4.4"));
ASSERT_THAT(Run({"sort", "set-1", "DESC", "ALPHA"}).GetVec(), ElementsAre("99.9", "9", "60", "5.3", "4.4", "100"));
ASSERT_THAT(Run({"sort", "set-1", "ALPHA"}).GetVec(),
ElementsAre("100", "4.4", "5.3", "60", "9", "99.9"));
ASSERT_THAT(Run({"sort", "set-1", "DESC"}).GetVec(),
ElementsAre("100", "99.9", "60", "9", "5.3", "4.4"));
ASSERT_THAT(Run({"sort", "set-1", "DESC", "ALPHA"}).GetVec(),
ElementsAre("99.9", "9", "60", "5.3", "4.4", "100"));
// Test intset sort
Run({"del", "intset-1"});
@ -354,4 +364,16 @@ TEST_F(GenericFamilyTest, Time) {
}
}
TEST_F(GenericFamilyTest, Persist) {
auto resp = Run({"set", "mykey", "somevalue"});
EXPECT_EQ(resp, "OK");
// Key without expiration time - return 1
EXPECT_EQ(1, CheckedInt({"persist", "mykey"}));
// set expiration time and try again
resp = Run({"EXPIRE", "mykey", "10"});
EXPECT_EQ(10, CheckedInt({"TTL", "mykey"}));
EXPECT_EQ(1, CheckedInt({"persist", "mykey"}));
EXPECT_EQ(-1, CheckedInt({"TTL", "mykey"}));
}
} // namespace dfly