mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2024-12-15 17:51:06 +00:00
feat(hset_family): Add NX option to HSETEX (#3295)
* feature(hset_family): Add NX option to HSETEX fixes dragonflydb#3265 Signed-off-by: Stepan Bagritsevich <bagr.stepan@gmail.com> * refactor(hset_family): Fix returned value in the HSETEX command Signed-off-by: Stepan Bagritsevich <bagr.stepan@gmail.com> * refactor: Revert the changes of the returned value for the HSETEX command Signed-off-by: Stepan Bagritsevich <bagr.stepan@gmail.com> --------- Signed-off-by: Stepan Bagritsevich <bagr.stepan@gmail.com>
This commit is contained in:
parent
bfa5df5d6c
commit
d648e3ddd1
2 changed files with 62 additions and 11 deletions
|
@ -13,6 +13,7 @@ extern "C" {
|
|||
|
||||
#include "base/logging.h"
|
||||
#include "core/string_map.h"
|
||||
#include "facade/cmd_arg_parser.h"
|
||||
#include "server/acl/acl_commands_def.h"
|
||||
#include "server/command_registry.h"
|
||||
#include "server/conn_context.h"
|
||||
|
@ -714,14 +715,15 @@ void HGetGeneric(CmdArgList args, ConnectionContext* cntx, uint8_t getall_mask)
|
|||
}
|
||||
}
|
||||
|
||||
// HSETEX key tll_sec field value field value ...
|
||||
// HSETEX key [NX] tll_sec field value field value ...
|
||||
void HSetEx(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() % 2 != 0) {
|
||||
return cntx->SendError(facade::WrongNumArgsError(cntx->cid->name()), kSyntaxErrType);
|
||||
}
|
||||
CmdArgParser parser{args};
|
||||
|
||||
string_view key = parser.Next();
|
||||
|
||||
bool skip_if_exists = static_cast<bool>(parser.Check("NX"sv).IgnoreCase());
|
||||
string_view ttl_str = parser.Next();
|
||||
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view ttl_str = ArgS(args, 1);
|
||||
uint32_t ttl_sec;
|
||||
constexpr uint32_t kMaxTtl = (1UL << 26);
|
||||
|
||||
|
@ -729,12 +731,16 @@ void HSetEx(CmdArgList args, ConnectionContext* cntx) {
|
|||
return cntx->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
args.remove_prefix(2);
|
||||
OpSetParams op_sp;
|
||||
op_sp.ttl = ttl_sec;
|
||||
CmdArgList fields = parser.Tail();
|
||||
|
||||
if (fields.size() % 2 != 0) {
|
||||
return cntx->SendError(facade::WrongNumArgsError(cntx->cid->name()), kSyntaxErrType);
|
||||
}
|
||||
|
||||
OpSetParams op_sp{skip_if_exists, ttl_sec};
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpSet(t->GetOpArgs(shard), key, args, op_sp);
|
||||
return OpSet(t->GetOpArgs(shard), key, fields, op_sp);
|
||||
};
|
||||
|
||||
OpResult<uint32_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
|
|
|
@ -306,13 +306,58 @@ TEST_F(HSetFamilyTest, HRandField) {
|
|||
TEST_F(HSetFamilyTest, HSetEx) {
|
||||
TEST_current_time_ms = kMemberExpiryBase * 1000; // to reset to test time.
|
||||
|
||||
EXPECT_THAT(Run({"HSETEX", "k", "1", "f", "v"}), IntArg(1));
|
||||
auto resp = Run({"HSETEX", "k", "1", "f", "v"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
|
||||
AdvanceTime(500);
|
||||
EXPECT_THAT(Run({"HGET", "k", "f"}), "v");
|
||||
|
||||
AdvanceTime(500);
|
||||
EXPECT_THAT(Run({"HGET", "k", "f"}), ArgType(RespExpr::NIL));
|
||||
|
||||
const std::string_view long_time = "100"sv;
|
||||
|
||||
resp = Run({"HSETEX", "k", long_time, "field1", "value"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
|
||||
resp = Run({"HSETEX", "k", long_time, "field1", "new_value"});
|
||||
EXPECT_THAT(resp, IntArg(0));
|
||||
|
||||
resp = Run({"HGET", "k", "field1"});
|
||||
EXPECT_THAT(resp, "new_value"); // HSETEX without NX option; value was replaced by new_value
|
||||
|
||||
resp = Run({"HSETEX", "k", long_time, "field2", "value"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
|
||||
resp = Run({"HSETEX", "k", "NX", long_time, "field2", "new_value"});
|
||||
EXPECT_THAT(resp, IntArg(0));
|
||||
|
||||
resp = Run({"HGET", "k", "field2"});
|
||||
EXPECT_THAT(resp, "value"); // HSETEX with NX option; value was NOT replaced by new_value
|
||||
|
||||
const std::string_view short_time = "1"sv;
|
||||
|
||||
resp = Run({"HSETEX", "k", long_time, "field3", "value"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
|
||||
resp = Run({"HSETEX", "k", short_time, "field3", "value"});
|
||||
EXPECT_THAT(resp, IntArg(0));
|
||||
|
||||
AdvanceTime(1000);
|
||||
resp = Run({"HGET", "k", "field3"});
|
||||
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||
// HSETEX without NX option; old expiration time was replaced by a new one
|
||||
|
||||
resp = Run({"HSETEX", "k", long_time, "field4", "value"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
|
||||
resp = Run({"HSETEX", "k", "NX", short_time, "field4", "value"});
|
||||
EXPECT_THAT(resp, IntArg(0));
|
||||
|
||||
AdvanceTime(1100);
|
||||
resp = Run({"HGET", "k", "field4"});
|
||||
EXPECT_THAT(resp,
|
||||
"value"); // HSETEX with NX option; old expiration time was NOT replaced by a new one
|
||||
}
|
||||
|
||||
TEST_F(HSetFamilyTest, TriggerConvertToStrMap) {
|
||||
|
|
Loading…
Reference in a new issue