OpenAtomFoundation / pikiwidb

a high-performance, large-capacity, multi-tenant, data-persistent, strong data consistency based on raft, Redis-compatible elastic KV data storage system based on RocksDB
BSD 3-Clause "New" or "Revised" License
198 stars 63 forks source link

fix: handle uninitialized and non-leader states in Raft cluster mode #316

Closed chanfun-ren closed 3 months ago

chanfun-ren commented 4 months ago

307

read/write commands are now dropped if raft has not been initialized in raft mode, and an error message 'NOCLUSTER No Raft Cluster' is returned to the client. This change prevents the system from crashing due to failed assertions.

Summary by CodeRabbit

longfar-ncy commented 4 months ago

https://github.com/OpenAtomFoundation/pikiwidb/pull/302 帮忙把这个内容加进这个pr

chanfun-ren commented 4 months ago

302 帮忙把这个内容加进这个pr

已加。

对于处于 raft 集群模式下的请求:

  1. 如果 PRAFT 还没有初始化,对于读写命令,返回客户端一个初始化未完成的提示信息。#307
  2. 如果 PRAFT 初始化完成了,对于写命令,如果自身不是 leader,返回一个重定向的信息。 #302
Issues-translate-bot commented 4 months ago

Bot detected the issue body's language is not English, translate it automatically.


302 Help add this content to this PR

added.

For requests in raft cluster mode:

  1. If PRAFT has not been initialized, for read and write commands, a prompt message indicating that the initialization is not completed is returned to the client. #307
  2. If PRAFT initialization is completed, for the write command, if it is not the leader, a redirection message will be returned. #302
luky116 commented 4 months ago

@开颜 @changyuan

Issues-translate-bot commented 4 months ago

Bot detected the issue body's language is not English, translate it automatically.


@kaiyan @changyuan

AlexStocks commented 4 months ago

@CodiumAI-Agent /improve

CodiumAI-Agent commented 4 months ago

PR Code Suggestions ✨

