Skip to content

feat: Add batch job submission - #75

Merged
sitaowang1998 merged 12 commits into
y-scope:mainfrom
sitaowang1998:batch_submit
Mar 9, 2025
Merged

feat: Add batch job submission#75
sitaowang1998 merged 12 commits into
y-scope:mainfrom
sitaowang1998:batch_submit

Conversation

@sitaowang1998

@sitaowang1998 sitaowang1998 commented Mar 9, 2025

Copy link
Copy Markdown
Collaborator

Description

Right now Spider only supports submitting one job at a time, which is inefficient when user submit a large group of jobs at the same time. This pr introduces to calls to the driver interface, begin_batch_start and end_batch_start, which can be used around multiple start calls, to send all storage requests in batch.

Client now also keeps an open storage connection to avoid unnecessary latency. However, TaskContext in task executor does not keep open storage connection to avoid running out open connection resource.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

  • GitHub workflows pass
  • Unit tests pass in dev container
  • Integration tests pass in dev container

Summary by CodeRabbit

  • New Features
    • Added batch job submission functionality for more efficient processing of multiple tasks.
  • Refactor
    • Streamlined database connection handling to improve reliability and performance.
    • Reorganized MySQL integration into a dedicated structure for easier maintenance.
  • Chores
    • Updated include paths to reflect the new directory structure for MySQL components.
  • Tests
    • Enhanced automated test coverage to verify batch operations and robust error handling.

@sitaowang1998
sitaowang1998 requested a review from a team as a code owner March 9, 2025 18:22
@coderabbitai

coderabbitai Bot commented Mar 9, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This update reorganises MySQL-related files by moving source and header files into a dedicated mysql subdirectory under storage. Multiple include paths across the project have been updated accordingly. In addition, connection handling has been refactored in key components—especially in the Driver and Job classes—to use shared pointers and support batch job submissions. New headers defining SQL statements and job batch interfaces have been added, and test cases have been updated to reflect these structural and functional changes.

Changes

