Skip to content

feat: Add storage interface - #14

Merged
sitaowang1998 merged 6 commits into
y-scope:mainfrom
sitaowang1998:storage_interface
Oct 31, 2024
Merged

feat: Add storage interface#14
sitaowang1998 merged 6 commits into
y-scope:mainfrom
sitaowang1998:storage_interface

Conversation

@sitaowang1998

@sitaowang1998 sitaowang1998 commented Oct 30, 2024

Copy link
Copy Markdown
Collaborator

Description

Add interface for metadata and data storage.

Validation performed

  • task:lint-check

Summary by CodeRabbit

  • New Features

    • Added support for the Boost library installation via a new script.
    • Introduced abseil-cpp as a submodule for enhanced functionality.
    • New classes and methods for managing tasks and data storage, improving task processing capabilities.
    • Enhanced library management in the build configuration.
  • Bug Fixes

    • Updated error handling and messaging for library dependencies in the build configuration.
  • Documentation

    • New scripts for automating library installations, including Boost.
  • Chores

    • Added entries to .gitignore to streamline project management.
    • Updated installation scripts to include Boost library installation.

Added interface for metadata and storage interface. Added simple Task
and Data class for interface to work. Add boost header for uuid and
abseil for flat_hash_map.
@coderabbitai

coderabbitai Bot commented Oct 30, 2024

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request introduces several changes across multiple files, including the addition of a new entry to the .gitignore file to exclude the cmake-build-debug directory, and the addition of a new submodule for the abseil-cpp library in the .gitmodules file. Modifications to the CMakeLists.txt files enhance library management, including the integration of Boost and adjustments for static library checks. New header files are introduced for Data, Error, Task, and TaskGraph classes, along with modifications to existing storage classes and the addition of MySQL storage implementations.

Changes

File Path Change Summary
.gitignore Added entry: cmake-build-debug
.gitmodules Added submodule: abseil-cpp with path submodules/abseil-cpp and URL https://github.com/abseil/abseil-cpp.git
CMakeLists.txt Added Boost library setup, adjusted spdlog and MariaDBClient configurations, included abseil-cpp as a subdirectory.
src/spider/CMakeLists.txt Updated SPIDER_CORE_SOURCES to include additional source files; added target_link_libraries for spider_worker.
src/spider/core/Data.hpp Added class Data with members for ID, key, and value; includes constructors and getter methods.
src/spider/core/Error.hpp Added enum StorageErrType and struct StorageErr for error handling.
src/spider/core/Task.hpp Introduced classes TaskInput, TaskOutput, Task, and enumerations for task management.
src/spider/core/TaskGraph.hpp Added class TaskGraph for managing tasks and their dependencies with various public methods.
src/spider/storage/DataStorage.hpp Added abstract class DataStorage with pure virtual methods for data operations.
src/spider/storage/MetadataStorage.hpp Defined class MetadataStorage with methods for task graph management and error handling.
src/spider/storage/MysqlStorage.cpp Implemented MySqlMetadataStorage and MySqlDataStorage classes with methods for database operations.
src/spider/storage/MysqlStorage.hpp Defined MySqlMetadataStorage and MySqlDataStorage classes with methods for managing task graphs and data.
submodules/abseil-cpp Added subproject commit: 07fff76ed619672bb7bf00939231ba45aef2b043.
tools/scripts/lib_install/boost.sh New script to automate installation of the Boost library from source.
tools/scripts/linux/install-lib.sh Added command to invoke boost.sh for installing Boost version 1.86.0.

Possibly related PRs


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 34

🧹 Outside diff range and nitpick comments (20)
.gitmodules (1)

7-9: Consider documenting the dependency's purpose.

Since abseil-cpp is a comprehensive utility library, it would be helpful to document which specific components are being utilized for the storage interface implementation.

Consider adding a comment in the README.md or documentation to explain:

  • Why abseil-cpp was chosen
  • Which specific components are being used
  • Any version/compatibility requirements

Would you like me to help draft this documentation?

tools/scripts/linux/install-lib.sh (1)

Line range hint 1-15: Consider enhancing script robustness

The script could benefit from these improvements:

  1. Add version validation
  2. Include installation verification
  3. Use more robust path handling

Here's a suggested improvement:

 #!/usr/bin/env bash
 
 # Exit on any error
 set -e
 
 # Error on undefined variable
 set -u
 
-script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+# More robust path handling
+script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd -P )"
 lib_install_scripts_dir=$script_dir/..
 
+# Function to verify installation
+verify_installation() {
+    local lib_name="$1"
+    echo "Verifying $lib_name installation..."
+}
+
 "$lib_install_scripts_dir"/lib_install/fmtlib.sh 11.0.2