CategorySuggestion                                                                                                                                    Score
Possible bug
Add a null check for PRAFT to prevent potential null pointer dereferences ___ **Consider checking if PRAFT is not null before calling its methods to avoid potential null
pointer dereferences.** [src/base_cmd.cc [39-41]](https://github.com/OpenAtomFoundation/pikiwidb/pull/316/files#diff-23c5847b03356e8dd665fe88eaea18e5a2ba197586895ecc56426ea9186f7fafR39-R41) ```diff -if (!PRAFT.IsInitialized() && (HasFlag(kCmdFlagsReadonly) || HasFlag(kCmdFlagsWrite))) { +if (PRAFT && !PRAFT.IsInitialized() && (HasFlag(kCmdFlagsReadonly) || HasFlag(kCmdFlagsWrite))) { DEBUG("drop command: {}", client->CmdName()); return client->SetRes(CmdRes::kErrOther, "PRAFT is not initialized"); } ```
Suggestion importance[1-10]: 9 Why: Adding a null check for `PRAFT` is a crucial improvement to prevent potential null pointer dereferences, which could lead to runtime crashes.
9
Enhancement
Use more descriptive error codes for specific failure scenarios ___ **Consider using a more specific error code than kErrOther for uninitialized PRAFT and
non-leader scenarios to improve error handling and client debugging.** [src/base_cmd.cc [41-46]](https://github.com/OpenAtomFoundation/pikiwidb/pull/316/files#diff-23c5847b03356e8dd665fe88eaea18e5a2ba197586895ecc56426ea9186f7fafR41-R46) ```diff -return client->SetRes(CmdRes::kErrOther, "PRAFT is not initialized"); -return client->SetRes(CmdRes::kErrOther, fmt::format("MOVED {}", PRAFT.GetLeaderAddress())); +return client->SetRes(CmdRes::kErrPraftUninitialized, "PRAFT is not initialized"); +return client->SetRes(CmdRes::kErrNotLeader, fmt::format("MOVED {}", PRAFT.GetLeaderAddress())); ```
Suggestion importance[1-10]: 8 Why: Using more descriptive error codes enhances error handling and client debugging, making it easier to diagnose specific issues.
8
Performance
Optimize the atomic load operation with relaxed memory ordering for potential performance improvement ___ **Use std::atomic::load(std::memory_order_relaxed) for potentially better performance when
the ordering of use_raft is not critical.** [src/base_cmd.cc [37]](https://github.com/OpenAtomFoundation/pikiwidb/pull/316/files#diff-23c5847b03356e8dd665fe88eaea18e5a2ba197586895ecc56426ea9186f7fafR37-R37) ```diff -if (g_config.use_raft.load()) { +if (g_config.use_raft.load(std::memory_order_relaxed)) { ```
Suggestion importance[1-10]: 7 Why: This suggestion is correct and can improve performance, but the impact is minor as it only optimizes a single atomic load operation.
7
Maintainability
Refactor complex condition checks into a separate method to enhance readability and maintainability ___ **Refactor the condition checks into a separate method to improve code readability and
maintainability.** [src/base_cmd.cc [39-46]](https://github.com/OpenAtomFoundation/pikiwidb/pull/316/files#diff-23c5847b03356e8dd665fe88eaea18e5a2ba197586895ecc56426ea9186f7fafR39-R46) ```diff -if (!PRAFT.IsInitialized() && (HasFlag(kCmdFlagsReadonly) || HasFlag(kCmdFlagsWrite))) { - DEBUG("drop command: {}", client->CmdName()); - return client->SetRes(CmdRes::kErrOther, "PRAFT is not initialized"); +if (checkPraftState(client)) { + return; } -if (!PRAFT.IsLeader() && HasFlag(kCmdFlagsWrite)) { - return client->SetRes(CmdRes::kErrOther, fmt::format("MOVED {}", PRAFT.GetLeaderAddress())); -} +// Define checkPraftState elsewhere in the class ```
Suggestion importance[1-10]: 6 Why: Refactoring condition checks into a separate method improves readability and maintainability, but it is a minor enhancement compared to functional or performance improvements.
6
AlexStocks commented 4 months ago

@CodiumAI-Agent /review

CodiumAI-Agent commented 4 months ago

PR Review 🔍

⏱️ Estimated effort to review [1-5] 3, because the PR involves changes in the core command execution logic and introduces new conditions based on the state of the Raft cluster. Understanding the implications of these changes on the overall system behavior and ensuring they do not introduce new bugs or regressions requires a moderate level of effort.
🧪 Relevant tests Yes
⚡ Possible issues Possible Bug: The new code in `BaseCmd::Execute` does not handle the case where a command is neither read-only nor write, which might lead to unexpected behaviors for such commands.
🔒 Security concerns No
Code feedback:
relevant filesrc/base_cmd.cc
suggestion       Consider adding an else clause to handle commands that do not fall into read-only or write categories. This will ensure that all command types are accounted for and handled appropriately. [important]
relevant linereturn client->SetRes(CmdRes::kErrOther, fmt::format("MOVED {}", PRAFT.GetLeaderAddress()));

coderabbitai[bot] commented 4 months ago

Walkthrough

本次更改主要集中在对命令处理和测试逻辑的增强。包括在执行命令前检查PRAFT初始化和领导状态的逻辑修改,以及更新命令构造函数的参数以调整其行为。此外,还增强了数据库刷新测试中的错误检查逻辑。

Changes

文件路径 更改摘要
src/base_cmd.cc 增加PRAFT初始化和领导状态检查逻辑。
src/cmd_admin.ccsrc/cmd_kv.cc 修改命令构造函数的参数,调整其行为和ACL类别。
tests/consistency_test.go 增强数据库刷新测试中的错误检查逻辑。

Poem

代码变更如微风, 优雅修复,步步成。 测试更严代码精, PRAFT助力稳如松。 未来之路皆光明, 齐心协力,共锦绣。


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 - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)
Tips ### Chat There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai): - Review comments: Directly reply to a review comment made by CodeRabbit. Example: - `I pushed a fix in commit .` - `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 generate interesting stats about this repository and render them as a table.` - `@coderabbitai show all the console.log statements in this repository.` - `@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 as 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. Additionally, you can add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed. ### CodeRabbit Configration 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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://coderabbit.ai/docs) for detailed information on how to use CodeRabbit. - Join our [Discord Community](https://discord.com/invite/GsXnASn26c) to get help, request features, and share feedback. - Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.