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:zpopmax && zpopmin to do cache #2922

Closed
wants to merge 2 commits into from

Conversation

chejinge
Copy link
Collaborator

@chejinge chejinge commented Oct 10, 2024

fix issue #2892 (执行zpopmin后还能查询到被删除数据)
1.zpopmin与zpopmax作为写操作不会更新到cache值,导致对cache进行读操作的指令能读到被zpopmin删除的值,因此为zpopmin与zpopmax添加了更新cache的功能。
2.新增对应的测试case

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced ZPopMin and ZPopMax methods to remove and retrieve elements from sorted sets based on scores.
    • Enhanced ZPopmaxCmd and ZPopminCmd with new methods for database interaction and cache updates.
  • Bug Fixes

    • Improved error handling for cases where keys do not exist in the cache.
  • Refactor

    • Updated method signatures across several classes to enhance functionality and maintainability.

Copy link

coderabbitai bot commented Oct 10, 2024

Walkthrough

The changes in this pull request primarily involve modifications to the PikaCache, RedisCache, ZPopmaxCmd, and ZPopminCmd classes. Key updates include the addition of new methods for popping minimum and maximum elements from sorted sets, the enhancement of existing method signatures to include database references, and the introduction of new methods for command handling and cache updates. These updates aim to improve the functionality and interaction of the cache system with the database.

Changes

File Change Summary
include/pika_cache.h Added methods ZPopMin, ZPopMax; modified methods ZIncrbyIfKeyExist, ZRange, ZRevrange, ZRevrangebylex, ZRank, ZRangebylex to include database parameter.
src/cache/src/zset.cc Implemented ZPopMin and ZPopMax methods in RedisCache.
src/pika_cache.cc Implemented ZPopMin and ZPopMax methods in PikaCache.
src/pika_zset.cc Added methods DoThroughDB and DoUpdateCache in ZPopmaxCmd and ZPopminCmd.
tests/integration/zset_test.go Added test case for ZPopMin and ZPopMax operations to verify functionality.

Possibly related PRs

  • fix:Segmentation fault in zremrangebyrank #2896: The changes in this PR involve modifications to the ZRemrangebyrankCmd class, which includes updates to the DoUpdateCache method that now calls a version of ZRemrangebyrank with an additional db_ parameter. This is related to the main PR's changes in the PikaCache class, which also involve method signatures that include a const std::shared_ptr<DB>& db parameter for similar operations.

Suggested labels

☢️ Bug, 🧹 Updates

Suggested reviewers

  • AlexStocks
  • Mixficsol

🐇 In the cache where scores reside,
New methods pop, with joy and pride.
Min and max, they swiftly take,
From sorted sets, for users' sake.
With flags that guide, and commands so bright,
Our cache now dances, a wondrous sight! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the ✏️ Feature New feature or request label Oct 10, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🧹 Outside diff range and nitpick comments (9)
src/cache/include/cache.h (3)

150-150: LGTM! Consider adding a brief comment.

The ZPopMin method signature looks good and is consistent with other methods in the class. It efficiently uses references and pointers for input/output parameters.

Consider adding a brief comment explaining the method's functionality, e.g.:

// Removes and returns up to 'count' members with the lowest scores from the sorted set stored at 'key'.

151-151: LGTM! Consider adding a brief comment.

The ZPopMax method signature is consistent with ZPopMin and other methods in the class, which is excellent for maintainability and usability.

Consider adding a brief comment explaining the method's functionality, e.g.:

// Removes and returns up to 'count' members with the highest scores from the sorted set stored at 'key'.

150-151: Great addition to Zset functionality. Consider grouping related methods.

The addition of ZPopMin and ZPopMax methods enhances the RedisCache class's capabilities for sorted set operations. These methods are valuable for implementing priority queues, leaderboards, and other use cases requiring ordered data manipulation.

Consider grouping related Zset methods together for better code organization. For example, you might want to place ZPopMin and ZPopMax near other methods that modify the sorted set, such as ZAdd or ZRem.

include/pika_zset.h (1)

606-607: LGTM! Consider adding brief comments for the new methods.

