Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hash): add support of hash expiration commands #2717

Open
wants to merge 26 commits into
base: unstable
Choose a base branch
from

Conversation

ltagliamonte-dd
Copy link

based on #2402

  • fixed CommandHStrlen return
  • removed keyExpirationCheck in GetMetadata as per @PragmaTwice request
  • verified all cmds

@jjz921024 I verified all hash cmds and they seem to work without the additional check in GetMetadata do you happen to remember if there was a specific use case you added it there?

@ltagliamonte-dd ltagliamonte-dd changed the title Hfe feat(hash): Support hash field expiration Jan 9, 2025
@jjz921024
Copy link
Contributor

@ltagliamonte-dd Hi. Did you set this config hash-field-expiration to yes or run the unit tests in this branch? If the field has an expiration, we have to check to the field expiration before each read operation.

@ltagliamonte-dd
Copy link
Author

ltagliamonte-dd commented Jan 9, 2025

@ltagliamonte-dd Hi. Did you set this config hash-field-expiration to yes or run the unit tests in this branch? If the field has an expiration, we have to check to the field expiration before each read operation.

Hello @jjz921024 thanks for getting back to me, yes I did test all hash commands having hash-field-expiration yes.
I plan to give another looks at the code today, i'd love to get in touch with you to better understand the check because from what i could briefly see the key expiration check is also done in each cmds implementations.
I coudn't find your contact neither on the kvrocks slack nor zulipchat.
i did run the unit test with no problem the go integration test only a test case is failing (i plan to look at it today):

--- FAIL: TestHashFieldExpiration (7.66s)
    --- FAIL: TestHashFieldExpiration/HFE_check_hash_metadata_after_all_of_fields_expired (1.00s)
        hash_test.go:1018: 
            	Error Trace:	/Users/luigi.tagliamonte/Projects/doordash/kvrocks/tests/gocase/unit/type/hash/hash_test.go:1018
            	Error:      	Not equal: 
            	            	expected: -2ns
            	            	actual  : -1ns
            	Test:       	TestHashFieldExpiration/HFE_check_hash_metadata_after_all_of_fields_expired
FAIL
exit status 1
FAIL	github.com/apache/kvrocks/tests/gocase/unit/type/hash	199.945s

@ltagliamonte
Copy link

@jjz921024 the CI seems to pass removing the check in GetMetadata and fixing GetTime.
Would love to get it touch with you to see if I'm missing something here.

@git-hulk
Copy link
Member