File(s) Change Summary
src/spider/CMakeLists.txt Updated MySQL source and header paths; added new headers (mysql_stmt.hpp, MySqlJobSubmissionBatch.hpp, JobSubmissionBatch.hpp) to support file reorganisation into the mysql subdirectory.
src/spider/client/Data.hpp, src/spider/client/TaskContext.{cpp,hpp}, src/spider/scheduler/scheduler.cpp, src/spider/worker/{FunctionManager.hpp,WorkerClient.cpp,task_executor.cpp,worker.cpp}, and related test files (e.g. tests/scheduler/*.cpp, tests/storage/*.hpp,*.cpp, tests/worker/*.cpp) Updated include directives to reflect the new MySQL header paths in storage/mysql/.
src/spider/client/{Driver.cpp,Driver.hpp,Job.hpp} Refactored connection handling to use shared pointers; introduced batch job submission methods (begin_batch_start(), end_batch_start()) and updated job handling logic to centralise connection management.
src/spider/storage/mysql/{MySqlConnection.cpp,MySqlConnection.hpp,MySqlStorage.cpp,MySqlStorage.hpp,MySqlJobSubmissionBatch.hpp, mysql_stmt.hpp}, src/spider/storage/JobSubmissionBatch.hpp, and src/spider/storage/MetadataStorage.hpp Simplified MySQL connection creation, updated SQL queries and table creation logic, and added batch processing support in storage components by modifying method signatures to include optional task states.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant D as Driver
    participant B as JobSubmissionBatch
    participant M as MetadataStorage
    participant S as MySQL Storage

    C->>D: begin_batch_start()
    D->>B: Initialize batch (MySqlJobSubmissionBatch)
    loop For each job
       C->>D: start(job)
       D->>B: Add job to batch
    end
    C->>D: end_batch_start()
    D->>M: add_job_batch(conn, batch, job_id, client_id, task_graph)
    M->>S: Execute batch submission via prepared statements
    S-->>M: Return StorageErr/Success
    M-->>D: Relay submission result
    D-->>C: Batch submission complete
Loading

Possibly related PRs

  • fix: Create database connection on need instead of keeping long-living connection #57: The changes in the main PR are related to the modifications in the retrieved PR as both involve updates to the MySQL connection handling, specifically the restructuring of file paths and the management of MySQL connection instances.
  • feat: Add pytest integration test for scheduler and worker #39: The changes in the main PR, which involve reorganizing MySQL-related files and updating their paths, are related to the modifications in the retrieved PR that also involve updating the include paths for the MySqlConnection header file, indicating a shared focus on the MySQL component structure.
  • fix: Limit storage connection lifetime in worker #74: The changes in the main PR, which involve reorganizing MySQL-related files and updating their paths, are related to the retrieved PR's modifications to the MySQL connection handling in WorkerClient.cpp, as both involve adjustments to how MySQL components are structured and referenced in the codebase.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ecaa38 and 47f4403.

📒 Files selected for processing (1)
  • tests/client/client-test.cpp (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/client/client-test.cpp
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
  • GitHub Check: lint

🪧 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 generate docstrings to generate docstrings for this 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: 2

🔭 Outside diff range comments (1)
src/spider/storage/mysql/MySqlStorage.cpp (1)

496-622: 🛠️ Refactor suggestion

Implements add_job_batch to handle large graphs in one shot.
This is crucial for efficient multi‐job insertion. The logic closely parallels add_job, so watch for any mismatch in ordering or rollback scenarios.

🧹 Nitpick comments (11)
tests/client/client-test.cpp (1)

160-177: Added test case for batch job submission.

This new test validates the batch job submission functionality introduced in the PR. It demonstrates how to:

  1. Begin a batch submission with begin_batch_start()
  2. Submit multiple jobs in a batch
  3. End the batch with end_batch_start()
  4. Verify the correct execution of all jobs in the batch

This test ensures the new feature works as intended and provides an example of its usage.

I notice that error conditions in the batch job test are logged but don't result in a return code that would indicate test failure. Consider returning the error code to ensure test failures are properly detected:

 if (job.get_status() != spider::JobStatus::Succeeded) {
     spdlog::error("Batch job failed");
+    return cJobFailed;
 }
 int const result = job.get_result();
 if (result != i + i) {
     spdlog::error("Batch job wrong result. Expect {}. Get {}.", i + i, result);
+    return cJobFailed;
 }
src/spider/client/Driver.cpp (1)

25-27: Consider initializing m_id in the initialization list

The m_id member is assigned in the constructor body. Consider moving it to the initialization list for consistency with C++ best practices.

-Driver::Driver(std::string const& storage_url) {
-    boost::uuids::random_generator gen;
-    m_id = gen();
+Driver::Driver(std::string const& storage_url) 
+    : m_id(boost::uuids::random_generator{}()) {
🧰 Tools
🪛 Cppcheck (2.10-2)

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

(useInitializationList)

src/spider/client/Driver.hpp (2)

138-171: Provides straightforward batch submission control.
The begin_batch_start() and end_batch_start() methods neatly encapsulate batch mode logic, preventing multiple concurrent batches. Be mindful of the scenario where begin_batch_start() is called but end_batch_start() is never invoked, which may leave an open m_batch. You might want to ensure or document that users always finalize their batches.


296-297: Introduces storage connection and batch member variables.
Storing these as std::shared_ptr is consistent with the new workflow. Just be mindful that if m_conn or m_batch become invalid externally, references here might lead to undefined behaviour.

src/spider/storage/mysql/MySqlStorage.hpp (2)

52-58: Introduces add_job_batch to the interface.
This method will allow clients to submit multiple tasks within a single transaction, aligning with the batch submission design. Ensure thorough integration tests to confirm consistent database state.


136-147: Adds overloading helpers for task insertion.
Splitting between add_task and add_task_batch helps avoid duplicated logic. Consider factoring out shared code if duplication grows.

src/spider/storage/mysql/MySqlStorage.cpp (1)

221-300: Implements add_task to insert tasks with optional states.
This handles function name, task inputs, and outputs thoroughly. Be sure to exercise complete coverage in unit tests, as partial inserts in error scenarios can be tricky.

src/spider/client/Job.hpp (3)

94-105: Check for repeated connection creation logic.
Similar fallback logic appears here, which may be extracted into a shared helper to avoid code duplication.


144-155: get_error() not implemented.
Currently, it throws a ConnectionException with a "Not implemented" message. If partial or placeholder error data is available, consider returning some minimal diagnostic info.

Do you want me to open a new issue to track implementing the logic for retrieving error details?


157-173: Constructor overloading for m_conn.
The two constructors differ only by whether a StorageConnection is provided. Document this carefully so that future usage is clear—particularly, which scenario each constructor is intended for.

src/spider/storage/mysql/MySqlJobSubmissionBatch.hpp (1)

41-60: Transactional integrity upon partial failures.
The rollback in line 54 handles an exception in the submit sequence, which is good. Consider whether partial results linger in memory or if certain data structures also need reset if the transaction fails.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f62ae5a and aac1b6d.

📒 Files selected for processing (28)
  • src/spider/CMakeLists.txt (2 hunks)
  • src/spider/client/Data.hpp (1 hunks)
  • src/spider/client/Driver.cpp (5 hunks)
  • src/spider/client/Driver.hpp (6 hunks)
  • src/spider/client/Job.hpp (5 hunks)
  • src/spider/client/TaskContext.cpp (1 hunks)
  • src/spider/client/TaskContext.hpp (1 hunks)
  • src/spider/scheduler/scheduler.cpp (1 hunks)
  • src/spider/storage/JobSubmissionBatch.hpp (1 hunks)
  • src/spider/storage/MetadataStorage.hpp (2 hunks)
  • src/spider/storage/mysql/MySqlConnection.cpp (1 hunks)
  • src/spider/storage/mysql/MySqlConnection.hpp (1 hunks)
  • src/spider/storage/mysql/MySqlJobSubmissionBatch.hpp (1 hunks)
  • src/spider/storage/mysql/MySqlStorage.cpp (16 hunks)
  • src/spider/storage/mysql/MySqlStorage.hpp (4 hunks)
  • src/spider/storage/mysql/mysql_stmt.hpp (1 hunks)
  • src/spider/worker/FunctionManager.hpp (1 hunks)
  • src/spider/worker/WorkerClient.cpp (1 hunks)
  • src/spider/worker/task_executor.cpp (1 hunks)
  • src/spider/worker/worker.cpp (1 hunks)
  • tests/client/client-test.cpp (2 hunks)
  • tests/scheduler/test-SchedulerPolicy.cpp (1 hunks)
  • tests/scheduler/test-SchedulerServer.cpp (1 hunks)
  • tests/storage/StorageTestHelper.hpp (1 hunks)
  • tests/storage/test-DataStorage.cpp (1 hunks)
  • tests/storage/test-MetadataStorage.cpp (2 hunks)
  • tests/worker/test-FunctionManager.cpp (1 hunks)
  • tests/worker/test-TaskExecutor.cpp (1 hunks)
🧰 Additional context used
🪛 Cppcheck (2.10-2)
src/spider/client/Driver.cpp

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

(useInitializationList)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
  • GitHub Check: lint
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
🔇 Additional comments (49)
src/spider/worker/WorkerClient.cpp (1)

26-26: Include path updated correctly.

The path to MySqlConnection.hpp has been updated to reflect the new directory structure with MySQL-related files now in a dedicated mysql subdirectory. This change is consistent with the project's reorganization of MySQL components.

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

18-18: Include path properly updated.

The include directive for MySqlConnection.hpp has been correctly updated to use the new path structure with MySQL components now in a dedicated subdirectory.

tests/scheduler/test-SchedulerServer.cpp (1)

28-28: Include path correctly modified.

The path to MySqlConnection.hpp has been properly updated to reflect the new directory structure, maintaining the correct relative path from the test file location.

src/spider/client/TaskContext.cpp (1)

12-12: Include path properly updated.

The path to MySqlConnection.hpp has been correctly modified to accommodate the new directory structure with MySQL components in a dedicated subdirectory.

src/spider/storage/mysql/MySqlConnection.hpp (1)

11-12: Include paths properly adjusted after file relocation.

Since MySqlConnection.hpp has been moved to the mysql subdirectory, the relative paths to the included headers have been correctly updated:

  1. Path to Error.hpp now goes up two directory levels instead of one
  2. Path to StorageConnection.hpp now goes up one level since it remains in the parent directory

These changes maintain proper include resolution after the file reorganization.

tests/storage/test-DataStorage.cpp (1)

16-16: Update include path for MySqlConnection header.

The include directive has been updated to point to the new location in the mysql subdirectory, which is consistent with the repository reorganisation.

tests/scheduler/test-SchedulerPolicy.cpp (1)

24-24: Revised MySqlConnection include path.

The include directive now correctly reflects the new mysql subdirectory structure. This update is consistent with the overall restructuring of MySQL-related files.

tests/worker/test-TaskExecutor.cpp (1)

25-25: Correct MySqlConnection include update.

The include path has been updated to use the new location in mysql, which aligns with the repository’s updated directory structure.

src/spider/worker/task_executor.cpp (1)

27-27: Update include for MySqlStorage header.

The change to include "../storage/mysql/MySqlStorage.hpp" instead of the former path is correct and in line with the new file organisation. There is no functional impact from this.

tests/worker/test-FunctionManager.cpp (1)

20-20: Adjust include directive for MySqlConnection.

The include directive now points to the mysql subdirectory version of MySqlConnection.hpp, which is consistent with the project-wide restructuring.

src/spider/client/TaskContext.hpp (1)

22-22: Path update is correct.

The include path has been correctly updated to reflect the new directory structure for MySQL-related files, which have been organized into a dedicated subdirectory.

src/spider/worker/FunctionManager.hpp (1)

29-29: Path update is correct.

The include path has been correctly updated to reflect the new directory structure where MySQL-related files have been moved to a dedicated subdirectory.

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

1-22: Well-designed abstract base class for batch job submission.

This new abstract interface provides the foundation for the batch job submission feature. The class is appropriately designed with:

  • A pure virtual method for batch submission
  • Proper rule-of-five implementation (deleted copy/move operations)
  • Virtual destructor for polymorphic inheritance

This design aligns well with the PR objective to support batch job submissions.

tests/storage/StorageTestHelper.hpp (1)

16-17: Path updates are correct.

The include paths have been correctly updated to reflect the restructured location of MySQL-related files, which have been moved to a dedicated subdirectory.

src/spider/worker/worker.cpp (1)

41-42: Include paths updated correctly.

The MySQL-related header files have been moved to a dedicated mysql subdirectory, consistent with the reorganization mentioned in the PR objectives.

src/spider/scheduler/scheduler.cpp (1)

27-28: Include paths updated correctly.

The MySQL-related header files have been moved to a dedicated mysql subdirectory, consistent with the reorganization mentioned in the PR objectives.

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

15-15: New include for batch job submission functionality.

The JobSubmissionBatch.hpp header file has been added to support the new batch job submission feature.


42-48:

Details

✅ Verification successful

New virtual method for batch job submission.

This new method extends the metadata storage interface to support batch job submissions, which aligns with the PR objectives to enhance the Spider application for submitting multiple jobs simultaneously. The method signature is consistent with the existing add_job method but takes an additional JobSubmissionBatch parameter.


🏁 Script executed:

#!/bin/bash
# Check if the MySqlMetadataStorage implementation includes the add_job_batch method
grep -A 10 "add_job_batch" src/spider/storage/mysql/MySqlStorage.hpp

Length of output: 573


Batch Job Submission Method Verified – Approved

The new virtual method add_job_batch in src/spider/storage/MetadataStorage.hpp is correctly implemented in MySqlStorage.hpp (as verified by the grep output). The method signature is consistent with the existing add_job function and suitably extends support for batch job submissions. No further changes are required.

tests/client/client-test.cpp (1)

78-78: Variable renamed for clarity.

The variable job has been renamed to graph_job to better reflect its purpose and distinguish it from other job types in the test.

Also applies to: 80-81, 82-82, 87-88

src/spider/storage/mysql/MySqlConnection.cpp (2)

10-12: Appropriate header changes to support batch processing

The addition of DriverManager and Properties headers provides the necessary components for the batch job submission feature. The DriverManager offers a more robust way to manage database connections while Properties allows configuration of bulk statements.


20-28: Good simplification of connection handling

The connection establishment has been nicely simplified by:

  1. Using a Properties object with useBulkStmts=true to enable batch operations
  2. Consolidating the connection creation into a single line using DriverManager
  3. Clarifying the comment to focus on validation rather than parsing

This is a clean improvement that will support the batch job submission functionality while reducing code complexity.

src/spider/CMakeLists.txt (2)

3-4: Well-organized MySQL source file restructuring

The MySQL-related source files have been properly moved to a dedicated mysql subdirectory, which improves code organization by grouping related components together.


28-32: Good addition of batch job submission headers

The CMakeLists.txt correctly includes the new headers necessary for batch job submission:

  1. mysql_stmt.hpp for SQL statement definitions
  2. MySqlJobSubmissionBatch.hpp for batch-specific implementation
  3. JobSubmissionBatch.hpp for the interface

This structure provides a clean separation between the generic batch submission interface and the MySQL-specific implementation, following good design principles.

src/spider/client/Driver.cpp (2)

37-39: Good use of shared_ptr for connection management

Using std::make_shared to create and store the MySQL connection is a good improvement. This maintains a single connection for the lifetime of the Driver, which aligns with the PR objective of reducing latency during batch operations by keeping an open storage connection.


112-120: Consistent use of stored connection

Methods now consistently use the stored shared connection pointer (*m_conn) instead of creating temporary connections, which will reduce connection overhead especially when submitting multiple jobs in batch.

🧰 Tools
🪛 Cppcheck (2.10-2)

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

(useInitializationList)

tests/storage/test-MetadataStorage.cpp (3)

21-22: Appropriate header updates for batch testing

The test file correctly includes the new MySqlJobSubmissionBatch header needed to test the batch submission functionality.


130-184: Good batch processing setup in existing test

The existing "Job add, get and remove" test has been modified to use the new batch processing capabilities. This ensures that the basic job operations work correctly within a batch context.


248-374: Comprehensive test coverage for batch job operations

The new "Job batch add, get and remove" test case thoroughly validates the batch job submission functionality. It provides complete test coverage by:

  1. Creating a batch processing context
  2. Testing complex task graphs with multiple dependencies
  3. Verifying correct job submission through batch interface
  4. Confirming job metadata can be retrieved correctly
  5. Validating task retrieval and relationship handling
  6. Testing job removal within the batch context

This test case ensures the batch job submission feature works as expected and maintains all the functionality of the non-batch approach.

src/spider/client/Driver.hpp (4)

20-23: Adds necessary includes for new batch submission functionality.
These headers are appropriate for the new batch job submission logic and storage connection handling.


214-228: Conditional logic cleanly ties into batch process.
Using add_job_batch when m_batch is non-null looks correct. This ensures that multiple job submissions are effectively combined, whereas standalone submissions continue to call add_job.


266-272: Extends start() to handle job creation consistently.
This line correctly uses m_metadata_storage->add_job() if there is no active batch. Ensure that all error codes returned by add_job or add_job_batch are properly handled to avoid partial job states in the database.


285-285: Fetches jobs by client ID with the new connection pointer.
Double-check whether any concurrency or race conditions might arise when multiple clients query the same records concurrently. This call otherwise seems correct.

src/spider/storage/mysql/MySqlStorage.hpp (2)

5-5: Includes <optional> for optional task states and related logic.
This is a good choice to accommodate the new approach.


15-27: Reorganized includes for MySQL storage files.
The new includes for Data.hpp, Driver.hpp, etc., appear consistent with the MySQL–specific classes.

src/spider/storage/mysql/MySqlStorage.cpp (5)

30-39: Introduces new headers for extended MySQL job submission.
These imports ensure the new batch submission code is integrated, though watch for potential compilation overhead from many includes.


127-139: Initializes storage with consolidated statements array.
Using mysql::cCreateStorage in a loop is a neat approach for schema initialization. Verify that partial table creation does not leave an inconsistent state if an error occurs mid-creation.


301-371: Adds batched version of task insertion (add_task_batch).
Your usage of prepared statements and batching can significantly cut overhead. Double-check edge cases, e.g., adding tasks with no inputs or outputs.


374-494: Extends add_job to rollback on any reference inconsistency.
The BFS‐like approach for adding tasks in topological order is logical. If referencing a large graph, ensure performance remains reasonable.


1783-1795: Initializes data storage with the same approach.
Reusing mysql::cCreateStorage again is consistent. Validate partial creation or concurrency concerns if multiple storage initializations run concurrently.

src/spider/storage/mysql/mysql_stmt.hpp (2)

1-206:

Details

❓ Verification inconclusive

Ensure that foreign key constraints align with all data lifecycles.
The code extensively uses ON DELETE CASCADE and other constraints. While beneficial for integrity, cascaded deletions might remove data that other parts of the system still need. Confirm that this behaviour is fully intended and tested, particularly for the jobs, tasks, and data tables.

You may want to run integration tests that validate whether child records are properly retained or removed after parent records are deleted:


🏁 Script executed:

#!/bin/bash
# Pseudocode: Re-run existing integration tests, in case specialized constraints are tested there
echo "Please run your integration tests to confirm that no data is inadvertently being deleted."

Length of output: 188


Action Required: Verify Foreign Key Cascade Behaviour Thoroughly
The integration test pseudocode you ran only confirmed that an instruction to execute tests exists—it didn’t provide actual test outcomes. Please ensure that your full integration test suite validates the cascading deletion behaviours for the jobs, tasks, and data tables. Confirm that deletions on parent records do not inadvertently remove child records needed elsewhere in the system.


1-206:

Details

❓ Verification inconclusive

Consider additional indexing to optimize query performance.
Several tables, for example tasks and data, contain fields (e.g., state, value) that may be frequently queried or filtered on. Adding secondary indexes or more granular indexing could improve performance when handling large volumes of data.

As a follow-up, please verify whether existing queries or usage patterns necessitate additional indexes by examining typical query patterns. You can start by searching for SQL statements referencing these columns:


🏁 Script executed:

#!/bin/bash
rg -A 2 -i 'SELECT' | grep -iE 'tasks|data'

Length of output: 6673


Action: Reconsider composite indexing on tasks based on query patterns

The query analysis confirms that many operations filter or sort by the state and job_id columns in the tasks table (e.g., SELECT state FROM tasks WHERE job_id = ? and other similar queries). In contrast, most queries on the data table primarily use its primary key, so additional indexing there seems less critical. I recommend:

  • Evaluating the benefit of a composite index on (job_id, state) for the tasks table to improve performance on queries filtering by both.
  • Checking typical workload patterns to ensure that the cost of additional indexes is justified.

Please verify these suggestions against your query execution plans and expected data volumes before implementing.

src/spider/client/Job.hpp (4)

24-25: No issues with the new includes.
These includes look compatible with the updated directory organization.


132-142: Confirm performance when retrieving larger result sets.
Creating a new connection on-demand can introduce overhead if the function is invoked frequently in large-scale scenarios. If tasks or results are large, consider leveraging a persistent connection pattern.


194-325: Comprehensive retrieval logic.
The approach for assembling tuples of outputs and verifying type consistency is quite thorough. Ensure that robust unit tests exist to confirm all branches (e.g., mismatched types, missing data, multiple output tasks).


332-332: Connection pointer usage.
m_conn is a shared pointer. Confirm that no cyclic references exist. If Job can outlive the connection context, it might inadvertently keep the connection alive.

src/spider/storage/mysql/MySqlJobSubmissionBatch.hpp (4)

19-29: Ensure prepareStatement is available on construction.
If this constructor is called too early (e.g., before the database session is fully established), subsequent statements might fail. Confirm that everything is safe at object construction time.


30-39: Consistent usage of the MySqlConnection pointer.
Both constructors perform nearly identical operations with different parameters. Confirm that the logic is consistent between sql::Connection& and MySqlConnection& so that prepared statements cannot diverge unexpectedly.


62-80: Getter methods facilitate better reusability.
Joining numerous statements into one class with getters fosters code clarity. This pattern is consistent with the rest of the design.


83-92: Clean resource management with unique_ptr.
Using std::unique_ptr for PreparedStatement ensures a neat release of resources. This is an appropriate approach for RAII.

Comment thread src/spider/client/Job.hpp
Comment on lines +174 to +192
auto wait_complete_conn(core::StorageConnection& conn) -> void {
bool complete = false;
core::StorageErr err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
if (!err.success()) {
throw ConnectionException{
fmt::format("Failed to get job completion status: {}", err.description)
};
}
while (!complete) {
constexpr int cSleepMs = 10;
std::this_thread::sleep_for(std::chrono::milliseconds(cSleepMs));
err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
if (!err.success()) {
throw ConnectionException{
fmt::format("Failed to get job completion status: {}", err.description)
};
}
}
auto& conn = std::get<core::MySqlConnection>(conn_result);
}

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

Potential infinite loop risk.
The while (!complete) poll/sleep approach may risk indefinite looping if the job is never marked complete. Consider adding a reasonable timeout or max retry count if your system can end up stuck.

Comment thread src/spider/client/Job.hpp
Comment on lines 66 to 77
auto wait_complete() -> void {
std::variant<core::MySqlConnection, core::StorageErr> conn_result
= core::MySqlConnection::create(m_data_storage->get_url());
if (std::holds_alternative<core::StorageErr>(conn_result)) {
throw ConnectionException(std::get<core::StorageErr>(conn_result).description);
}
auto& conn = std::get<core::MySqlConnection>(conn_result);

bool complete = false;
core::StorageErr err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
if (!err.success()) {
throw ConnectionException{
fmt::format("Failed to get job completion status: {}", err.description)
};
}
while (!complete) {
constexpr int cSleepMs = 10;
std::this_thread::sleep_for(std::chrono::milliseconds(cSleepMs));
err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
if (!err.success()) {
throw ConnectionException{
fmt::format("Failed to get job completion status: {}", err.description)
};
if (nullptr == m_conn) {
std::variant<core::MySqlConnection, core::StorageErr> conn_result
= core::MySqlConnection::create(m_data_storage->get_url());
if (std::holds_alternative<core::StorageErr>(conn_result)) {
throw ConnectionException(std::get<core::StorageErr>(conn_result).description);
}
auto& conn = std::get<core::MySqlConnection>(conn_result);
wait_complete_conn(conn);
}
wait_complete_conn(*m_conn);
}

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

Validate fallback connection creation in wait_complete.
When m_conn is null, the code creates a new MySqlConnection once and then uses wait_complete_conn(conn). However, line 76 unconditionally calls wait_complete_conn(*m_conn) again afterwards. There is no else block to skip that final invocation when a new connection was just created and used. This might result in logically redundant calls or potential misuse if m_conn remains null.

 auto wait_complete() -> void {
     if (nullptr == m_conn) {
         // ...
         wait_complete_conn(conn);
-    }
-    wait_complete_conn(*m_conn);
+    } else {
+        wait_complete_conn(*m_conn);
+    }
 }
📝 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
auto wait_complete() -> void {
std::variant<core::MySqlConnection, core::StorageErr> conn_result
= core::MySqlConnection::create(m_data_storage->get_url());
if (std::holds_alternative<core::StorageErr>(conn_result)) {
throw ConnectionException(std::get<core::StorageErr>(conn_result).description);
}
auto& conn = std::get<core::MySqlConnection>(conn_result);
bool complete = false;
core::StorageErr err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
if (!err.success()) {
throw ConnectionException{
fmt::format("Failed to get job completion status: {}", err.description)
};
}
while (!complete) {
constexpr int cSleepMs = 10;
std::this_thread::sleep_for(std::chrono::milliseconds(cSleepMs));
err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
if (!err.success()) {
throw ConnectionException{
fmt::format("Failed to get job completion status: {}", err.description)
};
if (nullptr == m_conn) {
std::variant<core::MySqlConnection, core::StorageErr> conn_result
= core::MySqlConnection::create(m_data_storage->get_url());
if (std::holds_alternative<core::StorageErr>(conn_result)) {
throw ConnectionException(std::get<core::StorageErr>(conn_result).description);
}
auto& conn = std::get<core::MySqlConnection>(conn_result);
wait_complete_conn(conn);
}
wait_complete_conn(*m_conn);
}
auto wait_complete() -> void {
if (nullptr == m_conn) {
std::variant<core::MySqlConnection, core::StorageErr> conn_result
= core::MySqlConnection::create(m_data_storage->get_url());
if (std::holds_alternative<core::StorageErr>(conn_result)) {
throw ConnectionException(std::get<core::StorageErr>(conn_result).description);
}
auto& conn = std::get<core::MySqlConnection>(conn_result);
wait_complete_conn(conn);
} else {
wait_complete_conn(*m_conn);
}
}

@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: 1

🧹 Nitpick comments (1)
src/spider/client/Job.hpp (1)

195-327: Consider breaking down the complex get_result_conn method.

The get_result_conn method has been marked to suppress complexity warnings, but it remains quite complex and difficult to maintain. Consider breaking it down into smaller, more focused methods that handle specific aspects like type checking, data retrieval, and tuple handling.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aac1b6d and 00941ba.

📒 Files selected for processing (1)
  • src/spider/client/Job.hpp (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
🔇 Additional comments (5)
src/spider/client/Job.hpp (5)

24-25: Updated include path for MySQL components.

The include path changes reflect the reorganization of MySQL-related files into a dedicated subdirectory, making the code structure more modular and organized.


66-77: Connection handling improvement with clear conditional logic.

The connection handling has been improved by adding a proper conditional check for an existing connection. This fixes the issue from the previous review where wait_complete_conn(*m_conn) was called unconditionally after creating a new connection.


183-192: Potential infinite loop risk.

The while (!complete) poll/sleep approach still carries a risk of indefinite looping if the job is never marked complete. Consider adding a reasonable timeout or max retry count.

 while (!complete) {
     constexpr int cSleepMs = 10;
+    static constexpr int cMaxRetries = 600;  // 6 seconds max wait time
+    static int retries = 0;
     std::this_thread::sleep_for(std::chrono::milliseconds(cSleepMs));
     err = m_metadata_storage->get_job_complete(conn, m_id, &complete);
     if (!err.success()) {
         throw ConnectionException{
                 fmt::format("Failed to get job completion status: {}", err.description)
         };
     }
+    if (++retries >= cMaxRetries) {
+        throw ConnectionException{"Timed out waiting for job to complete"};
+    }
 }

166-173: Good design for connection reuse in batch operations.

The new constructor accepting a shared StorageConnection pointer enables the batch job submission functionality described in the PR objectives. This allows for connection reuse across multiple operations, which should reduce latency.


333-333: Good addition of shared connection member.

Adding a shared pointer to a storage connection as a member variable is central to enabling the batch processing functionality described in the PR objectives. This allows the job to maintain and reuse an open storage connection.

Comment thread src/spider/client/Job.hpp
Comment on lines +154 to +156
auto get_error() -> std::pair<std::string, std::string> {
throw ConnectionException{"Not implemented"};
}

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 the get_error method.

The get_error method is declared but not implemented, throwing a "Not implemented" exception. This is inconsistent with having it as part of the public API. Either implement the method or mark it as a TODO with a clear timeline for implementation.

@sitaowang1998
sitaowang1998 merged commit cf758fe into y-scope:main Mar 9, 2025
@sitaowang1998
sitaowang1998 deleted the batch_submit branch March 9, 2025 23:57
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