+verify_installation "fmtlib"
 "$lib_install_scripts_dir"/lib_install/spdlog.sh 1.14.1
+verify_installation "spdlog"
 "$lib_install_scripts_dir"/lib_install/mariadb-connector-c.sh 3.4.1
+verify_installation "mariadb-connector-c"
 "$lib_install_scripts_dir"/lib_install/boost.sh 1.86.0
+verify_installation "boost"
src/spider/core/Error.hpp (1)

1-29: Consider adopting a more structured error handling pattern.

The current error handling approach is simple and functional, but consider these architectural improvements:

  1. Consider implementing std::error_code support for better integration with standard C++ error handling
  2. Add static factory methods for common errors to ensure consistent error messages
  3. Consider adding error categories (similar to std::error_category) for different storage backends

Example of how this could evolve:

#include <system_error>

namespace spider::core {
    enum class StorageErrType : std::uint8_t { ... };
    
    class StorageErrorCategory : public std::error_category {
        const char* name() const noexcept override;
        std::string message(int ev) const override;
    };
    
    std::error_code make_error_code(StorageErrType e);
}  // namespace spider::core

// Enable automatic conversion
namespace std {
    template<>
    struct is_error_code_enum<spider::core::StorageErrType> : true_type {};
}
src/spider/CMakeLists.txt (1)

2-13: Consider improving comment style for consistency

The comment "spider core source files" could be more descriptive and follow a consistent style. Consider using a more detailed description that explains the purpose of these core files.

-    "spider core source files"
+    "Core source files for Spider's storage interface and task management system"
src/spider/core/Data.hpp (1)

1-9: Add class documentation for thread safety guarantees

Consider adding class-level documentation to explicitly state thread safety guarantees, as this class might be used in concurrent storage operations.

Add before the class declaration:

+/**
+ * Class representing a data entity with optional key and UUID.
+ * Thread safety: This class is immutable after construction and is thread-safe for concurrent reads.
+ */
 class Data {
tools/scripts/lib_install/boost.sh (1)

46-46: Add newline at end of file

Add a newline at the end of the file to comply with POSIX standards.

src/spider/storage/MetadataStorage.hpp (3)

13-20: Consider adding an explicit default constructor.

While the Rule of Five is properly implemented, consider adding:

MetadataStorage() = default;

This makes the interface more complete and explicit about its construction behaviour.


24-29: Add documentation for task graph operations.

Consider adding Doxygen-style documentation for these methods, especially for:

  • Success/failure conditions
  • Ownership semantics of TaskGraph objects
  • Concurrent access behaviour

40-41: Consider adding heartbeat configuration parameters.

The heartbeat mechanism might benefit from configurable timeouts and intervals. Consider adding methods to configure these parameters or accepting them through a configuration object.

CMakeLists.txt (1)

120-128: Important licensing consideration for MariaDBClient

The warning about GPL licensing restrictions for static linking is crucial. Consider documenting this limitation in the project's README or documentation to ensure future maintainers are aware of this constraint.

src/spider/storage/MysqlStorage.cpp (1)

1-131: Consider production readiness improvements.

Several important aspects should be addressed before production deployment:

  1. Add comprehensive error handling and logging
  2. Implement connection pooling for better scalability
  3. Add monitoring capabilities (e.g., query performance, connection status)
  4. Consider implementing retry mechanisms for transient failures

Would you like assistance in implementing any of these improvements?

🧰 Tools
🪛 cppcheck

[performance] 19-19: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)


[performance] 24-24: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)


[performance] 101-101: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)


[performance] 27-27: Function parameter 'value' should be passed by const reference.

(passedByValue)


[performance] 53-53: Function parameter 'value' should be passed by const reference.

(passedByValue)

src/spider/core/TaskGraph.hpp (6)

23-27: Use const references in range-based for loops to avoid unnecessary copies

In the loop over parents, iterating by const reference avoids unnecessary copies of boost::uuids::uuid objects.

Apply this diff to improve efficiency:

-for (boost::uuids::uuid const parent_id : parents) {
+for (boost::uuids::uuid const& parent_id : parents) {
    if (!m_tasks.contains(parent_id)) {
        return false;
    }
}

33-35: Use const references in range-based for loops to avoid unnecessary copies

Similarly, updating this loop enhances performance by preventing unnecessary copies.

Apply this diff:

-for (boost::uuids::uuid const parent_id : parents) {
+for (boost::uuids::uuid const& parent_id : parents) {
    m_dependencies.emplace_back(parent_id, task_id);
}

49-53: Iterate over dependencies by const reference to improve efficiency

Using const references in the loop over m_dependencies prevents copying of the pairs, enhancing performance.

Apply this diff:

-for (std::pair<boost::uuids::uuid, boost::uuids::uuid> const dep : m_dependencies) {
+for (std::pair<boost::uuids::uuid, boost::uuids::uuid> const& dep : m_dependencies) {
    if (dep.first == id) {
        children.emplace_back(dep.second);
    }
}

60-64: Iterate over dependencies by const reference to improve efficiency

As with the previous loop, using const references here enhances performance.

Apply this diff:

-for (std::pair<boost::uuids::uuid, boost::uuids::uuid> const dep : m_dependencies) {
+for (std::pair<boost::uuids::uuid, boost::uuids::uuid> const& dep : m_dependencies) {
    if (dep.second == id) {
        parents.emplace_back(dep.first);
    }
}

40-43: Optimize task retrieval by using find instead of contains and at

To avoid redundant hash map lookups, consider using find to retrieve the task directly.

Apply this diff:

-if (m_tasks.contains(id)) {
-    return m_tasks.at(id);
-}
-return std::nullopt;
+auto it = m_tasks.find(id);
+if (it != m_tasks.end()) {
+    return it->second;
+}
+return std::nullopt;

18-18: Introduce a type alias for dependency pairs to enhance readability

Defining a type alias for task dependencies improves code readability and maintainability.

Apply this change:

+#include <utility>
+
+using TaskDependency = std::pair<boost::uuids::uuid, boost::uuids::uuid>;
 
-class TaskGraph {
-private:
-    absl::flat_hash_map<boost::uuids::uuid, Task> m_tasks;
-    std::vector<std::pair<boost::uuids::uuid, boost::uuids::uuid>> m_dependencies;
+class TaskGraph {
+private:
+    absl::flat_hash_map<boost::uuids::uuid, Task> m_tasks;
+    std::vector<TaskDependency> m_dependencies;

Remember to update other occurrences of std::pair<boost::uuids::uuid, boost::uuids::uuid> accordingly.

src/spider/storage/MysqlStorage.hpp (2)

55-58: Ensure consistent method declaration formatting

The formatting of method declarations in lines 55-62 is inconsistent with the rest of the code, which may affect readability. Consider adjusting the formatting to keep method declarations on a single line where possible.

Apply this diff to improve consistency:

-auto
-add_task_reference(boost::uuids::uuid id, boost::uuids::uuid task_id) -> StorageErr override;
+auto add_task_reference(boost::uuids::uuid id, boost::uuids::uuid task_id) -> StorageErr override;

-auto
-remove_task_reference(boost::uuids::uuid id, boost::uuids::uuid task_id) -> StorageErr override;
+auto remove_task_reference(boost::uuids::uuid id, boost::uuids::uuid task_id) -> StorageErr override;

-auto add_driver_reference(boost::uuids::uuid id, boost::uuids::uuid driver_id)
-        -> StorageErr override;
+auto add_driver_reference(boost::uuids::uuid id, boost::uuids::uuid driver_id) -> StorageErr override;

-auto remove_driver_reference(boost::uuids::uuid id, boost::uuids::uuid driver_id)
-        -> StorageErr override;
+auto remove_driver_reference(boost::uuids::uuid id, boost::uuids::uuid driver_id) -> StorageErr override;

Also applies to: 59-62


16-63: Add documentation comments to public methods

Consider adding documentation comments to the public methods of MySqlMetadataStorage and MySqlDataStorage classes to enhance code readability and maintainability.

src/spider/core/Task.hpp (1)

75-75: Correct the enumeration value to 'Succeeded' for grammatical accuracy

In the TaskState enum, the state Succeed should be changed to Succeeded to maintain consistent past tense with other states like Failed.

Apply this diff:

         Running,
-        Succeed,
+        Succeeded,
         Failed,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 43ce24f and 29a2428.

📒 Files selected for processing (15)
  • .gitignore (1 hunks)
  • .gitmodules (1 hunks)
  • CMakeLists.txt (2 hunks)
  • src/spider/CMakeLists.txt (2 hunks)
  • src/spider/core/Data.hpp (1 hunks)
  • src/spider/core/Error.hpp (1 hunks)
  • src/spider/core/Task.hpp (1 hunks)
  • src/spider/core/TaskGraph.hpp (1 hunks)
  • src/spider/storage/DataStorage.hpp (1 hunks)
  • src/spider/storage/MetadataStorage.hpp (1 hunks)
  • src/spider/storage/MysqlStorage.cpp (1 hunks)
  • src/spider/storage/MysqlStorage.hpp (1 hunks)
  • submodules/abseil-cpp (1 hunks)
  • tools/scripts/lib_install/boost.sh (1 hunks)
  • tools/scripts/linux/install-lib.sh (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • .gitignore
  • submodules/abseil-cpp
🧰 Additional context used
🪛 cppcheck
src/spider/storage/MysqlStorage.cpp

[performance] 19-19: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)


[performance] 24-24: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)


[performance] 101-101: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)


[performance] 27-27: Function parameter 'value' should be passed by const reference.

(passedByValue)


[performance] 53-53: Function parameter 'value' should be passed by const reference.

(passedByValue)

🔇 Additional comments (7)
tools/scripts/linux/install-lib.sh (1)

15-15: Verify Boost version compatibility

The script installs Boost 1.86.0, but the CMakeLists.txt requires version 1.74. While newer versions are typically backwards compatible, it would be prudent to document this decision or align the versions.

src/spider/core/Error.hpp (1)

1-7: LGTM! Well-structured header organization.

The include guards follow proper naming conventions, and the included headers are minimal and appropriate for the functionality needed.

src/spider/CMakeLists.txt (1)

30-34: Verify dependency configuration

The new library dependencies look good, but we should verify that these libraries are properly configured in the parent CMakeLists.txt file.

✅ Verification successful

Let me check the configuration of abseil-cpp to ensure it's properly set up.


Dependencies are properly configured

The dependency configuration is correct:

  • Boost is properly configured with minimum version 1.74 and REQUIRED flag
  • abseil-cpp is included as a submodule and added via add_subdirectory with EXCLUDE_FROM_ALL flag
  • Both dependencies are configured in the root CMakeLists.txt file
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for proper dependency configuration in parent CMakeLists.txt files

# Test 1: Check for find_package commands for Boost and abseil
echo "Checking for dependency configuration..."
rg -l "find_package.*Boost" $(fd CMakeLists.txt)
rg -l "add_subdirectory.*abseil-cpp" $(fd CMakeLists.txt)

# Test 2: Check if minimum versions are specified for Boost
rg "find_package.*Boost.*REQUIRED" $(fd CMakeLists.txt)

Length of output: 524


Script:

#!/bin/bash
# Check abseil-cpp configuration details
echo "Checking abseil-cpp configuration..."
rg "add_subdirectory.*abseil-cpp" -A 5 $(fd CMakeLists.txt)

# Check if there are any version constraints for abseil-cpp
echo "Checking abseil-cpp version constraints..."
rg "abseil-cpp.*version|VERSION" $(fd CMakeLists.txt)

# Check if abseil-cpp is fetched or included as a dependency
echo "Checking how abseil-cpp is included..."
rg "FetchContent.*abseil-cpp|include.*abseil-cpp" $(fd CMakeLists.txt)

Length of output: 1216

src/spider/core/Data.hpp (1)

27-31: LGTM! Getter methods are well-designed

The getter methods are appropriately designed, returning by value which is suitable for these types. The consistent use of trailing return type syntax is good for readability.

src/spider/storage/MetadataStorage.hpp (1)

1-11: LGTM! Verify std::vector usage.

The header organization follows best practices with system headers separated from project headers. All includes appear necessary, but let's verify the std::vector usage.

✅ Verification successful

The std::vector inclusion is necessary and properly used

The std::vector is extensively used throughout the codebase:

  • In TaskGraph.hpp for managing dependencies and parent-child relationships
  • In Task.hpp for storing inputs and outputs
  • In MetadataStorage.hpp interface methods for handling collections of tasks and task graphs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify std::vector usage in method signatures
rg -l "std::vector" "src/spider/core/{Task,TaskGraph}.hpp"

Length of output: 135


Script:

#!/bin/bash
# Let's first find the correct paths for Task.hpp and TaskGraph.hpp
fd "Task\.hpp|TaskGraph\.hpp" --type f

# Then check for std::vector usage in these files
rg "std::vector" --type cpp -A 2

Length of output: 5981

CMakeLists.txt (2)

80-89: LGTM: Boost configuration is well-structured

The Boost library configuration follows CMake best practices with proper version checking and error handling. The static/shared library handling aligns with the project's configuration.


131-133: Verify abseil-cpp integration impact

The integration looks correct, but since abseil-cpp is a significant dependency:

Let's verify the integration:

✅ Verification successful

Abseil-cpp integration is properly configured and used

The verification confirms that:

  • The abseil-cpp submodule is properly initialized
  • The library is used appropriately in the codebase:
    • absl::flat_hash_map is used in TaskGraph.hpp for efficient task storage
    • The dependency is correctly linked in src/spider/CMakeLists.txt
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify abseil-cpp submodule and its usage
# Check if the submodule is properly initialized
git submodule status submodules/abseil-cpp

# Look for abseil usage to ensure it's needed
rg -g '!{build,submodules}/*' -l 'absl::'

Length of output: 206


Script:

#!/bin/bash
# Check actual usage of abseil in the codebase
rg -g '!{build,submodules}/*' 'absl::' -A 3

# Check CMake configuration for abseil usage
cat src/spider/CMakeLists.txt

Length of output: 1629

Comment thread .gitmodules
Comment on lines +7 to +9
[submodule "submodules/abseil-cpp"]
path = submodules/abseil-cpp
url = https://github.com/abseil/abseil-cpp.git

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Submodule needs initialization

The submodule directory is empty, indicating that it hasn't been initialized. Please run:

git submodule update --init --recursive
🔗 Analysis chain

LGTM! Verify submodule initialization.

The addition of abseil-cpp as a submodule follows the project's conventions.

Let's verify the submodule initialization:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the abseil-cpp submodule is properly initialized

# Test: Check if the submodule directory exists and is not empty
if [ -d "submodules/abseil-cpp" ] && [ "$(ls -A submodules/abseil-cpp)" ]; then
    echo "Submodule is properly initialized"
else
    echo "Warning: Submodule directory is missing or empty"
fi

# Test: Verify the submodule commit
git submodule status submodules/abseil-cpp

Length of output: 294

Comment thread src/spider/core/Error.hpp
Comment on lines +9 to +16
enum class StorageErrType : std::uint8_t {
ConnectionErr,
DbNotFound,
KeyNotFoundErr,
DuplicateKeyErr,
ConstraintViolationErr,
Success
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider enhancing the error type enumeration.

While the enum class implementation is good for type safety, consider these improvements:

  1. Move Success to be the first value (0) as it's the default/normal case
  2. Add common error types like InvalidArgumentErr
  3. Add documentation for each error type

Here's a suggested improvement:

 enum class StorageErrType : std::uint8_t {
+    // Operation completed successfully
+    Success = 0,
+    // Failed to establish or maintain database connection
     ConnectionErr,
+    // Specified database does not exist
     DbNotFound,
+    // Requested key was not found in storage
     KeyNotFoundErr,
+    // Attempted to insert a key that already exists
     DuplicateKeyErr,
+    // Operation would violate a database constraint
     ConstraintViolationErr,
-    Success
+    // Invalid arguments provided to storage operation
+    InvalidArgumentErr
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
enum class StorageErrType : std::uint8_t {
ConnectionErr,
DbNotFound,
KeyNotFoundErr,
DuplicateKeyErr,
ConstraintViolationErr,
Success
};
enum class StorageErrType : std::uint8_t {
// Operation completed successfully
Success = 0,
// Failed to establish or maintain database connection
ConnectionErr,
// Specified database does not exist
DbNotFound,
// Requested key was not found in storage
KeyNotFoundErr,
// Attempted to insert a key that already exists
DuplicateKeyErr,
// Operation would violate a database constraint
ConstraintViolationErr,
// Invalid arguments provided to storage operation
InvalidArgumentErr
};

Comment thread src/spider/core/Error.hpp
Comment on lines +18 to +25
struct StorageErr {
StorageErrType type;
std::string description;

StorageErr(StorageErrType type, std::string description)
: type(type),
description(std::move(description)) {}
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance the StorageErr structure with additional functionality.

The structure could benefit from additional features to make it more robust and easier to use:

Consider these improvements:

 struct StorageErr {
     StorageErrType type;
     std::string description;
 
+    // Default constructor for Success case
+    StorageErr() : type(StorageErrType::Success), description() {}
+
+    // Main constructor
     StorageErr(StorageErrType type, std::string description)
             : type(type),
               description(std::move(description)) {}
+
+    // Convenience method to check success
+    [[nodiscard]] bool is_success() const {
+        return type == StorageErrType::Success;
+    }
+
+    // Enable comparison
+    bool operator==(const StorageErr& other) const {
+        return type == other.type;
+    }
 };

This adds:

  1. A default constructor for the success case
  2. A convenience method to check success
  3. Comparison operator for easier testing
  4. The [[nodiscard]] attribute to ensure error checking isn't accidentally ignored

Committable suggestion was skipped due to low confidence.

Comment thread src/spider/CMakeLists.txt Outdated
Comment on lines +24 to +29
target_sources(
spider_worker
PRIVATE
${SPIDER_CORE_SOURCES}
${SPIDER_WORKER_SOURCES}
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate target_sources command

This target_sources command is an exact duplicate of the one above. Having duplicate commands doesn't provide any benefit and could lead to maintenance issues.

-target_sources(
-    spider_worker
-    PRIVATE
-        ${SPIDER_CORE_SOURCES}
-        ${SPIDER_WORKER_SOURCES}
-)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
target_sources(
spider_worker
PRIVATE
${SPIDER_CORE_SOURCES}
${SPIDER_WORKER_SOURCES}
)

Comment thread src/spider/core/Data.hpp
Comment on lines +10 to +15
class Data {
private:
boost::uuids::uuid m_id;
std::optional<std::string> m_key;
std::string m_value;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance const correctness and exception specifications

The class design is good with proper encapsulation. Consider enhancing it with const correctness and explicit exception specifications.

-    auto get_id() -> boost::uuids::uuid { return m_id; }
+    auto get_id() const noexcept -> boost::uuids::uuid { return m_id; }

-    auto get_key() -> std::optional<std::string> { return m_key; }
+    auto get_key() const noexcept -> std::optional<std::string> { return m_key; }

-    auto get_value() -> std::string { return m_value; }
+    auto get_value() const noexcept -> std::string { return m_value; }

Committable suggestion was skipped due to low confidence.

Comment thread src/spider/core/Task.hpp
return m_data_id;
}

[[nodiscard]] auto get_type() const -> std::string { return m_type; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Return const reference from getter to avoid unnecessary copying

The get_type() function returns a std::string by value, which may cause unnecessary copying. Consider returning a const std::string& to improve performance.

Apply this diff:

-        [[nodiscard]] auto get_type() const -> std::string { return m_type; }
+        [[nodiscard]] auto get_type() const -> const std::string& { return m_type; }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[[nodiscard]] auto get_type() const -> std::string { return m_type; }
[[nodiscard]] auto get_type() const -> const std::string& { return m_type; }

Comment thread src/spider/core/Task.hpp Outdated
std::string m_type;

public:
TaskOutput(std::string value, std::string type) : m_value(value), m_type(std::move(type)) {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize constructor by moving parameters to avoid unnecessary copying

In the TaskOutput constructor, consider using std::move for value to avoid unnecessary copying.

Apply this diff:

-        TaskOutput(std::string value, std::string type) : m_value(value), m_type(std::move(type)) {}
+        TaskOutput(std::string value, std::string type) : m_value(std::move(value)), m_type(std::move(type)) {}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
TaskOutput(std::string value, std::string type) : m_value(value), m_type(std::move(type)) {}
TaskOutput(std::string value, std::string type) : m_value(std::move(value)), m_type(std::move(type)) {}

Comment thread src/spider/core/Task.hpp Outdated
TaskInput(boost::uuids::uuid output_task_id, std::uint8_t position, std::string type)
: m_task_output({output_task_id, position}),
m_type(std::move(type)) {};
TaskInput(std::string value, std::string type) : m_value(value), m_type(std::move(type)) {};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize constructor by moving parameters to avoid unnecessary copying

In the TaskInput constructor, consider using std::move for value to avoid unnecessary copying.

Apply this diff:

-        TaskInput(std::string value, std::string type) : m_value(value), m_type(std::move(type)) {};
+        TaskInput(std::string value, std::string type) : m_value(std::move(value)), m_type(std::move(type)) {};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
TaskInput(std::string value, std::string type) : m_value(value), m_type(std::move(type)) {};
TaskInput(std::string value, std::string type) : m_value(std::move(value)), m_type(std::move(type)) {};

Comment thread src/spider/core/Task.hpp

[[nodiscard]] auto get_id() const -> boost::uuids::uuid { return m_id; }

[[nodiscard]] auto get_function_name() const -> std::string { return m_function_name; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Return const reference from getter to avoid unnecessary copying

The get_function_name() function returns a std::string by value, which may cause unnecessary copying. Consider returning a const std::string& to improve performance.

Apply this diff:

-        [[nodiscard]] auto get_function_name() const -> std::string { return m_function_name; }
+        [[nodiscard]] auto get_function_name() const -> const std::string& { return m_function_name; }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[[nodiscard]] auto get_function_name() const -> std::string { return m_function_name; }
[[nodiscard]] auto get_function_name() const -> const std::string& { return m_function_name; }

Comment thread src/spider/core/Task.hpp

[[nodiscard]] auto get_num_outputs() const -> size_t { return m_outputs.size(); }

[[nodiscard]] auto get_input(uint64_t index) const -> TaskInput { return m_inputs[index]; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Return const reference from getter to avoid unnecessary copying

The get_input() function returns a TaskInput by value, which may result in unnecessary copying. Consider returning a const TaskInput& instead.

Apply this diff:

-        [[nodiscard]] auto get_input(uint64_t index) const -> TaskInput { return m_inputs[index]; }
+        [[nodiscard]] auto get_input(uint64_t index) const -> const TaskInput& { return m_inputs[index]; }

Similarly for get_output():

-        [[nodiscard]] auto get_output(uint64_t index) const -> TaskOutput { return m_outputs[index]; }
+        [[nodiscard]] auto get_output(uint64_t index) const -> const TaskOutput& { return m_outputs[index]; }

Committable suggestion was skipped due to low confidence.

@sitaowang1998 sitaowang1998 changed the title feature: Add storage interface feat: Add storage interface Oct 30, 2024

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (2)
src/spider/core/Task.hpp (2)

74-86: Add documentation for enum values

Consider adding documentation for each enum value to clarify:

  • The conditions that trigger each TaskState
  • The implications of each state
  • The specific use cases for each TaskCreatorType

Example:

/// Represents the various states a task can be in during its lifecycle
enum class TaskState : std::uint8_t {
    Pending,  ///< Task is created but not yet ready for execution
    Ready,    ///< Task's dependencies are met and it's ready to run
    // ... etc
};

88-131: Add state transition management

The Task class lacks methods to manage state transitions. Consider adding:

  1. A method to update the task state with validation
  2. State transition validation logic
  3. Optional state change callbacks

Example implementation:

void set_state(TaskState new_state) {
    // Validate state transition
    if (!is_valid_transition(m_state, new_state)) {
        throw std::invalid_argument("Invalid state transition");
    }
    m_state = new_state;
}

private:
static bool is_valid_transition(TaskState from, TaskState to) {
    // Define valid state transitions
    if (from == TaskState::Pending && to == TaskState::Ready) return true;
    if (from == TaskState::Ready && to == TaskState::Running) return true;
    // ... etc
    return false;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 29a2428 and 4c0555c.

📒 Files selected for processing (4)
  • src/spider/CMakeLists.txt (2 hunks)
  • src/spider/core/Data.hpp (1 hunks)
  • src/spider/core/Error.hpp (1 hunks)
  • src/spider/core/Task.hpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/spider/CMakeLists.txt
  • src/spider/core/Data.hpp
  • src/spider/core/Error.hpp
🔇 Additional comments (2)
src/spider/core/Task.hpp (2)

72-72: Document or implement TaskInstance class

The empty class declaration should either be documented to explain its future purpose or be implemented if it's currently needed.

Would you like me to help create a basic implementation or documentation for this class?


34-37: ⚠️ Potential issue

Add bounds checking for tuple access in get_task_output()

The tuple access could be unsafe if the optional is empty. Consider adding validation or using std::tie for safer tuple handling.

Apply this diff:

 [[nodiscard]] auto get_task_output(
 ) const -> std::optional<std::tuple<boost::uuids::uuid, std::uint8_t>> {
-    return m_task_output;
+    if (!m_task_output) {
+        return std::nullopt;
+    }
+    return m_task_output;
 }

Likely invalid or redundant comment.

Comment thread src/spider/core/Task.hpp
Comment on lines +96 to +97
std::vector<TaskInput> m_inputs;
std::vector<TaskOutput> m_outputs;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider pre-allocating vectors if size is known

If the number of inputs/outputs is known at construction time, consider using reserve() to prevent reallocation.

Example:

// In constructor
m_inputs.reserve(expected_inputs);
m_outputs.reserve(expected_outputs);

Comment thread src/spider/core/Task.hpp
Comment on lines +128 to +130
[[nodiscard]] auto get_input(uint64_t index) const -> TaskInput { return m_inputs[index]; }

[[nodiscard]] auto get_output(uint64_t index) const -> TaskOutput { return m_outputs[index]; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add bounds checking for vector access

The get_input and get_output methods should validate the index before accessing the vectors to prevent out-of-bounds access.

Apply this diff:

-    [[nodiscard]] auto get_input(uint64_t index) const -> TaskInput { return m_inputs[index]; }
+    [[nodiscard]] auto get_input(uint64_t index) const -> TaskInput {
+        if (index >= m_inputs.size()) {
+            throw std::out_of_range("Input index out of bounds");
+        }
+        return m_inputs[index];
+    }

-    [[nodiscard]] auto get_output(uint64_t index) const -> TaskOutput { return m_outputs[index]; }
+    [[nodiscard]] auto get_output(uint64_t index) const -> TaskOutput {
+        if (index >= m_outputs.size()) {
+            throw std::out_of_range("Output index out of bounds");
+        }
+        return m_outputs[index];
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[[nodiscard]] auto get_input(uint64_t index) const -> TaskInput { return m_inputs[index]; }
[[nodiscard]] auto get_output(uint64_t index) const -> TaskOutput { return m_outputs[index]; }
[[nodiscard]] auto get_input(uint64_t index) const -> TaskInput {
if (index >= m_inputs.size()) {
throw std::out_of_range("Input index out of bounds");
}
return m_inputs[index];
}
[[nodiscard]] auto get_output(uint64_t index) const -> TaskOutput {
if (index >= m_outputs.size()) {
throw std::out_of_range("Output index out of bounds");
}
return m_outputs[index];
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
src/spider/storage/MysqlStorage.cpp (1)

13-13: Improve parameter naming in method declarations.

Instead of commenting out parameter names, consider:

  1. Using meaningful parameter names in the declaration
  2. Adding [[nodiscard]] attribute to emphasize return value importance
  3. Using more descriptive names for UUID parameters

Example refactor:

[[nodiscard]] auto connect(std::string const& connection_url, 
    boost::uuids::uuid storage_id) -> StorageErr;

[[nodiscard]] auto get_task_graph(boost::uuids::uuid graph_id, 
    TaskGraph& out_task_graph) -> StorageErr;

Also applies to: 27-28, 40-41, 53-54, 70-71, 75-76, 84-85, 107-108, 112-114, 118-120, 124-127

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4c0555c and 6c5667b.

📒 Files selected for processing (1)
  • src/spider/storage/MysqlStorage.cpp (1 hunks)
🧰 Additional context used
🪛 cppcheck
src/spider/storage/MysqlStorage.cpp

[performance] 105-105: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)

🔇 Additional comments (1)
src/spider/storage/MysqlStorage.cpp (1)

1-131: Verify schema creation and migration strategy.

The implementation will need a way to:

  1. Create required tables if they don't exist
  2. Handle schema migrations for future updates
  3. Validate schema version during initialization

Let's check for existing schema management:

🧰 Tools
🪛 cppcheck

[performance] 105-105: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)

Comment on lines +13 to +15
auto MySqlMetadataStorage::connect(std::string /*url*/, boost::uuids::uuid /*id*/) -> StorageErr {
return StorageErr{};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement consistent error handling across all methods.

The current implementation returns empty StorageErr objects. Consider implementing proper error handling:

  1. Define specific error types for different failure scenarios
  2. Return appropriate error messages
  3. Include error context (e.g., method name, operation type)

Example implementation pattern:

auto MySqlMetadataStorage::initialize() -> StorageErr {
    if (nullptr == m_mysql) {
        return StorageErr{StorageErrType::NotConnected, "Database connection not established"};
    }
    
    try {
        // Implementation here
        return StorageErr{StorageErrType::Success, ""};
    } catch (const std::exception& e) {
        return StorageErr{StorageErrType::InitializationFailed, 
            std::string("Failed to initialize storage: ") + e.what()};
    }
}

Also applies to: 19-21, 23-25, 27-30, 32-34, 36-38, 40-43, 45-47, 49-51, 53-56, 58-60, 62-64, 66-68, 70-73, 75-78, 80-82, 84-87

Comment on lines +89 to +129
auto MySqlDataStorage::connect(std::string /*url*/, boost::uuids::uuid /*id*/) -> StorageErr {
return StorageErr{};
}

void MySqlDataStorage::close() {}

auto MySqlDataStorage::initialize() -> StorageErr {
return StorageErr{};
}

auto MySqlDataStorage::add_data(Data const& /*data*/) -> StorageErr {
return StorageErr{};
}

auto MySqlDataStorage::get_data(boost::uuids::uuid /*id*/, Data& /*data*/) -> StorageErr {
return StorageErr{};
}

auto MySqlDataStorage::add_task_reference(boost::uuids::uuid /*id*/, boost::uuids::uuid /*task_id*/)
-> StorageErr {
return StorageErr{};
}

auto MySqlDataStorage::
remove_task_reference(boost::uuids::uuid /*id*/, boost::uuids::uuid /*task_id*/)
-> StorageErr {
return StorageErr{};
}

auto MySqlDataStorage::
add_driver_reference(boost::uuids::uuid /*id*/, boost::uuids::uuid /*driver_id*/)
-> StorageErr {
return StorageErr{};
}

auto MySqlDataStorage::remove_driver_reference(
boost::uuids::uuid /*id*/,
boost::uuids::uuid /*driver_id*/
) -> StorageErr {
return StorageErr{};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add destructor and logging support for MySqlDataStorage.

Consider the following improvements:

  1. Add a virtual destructor to ensure proper cleanup
  2. Implement logging for debugging and monitoring
  3. Add connection state validation

Example implementation:

class MySqlDataStorage {
public:
    virtual ~MySqlDataStorage() {
        close();
    }
    
    auto connect(std::string const& url, boost::uuids::uuid id) -> StorageErr {
        SPDLOG_DEBUG("Connecting to MySQL storage with ID: {}", 
            boost::uuids::to_string(id));
        // Implementation
    }
    // ... other methods
};
🧰 Tools
🪛 cppcheck

[performance] 105-105: Variable 'm_id' is assigned in constructor body. Consider performing initialization in initialization list.

(useInitializationList)

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.

1 participant