The addition of DoThroughDB() and DoUpdateCache() methods is a good improvement, allowing for better database and cache interaction. The use of the override keyword is correct and follows best practices.

Consider adding brief inline comments to describe the purpose of these methods, which would improve the code's self-documentation. For example:

// Performs the command operation through the database
void DoThroughDB() override;

// Updates the cache after the command execution
void DoUpdateCache() override;
src/pika_zset.cc (2)

1514-1519: Consider adding error handling and validating count_.

The implementation looks good overall, but there are a couple of points to consider:

  1. The method doesn't handle the case where s_ is not ok and not "NotFound". This might lead to unexpected behavior if there's an error.

  2. The count_ variable is used without checking its value. If it's negative or zero, it might lead to unexpected behavior.

Consider adding error handling and validating count_:

 void ZPopmaxCmd::DoUpdateCache() {
   std::vector<storage::ScoreMember> score_members;
-  if (s_.ok() || s_.IsNotFound()) {
+  if (s_.ok()) {
+    if (count_ > 0) {
       db_->cache()->ZPopMax(key_, count_, &score_members, db_);
+    }
+  } else if (!s_.IsNotFound()) {
+    // Log error or handle it appropriately
   }
 }

Line range hint 1510-1546: Summary of changes to ZPopmaxCmd and ZPopminCmd

The additions to ZPopmaxCmd and ZPopminCmd classes implement DoThroughDB and DoUpdateCache methods, which are consistent with the pattern used in other commands in this file. However, there are a few areas that could be improved:

  1. Error Handling: Both DoUpdateCache methods could benefit from better error handling, especially for cases where s_ is not ok and not "NotFound".

  2. Input Validation: The count_ variable is used without validation in both DoUpdateCache methods. It should be checked to ensure it's positive before use.

  3. Code Duplication: There's significant similarity between the DoUpdateCache methods of ZPopmaxCmd and ZPopminCmd. Consider refactoring to reduce duplication, possibly by creating a base class with a template method.

  4. Consistency: Ensure that the error handling and input validation are consistent across all similar methods in the file.

Consider creating a base class for Zset commands that implements common functionality, which could then be inherited by specific command classes like ZPopmaxCmd and ZPopminCmd. This would promote code reuse and ensure consistency across similar operations.

src/pika_cache.cc (3)

1468-1481: Implementation looks good, with a minor note.

The ZPopMin function is well-implemented with proper thread safety and error handling. It correctly checks for the key's existence in the cache before performing the operation.

The db parameter is currently unused in the function body. If it's intentional (e.g., for consistency with other method signatures or future use), consider adding a comment explaining its purpose or use the [[maybe_unused]] attribute to suppress potential compiler warnings.


1483-1496: Implementation is correct and consistent with ZPopMin.

The ZPopMax function is well-implemented, mirroring the structure of ZPopMin. It ensures thread safety, proper error handling, and correctly delegates the operation to the cache object.

  1. The db parameter is unused, similar to ZPopMin. Consider adding a comment or using the [[maybe_unused]] attribute.
  2. Given the similarity between ZPopMin and ZPopMax, you might consider refactoring the common logic into a private helper function to reduce code duplication and improve maintainability.

1468-1496: Summary: Successful implementation of ZPopMin and ZPopMax functionality

The addition of ZPopMin and ZPopMax functions to the PikaCache class successfully implements the PR objectives. These functions enhance the cache's capabilities for sorted sets, allowing efficient pop operations for minimum and maximum elements.

Key points:

  1. Both functions are correctly implemented with proper thread safety and error handling.
  2. The implementations are consistent with each other and with the existing coding style in the PikaCache class.
  3. The changes integrate well with the existing codebase and extend the cache functionality as intended.

To further improve the code:

  1. Consider refactoring the common logic in ZPopMin and ZPopMax into a private helper function to reduce duplication.
  2. Address the unused db parameter in both functions, either by adding a comment explaining its purpose or by using the [[maybe_unused]] attribute.

These changes have a positive impact on the codebase by expanding the cache's functionality for sorted sets, which can potentially improve performance for certain operations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e12ee5e and 06aca57.

📒 Files selected for processing (7)
  • include/pika_cache.h (1 hunks)
  • include/pika_zset.h (2 hunks)
  • src/cache/include/cache.h (1 hunks)
  • src/cache/src/zset.cc (1 hunks)
  • src/pika_cache.cc (1 hunks)
  • src/pika_command.cc (1 hunks)
  • src/pika_zset.cc (2 hunks)
🧰 Additional context used
🔇 Additional comments (14)
include/pika_zset.h (1)

628-629: LGTM! Consistent with ZPopmaxCmd changes.

The addition of DoThroughDB() and DoUpdateCache() methods in ZPopminCmd is consistent with the changes made to ZPopmaxCmd, which is good for maintaining symmetry between these related commands.

As mentioned in the comment for ZPopmaxCmd, consider adding brief inline comments to describe the purpose of these methods.

src/pika_zset.cc (2)

1510-1512: Implementation looks good.

The DoThroughDB method correctly calls the Do() method, which is consistent with the pattern used in other commands in this file.


1537-1539: Implementation looks good.

The DoThroughDB method correctly calls the Do() method, which is consistent with the pattern used in other commands in this file.

src/pika_command.cc (2)

603-603: Approved: Enhanced ZPopmaxCmd with cache interaction

The ZPopmaxCmd constructor has been updated to include two new flags: kCmdFlagsDoThroughDB and kCmdFlagsUpdateCache. These additions improve the command's interaction with the cache:

  1. kCmdFlagsDoThroughDB ensures that the command interacts directly with the database, maintaining data consistency.
  2. kCmdFlagsUpdateCache allows the cache to be updated after the database operation, keeping the cache in sync.

These changes align well with the PR objective of implementing cache functionality for the zpopmax command, potentially improving performance while maintaining data integrity.


607-607: Approved: Consistent enhancement of ZPopminCmd with cache interaction

The ZPopminCmd constructor has been updated in a manner consistent with the ZPopmaxCmd changes. The addition of kCmdFlagsDoThroughDB and kCmdFlagsUpdateCache flags ensures that:

  1. The command interacts directly with the database, maintaining data consistency.
  2. The cache is updated after the database operation, keeping it in sync.

This consistency between zpopmin and zpopmax is commendable, as these complementary commands should have similar behavior with respect to cache interactions.

include/pika_cache.h (9)

152-153: Addition of parameters to ZIncrbyIfKeyExist method is appropriate

The updated method signature with the added parameters ZIncrbyCmd* cmd and const std::shared_ptr<DB>& db is consistent with other methods and enhances functionality.


154-155: Update to ZRange method signature is appropriate and consistent

Adding const std::shared_ptr<DB>& db to the ZRange method aligns with other method signatures and allows for enhanced database interaction.


163-164: Update to ZRevrange method signature is appropriate and consistent

Adding const std::shared_ptr<DB>& db to the ZRevrange method ensures consistency and facilitates database transactions.


168-169: Update to ZRevrangebylex method signature is appropriate and consistent

Including const std::shared_ptr<DB>& db in the ZRevrangebylex method aligns it with the other methods and supports database interactions.


170-170: Update to ZRevrank method signature is appropriate and consistent

Adding const std::shared_ptr<DB>& db to the ZRevrank method ensures consistency across the class methods.


172-173: Update to ZRangebylex method signature is appropriate and consistent

Including const std::shared_ptr<DB>& db aligns the ZRangebylex method with other methods requiring database references.


177-178: Addition of ZPopMin method is appropriate and aligns with class functionality

The new method ZPopMin is correctly added, enhancing the sorted set operations.


179-180: Addition of ZPopMax method is appropriate and aligns with class functionality

The new method ZPopMax complements the sorted set capabilities.


152-173: Verify all usages of updated methods have been updated accordingly

The methods ZIncrbyIfKeyExist, ZRange, ZRevrange, ZRevrangebylex, ZRank, and ZRangebylex have updated signatures with additional parameters. Please ensure that all calls to these methods in the codebase have been updated to match the new signatures.

Run the following script to find all usages of these methods:

Comment on lines +1541 to +1546
void ZPopminCmd::DoUpdateCache() {
std::vector<storage::ScoreMember> score_members;
if (s_.ok() || s_.IsNotFound()) {
db_->cache()->ZPopMin(key_, count_, &score_members, db_);
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding error handling, validating count_, and reusing code.

The implementation looks good overall, but there are several points to consider:

  1. The method doesn't handle the case where s_ is not ok and not "NotFound". This might lead to unexpected behavior if there's an error.

  2. The count_ variable is used without checking its value. If it's negative or zero, it might lead to unexpected behavior.

  3. This method is very similar to ZPopmaxCmd::DoUpdateCache, suggesting a potential for code reuse.

Consider the following improvements:

  1. Add error handling and validate count_:
 void ZPopminCmd::DoUpdateCache() {
   std::vector<storage::ScoreMember> score_members;
-  if (s_.ok() || s_.IsNotFound()) {
+  if (s_.ok()) {
+    if (count_ > 0) {
       db_->cache()->ZPopMin(key_, count_, &score_members, db_);
+    }
+  } else if (!s_.IsNotFound()) {
+    // Log error or handle it appropriately
   }
 }
  1. To reduce code duplication, consider creating a template method in a base class that both ZPopmaxCmd and ZPopminCmd can inherit from. This would allow you to reuse the same code for both ZPopMax and ZPopMin operations.

Committable suggestion was skipped due to low confidence.

Comment on lines +603 to +607
kCmdNameZPopmax, -2, kCmdFlagsWrite | kCmdFlagsZset | kCmdFlagsFast | kCmdFlagsDoThroughDB | kCmdFlagsUpdateCache);
cmd_table->insert(std::pair<std::string, std::unique_ptr<Cmd>>(kCmdNameZPopmax, std::move(zpopmaxptr)));
////ZPopmin
std::unique_ptr<Cmd> zpopminptr = std::make_unique<ZPopminCmd>(
kCmdNameZPopmin, -2, kCmdFlagsWrite | kCmdFlagsZset | kCmdFlagsFast);
kCmdNameZPopmin, -2, kCmdFlagsWrite | kCmdFlagsZset | kCmdFlagsFast | kCmdFlagsDoThroughDB | kCmdFlagsUpdateCache);
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Inconsistency Found in Zset Commands Flag Usage

While ZPopmaxCmd and ZPopminCmd have been updated with the kCmdFlagsDoThroughDB and kCmdFlagsUpdateCache flags, several other Zset commands are missing these flags. This inconsistency could lead to unexpected behavior or performance issues.

Affected Files:

  • include/pika_zset.h:
    • ZAddCmd
    • ZCardCmd
    • ZIncrbyCmd
    • ZRangeCmd
    • ZRevrangeCmd
    • ZCountCmd
    • ZRemCmd
    • ZUnionstoreCmd
    • ZInterstoreCmd
    • ZRankCmd
    • ZRevrankCmd
    • ZScoreCmd
    • ZRangebylexCmd
    • ZLexcountCmd
    • ZRemrangebyrankCmd
    • ZRemrangebyscoreCmd
    • ZRemrangebylexCmd
    • ZScanCmd
    • ZRangebyscoreCmd
    • ZRevrangebyscoreCmd

Please update these commands to include the kCmdFlagsDoThroughDB and kCmdFlagsUpdateCache flags to ensure consistent behavior across all Zset operations.

🔗 Analysis chain

Summary: Effective implementation of cache functionality for zpopmax and zpopmin

The changes to both ZPopmaxCmd and ZPopminCmd constructors successfully implement cache interaction for these commands. By adding the kCmdFlagsDoThroughDB and kCmdFlagsUpdateCache flags, the modifications ensure that:

  1. Both commands will interact directly with the database, maintaining data consistency.
  2. The cache will be updated after database operations, keeping it in sync.

These changes are consistent across both commands and align well with the PR objective. The implementation should improve performance while maintaining data integrity for sorted set operations.

Consider adding unit tests to verify the new cache interaction behavior for both commands.

To ensure the changes are properly integrated, run the following verification script:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash

# Check if the new flags are used consistently across the codebase
echo "Checking usage of new flags:"
rg "kCmdFlagsDoThroughDB|kCmdFlagsUpdateCache" --type cpp

# Verify if there are any other Zset commands that might need similar updates
echo "Checking other Zset commands:"
rg "std::make_unique<Z\w+Cmd>" --type cpp

Length of output: 19379

include/pika_cache.h Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (14)
src/cache/src/zset.cc (1)

408-475: Overall implementation review for ZPopMin and ZPopMax.

The implementation of ZPopMin and ZPopMax achieves the basic functionality of popping minimum and maximum elements from sorted sets. However, there are several areas for improvement:

  1. Efficiency: Both methods retrieve all items from the sorted set, which can be inefficient for large sets. Consider using range-limited retrieval.
  2. Error handling: The return value of RcZRem is not checked in both methods, which could lead to undetected errors.
  3. Memory management: In ZPopMin, memory allocation for members_obj can be optimized.
  4. Loop and indexing issues: In ZPopMax, there's a potential infinite loop and incorrect indexing when populating members_obj.

Addressing these issues will improve the robustness and efficiency of the implementation.

Consider creating a helper function to handle the common logic between ZPopMin and ZPopMax, parameterizing the differences (e.g., range retrieval function, indexing). This would reduce code duplication and make maintenance easier.

src/pika_zset.cc (2)

1514-1519: Implementation looks good, with a minor optimization possibility

The DoUpdateCache method correctly updates the cache when the status is ok or NotFound. It's good that it checks for both conditions.

One minor suggestion:
If the score_members vector is not used after the ZPopMax call, you could consider passing a nullptr instead to avoid unnecessary memory allocation:

- std::vector<storage::ScoreMember> score_members;
  if (s_.ok() || s_.IsNotFound()) {
-   db_->cache()->ZPopMax(key_, count_, &score_members, db_);
+   db_->cache()->ZPopMax(key_, count_, nullptr, db_);
  }

This change would be more efficient if the popped elements are not needed for any further operations in the cache update.


1541-1546: Implementation looks good, with a minor optimization possibility

The DoUpdateCache method correctly updates the cache when the status is ok or NotFound, which is consistent with the ZPopmaxCmd implementation.

As with the ZPopmaxCmd, if the score_members vector is not used after the ZPopMin call, consider passing a nullptr instead to avoid unnecessary memory allocation:

- std::vector<storage::ScoreMember> score_members;
  if (s_.ok() || s_.IsNotFound()) {
-   db_->cache()->ZPopMin(key_, count_, &score_members, db_);
+   db_->cache()->ZPopMin(key_, count_, nullptr, db_);
  }

This change would be more efficient if the popped elements are not needed for any further operations in the cache update.

src/pika_cache.cc (2)

1468-1481: Implementation looks good, but consider improving error handling and cache warming.

The ZPopMin function is correctly implemented with proper thread safety and key existence check. However, there are a couple of areas that could be improved:

  1. Error handling: The function doesn't handle the case where the key exists but the ZPopMin operation on the cache object fails. Consider adding error handling for this scenario.

  2. Cache warming: When the key is not found in the cache, this could be an opportunity to load it from the database and warm up the cache. Consider implementing a cache warming strategy in this case.

Here's a suggested improvement:

Status PikaCache::ZPopMin(std::string &key, int64_t count, std::vector<storage::ScoreMember> *score_members,
                          const std::shared_ptr<DB> &db) {
  int cache_index = CacheIndex(key);
  std::lock_guard lm(*cache_mutexs_[cache_index]);

  auto cache_obj = caches_[cache_index];
  Status s;

  if (cache_obj->Exists(key)) {
-   return cache_obj->ZPopMin(key, count, score_members);
+   s = cache_obj->ZPopMin(key, count, score_members);
+   if (!s.ok()) {
+     // Handle the error case
+     // For example, log the error or take appropriate action
+   }
+   return s;
  } else {
+   // Consider implementing cache warming here
+   // For example:
+   // s = LoadZSetFromDB(key, db);
+   // if (s.ok()) {
+   //   return cache_obj->ZPopMin(key, count, score_members);
+   // }
    return Status::NotFound("key not in cache");
  }
}

1483-1496: Implementation is consistent with ZPopMin, consider applying the same improvements.

The ZPopMax function is implemented consistently with ZPopMin, which is good for code maintainability. However, it shares the same areas for improvement:

  1. Error handling: Add handling for the case where the key exists but the ZPopMax operation fails.
  2. Cache warming: Consider implementing a cache warming strategy when the key is not found in the cache.

Apply the same improvements suggested for ZPopMin:

Status PikaCache::ZPopMax(std::string &key, int64_t count, std::vector<storage::ScoreMember> *score_members,
                          const std::shared_ptr<DB> &db) {
  int cache_index = CacheIndex(key);
  std::lock_guard lm(*cache_mutexs_[cache_index]);

  auto cache_obj = caches_[cache_index];
  Status s;

  if (cache_obj->Exists(key)) {
-   return cache_obj->ZPopMax(key, count, score_members);
+   s = cache_obj->ZPopMax(key, count, score_members);
+   if (!s.ok()) {
+     // Handle the error case
+     // For example, log the error or take appropriate action
+   }
+   return s;
  } else {
+   // Consider implementing cache warming here
+   // For example:
+   // s = LoadZSetFromDB(key, db);
+   // if (s.ok()) {
+   //   return cache_obj->ZPopMax(key, count, score_members);
+   // }
    return Status::NotFound("key not in cache");
  }
}

Additionally, consider extracting the common logic of ZPopMin and ZPopMax into a private helper function to reduce code duplication.

tests/integration/zset_test.go (1)

1095-1125: Excellent addition of the "should Zpopmin test" case.

This test case effectively covers both ZPopMax and ZPopMin operations, aligning well with the PR objectives. It follows the existing test patterns and provides good coverage of the functionality.

A minor suggestion for improvement:

Consider adding an assertion to check the length of the remaining set after the ZPopMax and ZPopMin operations. This would provide an additional verification that the set size has decreased as expected. You can add this assertion just before the final ZRange check:

// Add this before the ZRange check
setSize, err := client.ZCard(ctx, "zpopzset1").Result()
Expect(err).NotTo(HaveOccurred())
Expect(setSize).To(Equal(int64(1)))

This addition would further strengthen the test by ensuring that the set size is correct after the pop operations.

include/pika_cache.h (8)

152-153: Consider passing 'key' and 'member' as const references

To improve efficiency and prevent unintended modifications, consider changing the parameters key and member to const std::string&.

Apply this diff:

-rocksdb::Status ZIncrbyIfKeyExist(std::string& key, std::string& member, double increment, ZIncrbyCmd* cmd,
+rocksdb::Status ZIncrbyIfKeyExist(const std::string& key, const std::string& member, double increment, ZIncrbyCmd* cmd,
                                        const std::shared_ptr<DB>& db);

154-155: Consider passing 'key' as a const reference

For consistency and efficiency, consider changing the parameter key to const std::string&.

Apply this diff:

-rocksdb::Status ZRange(std::string& key, int64_t start, int64_t stop,
+rocksdb::Status ZRange(const std::string& key, int64_t start, int64_t stop,
                             std::vector<storage::ScoreMember>* score_members, const std::shared_ptr<DB>& db);

163-164: Consider passing 'key' as a const reference

To improve const correctness and prevent unintended side effects, consider changing the parameter key to const std::string&.

Apply this diff:

-rocksdb::Status ZRevrange(std::string& key, int64_t start, int64_t stop,
+rocksdb::Status ZRevrange(const std::string& key, int64_t start, int64_t stop,
                                std::vector<storage::ScoreMember>* score_members, const std::shared_ptr<DB>& db);

168-169: Consider passing string parameters as const references

For improved efficiency and to prevent unintended modifications, consider changing the parameters key, min, and max to const std::string&.

Apply this diff:

-rocksdb::Status ZRevrangebylex(std::string& key, std::string& min, std::string& max,
+rocksdb::Status ZRevrangebylex(const std::string& key, const std::string& min, const std::string& max,
                                     std::vector<std::string>* members, const std::shared_ptr<DB>& db);

170-170: Consider passing 'key' and 'member' as const references

To enhance const correctness and ensure the parameters are not modified, consider changing key and member to const std::string&.

Apply this diff:

-rocksdb::Status ZRevrank(std::string& key, std::string& member, int64_t* rank, const std::shared_ptr<DB>& db);
+rocksdb::Status ZRevrank(const std::string& key, const std::string& member, int64_t* rank, const std::shared_ptr<DB>& db);

172-173: Consider passing string parameters as const references

For consistency and to prevent unintended changes, consider changing the parameters key, min, and max to const std::string&.

Apply this diff:

-rocksdb::Status ZRangebylex(std::string& key, std::string& min, std::string& max, std::vector<std::string>* members,
+rocksdb::Status ZRangebylex(const std::string& key, const std::string& min, const std::string& max, std::vector<std::string>* members,
                                  const std::shared_ptr<DB>& db);

177-178: Consider passing 'key' as a const reference

To improve efficiency and maintain const correctness, consider changing the parameter key to const std::string&.

Apply this diff:

-rocksdb::Status ZPopMin(std::string& key, int64_t count, std::vector<storage::ScoreMember>* score_members,
+rocksdb::Status ZPopMin(const std::string& key, int64_t count, std::vector<storage::ScoreMember>* score_members,
                              const std::shared_ptr<DB>& db);

179-180: Consider passing 'key' as a const reference

For consistency and to prevent unintended modifications, consider changing the parameter key to const std::string&.

Apply this diff:

-rocksdb::Status ZPopMax(std::string& key, int64_t count, std::vector<storage::ScoreMember>* score_members,
+rocksdb::Status ZPopMax(const std::string& key, int64_t count, std::vector<storage::ScoreMember>* score_members,
                              const std::shared_ptr<DB>& db);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 06aca57 and 7c6c24c.

📒 Files selected for processing (5)
  • include/pika_cache.h (1 hunks)
  • src/cache/src/zset.cc (1 hunks)
  • src/pika_cache.cc (1 hunks)
  • src/pika_zset.cc (2 hunks)
  • tests/integration/zset_test.go (1 hunks)
🧰 Additional context used
🔇 Additional comments (3)
src/pika_zset.cc (2)

1510-1512: Implementation looks good

The DoThroughDB method correctly calls the Do() method, which is consistent with the pattern used in other similar commands in this file.


1537-1539: Implementation looks good

The DoThroughDB method correctly calls the Do() method, which is consistent with the implementation in ZPopmaxCmd and other similar commands in this file.

tests/integration/zset_test.go (1)

Line range hint 1-1126: Overall, the changes in this file are well-implemented and valuable.

The addition of the "should Zpopmin test" case enhances the test coverage for the zpopmin and zpopmax commands, which directly addresses the PR objectives. The test is well-structured and follows the existing patterns in the file.

The changes in this file are approved, with a minor suggestion for improvement in the new test case.

src/cache/src/zset.cc Show resolved Hide resolved
Comment on lines +430 to +433
robj **members_obj = (robj **)zcallocate(sizeof(robj *) * items_size);
for (unsigned long i = 0; i < items_size; ++i) {
members_obj[i] = createObject(OBJ_STRING, sdsnewlen(items[i].member, sdslen(items[i].member)));
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize memory allocation for members_obj.

members_obj is allocated with items_size elements, but only to_return elements are used.

Allocate only the necessary memory:

-robj **members_obj = (robj **)zcallocate(sizeof(robj *) * items_size);
-for (unsigned long i = 0; i < items_size; ++i) {
+robj **members_obj = (robj **)zcallocate(sizeof(robj *) * to_return);
+for (unsigned long i = 0; i < to_return; ++i) {
   members_obj[i] = createObject(OBJ_STRING, sdsnewlen(items[i].member, sdslen(items[i].member)));
 }

This change reduces memory usage and improves efficiency.

Committable suggestion was skipped due to low confidence.

src/cache/src/zset.cc Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
src/cache/src/zset.cc Show resolved Hide resolved
@Mixficsol Mixficsol assigned Mixficsol and chejinge and unassigned Mixficsol Oct 11, 2024
@Mixficsol Mixficsol self-requested a review October 11, 2024 12:26
@chejinge chejinge closed this Oct 17, 2024
@chejinge chejinge deleted the popfix branch October 17, 2024 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✏️ Feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants