1
0
Fork 0
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:
Stepan Bagritsevich 2024-07-18 16:09:04 +04:00 committed by GitHub
parent bfa5df5d6c
commit d648e3ddd1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 11 deletions

View file

@ -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));

View file

@ -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) {