@jjz921024 @ltagliamonte-dd Thanks for your great efforts. I took my first pass in a new PR and generally look in good shape from my perspective. Two nit points can be improved:

  1. Change ExistValidField to GetValidFieldCount, so that Hash::Size can also resue this function.
  2. Many places decode the hash metadata and check if it has any valid fields. We can avoid duplicate code by adding a dedicated function to this check.
    if (metadata.Type() == kRedisHash) {
      HashMetadata hash_metadata(false);
      s = hash_metadata.Decode(rocksdb::Slice(pin_values[i].data(), pin_values[i].size()));
      if (!s.ok()) continue;
      redis::Hash hash_db(storage_, namespace_);
      if (hash_db.ExistValidField(ctx, slice_keys[i], hash_metadata)) {

@git-hulk git-hulk changed the title feat(hash): Support hash field expiration feat(hash): add support of hash expiration commands Jan 11, 2025
@jjz921024
Copy link
Contributor

jjz921024 commented Jan 12, 2025

@ltagliamonte-dd Hi, I create a PR #1 in your kvrocks fork repo. There are some polish about this feature for your reference.

The purpose of this this commit aac63cc is to avoid unnecessary field expiration checks when executing the hset/hmset command, which comes from #2402 (comment) @PragmaTwice suggestion.

The purpose of this this commit 7306231 is make ExistValidField method more general so that Hash::Size can also resue it. which comes from @git-hulk suggestion.

@ltagliamonte-dd
Copy link
Author

Hello @jjz921024 thank you for the help on getting this through the finish line.
As I looked at the PR ltagliamonte-dd#1 I can see that GetMetadata still contains the expiration check on all fields keys, that @PragmaTwice was pointing out as possible perf problem.

Discussing this check with @PragmaTwice and @git-hulk on zulipchat we decided to move the check up in the call stack and perform it only when required.

As the CI on this PR is showing (and my verification) it looks like there is no need for expiration check in GetMetadata, I would love to hear from you if i'm missing something and why the check is required. Please join us on zulipchat so we can discuss this in a more interactive way.

by removing the check in GetMetadata commit aac63cc is not needed

thank you for commit 7306231 i will be importing it.

@ltagliamonte-dd
Copy link
Author

@git-hulk I gave a look at your suggestion to remove duplicated code, it looks like duplicated but if you look closely they are all slightly different checks... we may be able to refactor with something like this:

rocksdb::Status Hash::HandleRedisHash(engine::Context &ctx, const Metadata &metadata, const std::string &value,
                                  const std::string &key, std::function<void(int)> on_valid_field_count);

so we pass an handleFunction into the refactored function
Happy to hear if you have better/different ideas about it.

@git-hulk
Copy link
Member

@PragmaTwice @mapleFU @torwig @caipengbo To see if you guys can have a look at this PR. It generally looks good to me. It'd be nice to push this feature forward to avoid pending too long time.

@PragmaTwice
Copy link
Member

PragmaTwice commented Jan 22, 2025

I'll take a look at this weekend if no other things happen : )

cc @mapleFU PTAL.

Also now we need to solve git conflicts before reviewing and merging. cc @ltagliamonte-dd

@ltagliamonte-dd
Copy link
Author

@PragmaTwice can you please re-trigger the CI it looks like a flaky test

kvrocks.conf Outdated Show resolved Hide resolved
Comment on lines 749 to 755
rocksdb::Status Hash::encodeExpireToValue(std::string *value, uint64_t expire) {
std::string buf;
PutFixed64(&buf, expire);
buf.append(*value);
value->assign(buf.data(), buf.size());
return rocksdb::Status::OK();
}
Copy link
Member

@PragmaTwice PragmaTwice Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rocksdb::Status Hash::encodeExpireToValue(std::string *value, uint64_t expire) {
std::string buf;
PutFixed64(&buf, expire);
buf.append(*value);
value->assign(buf.data(), buf.size());
return rocksdb::Status::OK();
}
rocksdb::Status Hash::encodeExpireAndValue(std::string_view value, uint64_t expire, std::string *out) {
PutFixed64(out, expire);
out->append(value);
return rocksdb::Status::OK();
}

Also for all places that uses this function.

Copy link
Author

@ltagliamonte-dd ltagliamonte-dd Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PragmaTwice I have trouble understanding the suggestion.. would be this correct:

rocksdb::Status Hash::encodeExpireAndValue(std::string value, uint64_t expire, std::string *enc_value) {
  PutFixed64(enc_value, expire);
  enc_value->append(value);
  return rocksdb::Status::OK();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think string_view should be better here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PragmaTwice please let me know how 3a726e1 looks, happy to address further if needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PragmaTwice string_view comment addressed via b10d710

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I revisited it and I think it can be std::string Hash::encodeExpireAndValue(std::string_view value, uint64_t expire).

The returned status here seems useless.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::string Hash::encodeExpireAndValue(std::string_view value, uint64_t expire) {
  std::string out;
  PutFixed64(&out, expire);
  out.append(value);
  return out;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks addressed via 9bbc8d9

Copy link
Member

@PragmaTwice PragmaTwice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking that, size in hash metadata will become nearly a useless field while expiration is enabled, so it's a little tricky since we can easily misuse it. cc @git-hulk @mapleFU

@git-hulk
Copy link
Member

I'm thinking that, size in hash metadata will become nearly a useless field while expiration is enabled, so it's a little tricky since we can easily misuse it. cc @git-hulk @mapleFU

Yes, we need to take care of this after introducing the hash expiration feature. But we can try to improve this before formally releasing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants