mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2024-12-14 11:58:02 +00:00
fix(server): support for persist command #345 Co-authored-by: Boaz Sade <boaz@dragonflydb.io>
This commit is contained in:
parent
bfc073b59d
commit
8f5500af16
4 changed files with 62 additions and 11 deletions
|
@ -177,7 +177,7 @@ with respect to Memcached and Redis APIs.
|
||||||
- [X] EVAL
|
- [X] EVAL
|
||||||
- [X] EVALSHA
|
- [X] EVALSHA
|
||||||
- [ ] OBJECT
|
- [ ] OBJECT
|
||||||
- [ ] PERSIST
|
- [x] PERSIST
|
||||||
- [X] PTTL
|
- [X] PTTL
|
||||||
- [ ] RESTORE
|
- [ ] RESTORE
|
||||||
- [X] SCRIPT LOAD/EXISTS
|
- [X] SCRIPT LOAD/EXISTS
|
||||||
|
|
|
@ -29,6 +29,8 @@ using namespace facade;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
OpStatus OpPersist(const OpArgs& op_args, string_view key);
|
||||||
|
|
||||||
class Renamer {
|
class Renamer {
|
||||||
public:
|
public:
|
||||||
Renamer(ShardId source_id) : src_sid_(source_id) {
|
Renamer(ShardId source_id) : src_sid_(source_id) {
|
||||||
|
@ -177,6 +179,22 @@ struct ScanOpts {
|
||||||
unsigned bucket_id = UINT_MAX;
|
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) {
|
bool ScanCb(const OpArgs& op_args, PrimeIterator it, const ScanOpts& opts, StringVec* res) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.shard->db_slice();
|
||||||
if (it->second.HasExpire()) {
|
if (it->second.HasExpire()) {
|
||||||
|
@ -348,6 +366,15 @@ void GenericFamily::Exists(CmdArgList args, ConnectionContext* cntx) {
|
||||||
return (*cntx)->SendLong(result.load(memory_order_release));
|
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) {
|
void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) {
|
||||||
string_view key = ArgS(args, 1);
|
string_view key = ArgS(args, 1);
|
||||||
string_view sec = ArgS(args, 2);
|
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{"EXISTS", CO::READONLY | CO::FAST, -2, 1, -1, 1}.HFUNC(Exists)
|
||||||
<< CI{"EXPIRE", CO::WRITE | CO::FAST, 3, 1, 1, 1}.HFUNC(Expire)
|
<< 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{"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{"KEYS", CO::READONLY, 2, 0, 0, 0}.HFUNC(Keys)
|
||||||
<< CI{"PEXPIREAT", CO::WRITE | CO::FAST, 3, 1, 1, 1}.HFUNC(PexpireAt)
|
<< CI{"PEXPIREAT", CO::WRITE | CO::FAST, 3, 1, 1, 1}.HFUNC(PexpireAt)
|
||||||
<< CI{"RENAME", CO::WRITE, 3, 1, 2, 1}.HFUNC(Rename)
|
<< CI{"RENAME", CO::WRITE, 3, 1, 2, 1}.HFUNC(Rename)
|
||||||
|
|
|
@ -46,6 +46,7 @@ class GenericFamily {
|
||||||
static void Exists(CmdArgList args, ConnectionContext* cntx);
|
static void Exists(CmdArgList args, ConnectionContext* cntx);
|
||||||
static void Expire(CmdArgList args, ConnectionContext* cntx);
|
static void Expire(CmdArgList args, ConnectionContext* cntx);
|
||||||
static void ExpireAt(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 Keys(CmdArgList args, ConnectionContext* cntx);
|
||||||
static void PexpireAt(CmdArgList args, ConnectionContext* cntx);
|
static void PexpireAt(CmdArgList args, ConnectionContext* cntx);
|
||||||
static void Stick(CmdArgList args, ConnectionContext* cntx);
|
static void Stick(CmdArgList args, ConnectionContext* cntx);
|
||||||
|
|
|
@ -282,21 +282,28 @@ TEST_F(GenericFamilyTest, Sort) {
|
||||||
// numeric
|
// numeric
|
||||||
ASSERT_THAT(Run({"sort", "list-1"}).GetVec(), ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
|
ASSERT_THAT(Run({"sort", "list-1"}).GetVec(), ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
|
||||||
// string
|
// 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
|
// 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
|
// 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
|
// 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", "5"}).GetVec(),
|
||||||
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "0", "10"}).GetVec(), ElementsAre("1.2", "2.20", "3.5", "10.1", "200"));
|
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", "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", "1", "1"}), "2.20");
|
||||||
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "4", "2"}), "200");
|
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "4", "2"}), "200");
|
||||||
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "5", "2"}), ArrLen(0));
|
ASSERT_THAT(Run({"sort", "list-1", "LIMIT", "5", "2"}), ArrLen(0));
|
||||||
// limits desc
|
// 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", "0", "5"}).GetVec(),
|
||||||
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "2", "2"}).GetVec(), ElementsAre("3.5", "2.20"));
|
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", "1", "1"}), "10.1");
|
||||||
ASSERT_THAT(Run({"sort", "list-1", "DESC", "LIMIT", "5", "2"}), ArrLen(0));
|
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({"del", "set-1"});
|
||||||
Run({"sadd", "set-1", "5.3", "4.4", "60", "99.9", "100", "9"});
|
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"}).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", "ALPHA"}).GetVec(),
|
||||||
ASSERT_THAT(Run({"sort", "set-1", "DESC"}).GetVec(), ElementsAre("100", "99.9", "60", "9", "5.3", "4.4"));
|
ElementsAre("100", "4.4", "5.3", "60", "9", "99.9"));
|
||||||
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", "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
|
// Test intset sort
|
||||||
Run({"del", "intset-1"});
|
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
|
} // namespace dfly
|
||||||
|
|
Loading…
Reference in a new issue