Skip to content

feat: Add job cancellation. #137

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 52 commits into
base: main
Choose a base branch
from

Conversation

sitaowang1998
Copy link
Collaborator

@sitaowang1998 sitaowang1998 commented May 12, 2025

Description

Add job cancellation support from inside the task through TaskContext::abort and from user through Job::cancel.

Add job_errors table to store the cancellation messages. Add storage functions to cancel job and to get cancellation messages. Add implementation of the two functions mentioned in previous paragraph in client. Add task cancellation check in worker. Add unit tests for new storage functions. Add integration tests for job cancellation.

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

Summary by CodeRabbit

  • New Features

    • Added job and task cancellation methods with error message retrieval.
    • Implemented thread-safe management of task execution and cancellation.
    • Extended database schema with a job_errors table for storing error details.
  • Bug Fixes

    • Improved task state handling to correctly reflect cancellations and errors.
  • Tests

    • Developed unit and integration tests for cancellation workflows.
    • Added test tasks for sleep and abort scenarios to verify cancellation logic.
  • Refactor

    • Renamed task state check methods for clarity and consistency.
  • Chores

    • Updated build and test configurations to incorporate new features and tests.

@sitaowang1998 sitaowang1998 requested a review from a team as a code owner May 12, 2025 20:22
Copy link
Contributor

coderabbitai bot commented May 12, 2025

Warning

Rate limit exceeded

@sitaowang1998 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 4 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e2a2ea6 and 1d20f50.

📒 Files selected for processing (2)
  • tests/client/cancel-test.cpp (1 hunks)
  • tests/storage/test-MetadataStorage.cpp (2 hunks)
## Walkthrough

This update adds job and task cancellation features, including schema changes, storage API extensions, worker cancellation checks, and related tests. It also introduces thread-safe `ExecutorHandle` management and updates task executor state methods.

## Changes

| File(s)                                                                                 | Summary                                                                                                             |
|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| src/spider/CMakeLists.txt, src/spider/worker/ExecutorHandle.cpp, src/spider/worker/ExecutorHandle.hpp | Adds `ExecutorHandle` class and integrates it into the build process.                                              |
| src/spider/client/Job.hpp                                                               | Implements `cancel()` and `get_error()` methods for job cancellation and error retrieval.                          |
| src/spider/client/TaskContext.cpp                                                       | Adds `abort()` method to cancel a job from within a task, with immediate process termination.                      |
| src/spider/storage/MetadataStorage.hpp, src/spider/storage/mysql/MySqlStorage.hpp       | Extends storage API with job/task cancellation and error message retrieval methods.                                 |
| src/spider/storage/mysql/MySqlStorage.cpp                                               | Implements job/task cancellation and error retrieval in MySQL storage; updates `task_fail` logic.                  |
| src/spider/storage/mysql/mysql_stmt.hpp, tools/scripts/storage/init_db.sql              | Adds new `job_errors` table and corresponding SQL schema for storing job error messages.                           |
| src/spider/worker/TaskExecutor.cpp, src/spider/worker/TaskExecutor.hpp                  | Renames task state query methods; adds `cancelled()` method.                                                      |
| src/spider/worker/worker.cpp                                                            | Implements cooperative task cancellation in the worker, integrates with heartbeat, and updates control flow.        |
| tests/CMakeLists.txt, tests/client/cancel-test.cpp, tests/integration/test_cancel.py    | Adds new client and integration tests for cancellation; updates test build configuration.                          |
| tests/storage/test-MetadataStorage.cpp                                                  | Adds unit tests for job cancellation and cancellation by task.                                                      |
| tests/worker/worker-test.cpp, tests/worker/worker-test.hpp                              | Adds test tasks for sleep and abort scenarios; updates test task declarations.                                     |
| tests/worker/test-TaskExecutor.cpp                                                      | Updates test assertions to use new task executor state method names.                                               |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant Driver
    participant MetadataStorage
    participant Worker
    participant ExecutorHandle
    participant TaskExecutor

    Client->>Driver: submit_job()
    Driver->>MetadataStorage: create_job()
    MetadataStorage-->>Driver: job_id
    Driver-->>Client: Job

    Client->>Job: cancel()
    Job->>MetadataStorage: cancel_job(job_id, message)
    MetadataStorage-->>Job: result

    loop Heartbeat
        Worker->>ExecutorHandle: get_task_id()
        alt Task running
            Worker->>MetadataStorage: get_task_state(task_id)
            MetadataStorage-->>Worker: state
            alt state == Cancelled
                Worker->>ExecutorHandle: get_executor()
                Worker->>TaskExecutor: cancel()
            end
        end
    end

    Worker->>TaskExecutor: run()
    alt Task cancelled
        TaskExecutor-->>Worker: is_cancelled() == true
        Worker-->>MetadataStorage: update task/job state to Cancelled
    else Task completes
        Worker-->>MetadataStorage: update task/job state to Succeeded/Failed
    end

Suggested reviewers

  • davidlion

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [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)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=y-scope/spider&utm_content=137):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `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 explain this code block.`
  -	`@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 explain its main purpose.`
  - `@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.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

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](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in 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](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://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/spider/storage/mysql/MySqlStorage.cpp (2)

1056-1083: Silent success & missing guard in cancel_job() (see earlier review)

This implementation still:

  1. Ignores the affected-row count of the UPDATE statements – an invalid job_id will “succeed” silently.
  2. Allows multiple identical rows to accumulate in job_errors.
  3. Rolls back only on SQL exceptions, not on logical errors.

Please revisit the earlier suggestion (copied below) and apply it:

 int32_t updated = task_statement->executeUpdate();
 if (updated == 0) {
     static_cast<MySqlConnection&>(conn)->rollback();
     return StorageErr{StorageErrType::KeyNotFoundErr,
                       fmt::format("No running job with id {}", boost::uuids::to_string(id))};
 }

 updated = job_statement->executeUpdate();
 if (updated == 0) {
     static_cast<MySqlConnection&>(conn)->rollback();
     return StorageErr{StorageErrType::KeyNotFoundErr,
                       fmt::format("No job with id {}", boost::uuids::to_string(id))};
 }

-"INSERT INTO `job_errors` ..."
+"INSERT IGNORE INTO `job_errors` ..."

1085-1142: Same robustness issues in cancel_job_by_task()

The method duplicates the problems outlined for cancel_job() (lack of row-count checks and duplicate job_errors entries). Apply the same guards here for consistency and reliability.

🧹 Nitpick comments (2)
src/spider/worker/ExecutorHandle.cpp (1)

31-35: set() does not guarantee visibility of paired members

m_task_id and m_executor are set individually. A racing reader could observe a new task_id paired with the previous executor (or vice-versa). Pack them into a struct and assign once, or update m_executor first, then m_task_id (the latter being the validity flag).

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

18-22: Accessor methods should be const

Both get_task_id() and get_executor() do not modify the object and can safely be marked const, improving usability and conveying intent.

-[[nodiscard]] auto get_task_id() -> std::optional<boost::uuids::uuid>;
-[[nodiscard]] auto get_executor() -> TaskExecutor*;
+[[nodiscard]] auto get_task_id() const -> std::optional<boost::uuids::uuid>;
+[[nodiscard]] auto get_executor() const -> TaskExecutor*;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e2cad8f and 17dd4df.

📒 Files selected for processing (10)
  • src/spider/client/Job.hpp (2 hunks)
  • src/spider/storage/MetadataStorage.hpp (2 hunks)
  • src/spider/storage/mysql/MySqlStorage.cpp (3 hunks)
  • src/spider/storage/mysql/MySqlStorage.hpp (2 hunks)
  • src/spider/worker/ExecutorHandle.cpp (1 hunks)
  • src/spider/worker/ExecutorHandle.hpp (1 hunks)
  • src/spider/worker/worker.cpp (8 hunks)
  • tests/CMakeLists.txt (2 hunks)
  • tests/client/cancel-test.cpp (1 hunks)
  • tests/storage/test-MetadataStorage.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • tests/CMakeLists.txt
  • src/spider/storage/mysql/MySqlStorage.hpp
  • tests/client/cancel-test.cpp
  • src/spider/client/Job.hpp
  • src/spider/storage/MetadataStorage.hpp
  • tests/storage/test-MetadataStorage.cpp
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/spider/worker/ExecutorHandle.cpp (1)
src/spider/worker/ExecutorHandle.hpp (1)
  • task_id (21-21)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
  • GitHub Check: lint
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
🔇 Additional comments (8)
src/spider/storage/mysql/MySqlStorage.cpp (2)

1520-1551: Map unknown task state to error, not Pending

string_to_task_state() returns Pending for unknown strings. Thus, if the DB contains a typo, get_task_state() will silently report Pending instead of signalling an error.

-if (state_str.empty()) {
-    *state = spider::core::TaskState::Pending;
-} else {
-    // ...
-}
+if (state_str.empty()) {
+    static_cast<MySqlConnection&>(conn)->rollback();
+    return StorageErr{StorageErrType::OtherErr,
+                      fmt::format("Unknown task state '{}'", state_str)};
+}

1836-1845: Good defensive update in task_fail()

The added row-count check prevents false failure propagation when the task is no longer running. Nice catch!

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

50-50: Good addition of ExecutorHandle inclusion for managing task cancellation.

This inclusion properly supports the new cancellation mechanism introduced in this PR.


127-158: Well-implemented cancellation check with appropriate error handling.

The check_task_cancel function properly implements the cooperative cancellation mechanism by:

  1. Retrieving the current task ID from the executor handle
  2. Checking the task state from the metadata store
  3. Triggering cancellation when appropriate

The function contains thorough error handling and follows a clear, logical flow.


164-164: Properly integrated cancellation check into the heartbeat loop.

Adding the executor_handle parameter and calling check_task_cancel in the heartbeat loop enables asynchronous detection of cancellation requests. This is an efficient approach that leverages the existing heartbeat mechanism.

Also applies to: 185-186


326-326: Improved method naming for better readability.

Renaming succeed() to is_succeeded() follows better naming conventions for boolean getter methods and improves code clarity.


388-388: Well-implemented task cancellation handling in the task loop.

The implementation:

  1. Properly tracks the current task with executor_handle.set(task_id, &executor)
  2. Clears the handle after execution with executor_handle.clear()
  3. Correctly handles cancellation cases with detailed comments explaining the behavior

The code cleanly integrates cancellation into the existing task execution flow without disrupting the normal path.

Also applies to: 430-431, 443-443, 446-453


558-559: Properly initialized and shared executor_handle across threads.

The ExecutorHandle is correctly instantiated in the main thread and passed to both the heartbeat and task threads, allowing for coordinated cancellation detection and handling.

Also applies to: 566-566, 574-574

@sitaowang1998 sitaowang1998 requested a review from davidlion May 13, 2025 00:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/spider/client/TaskContext.cpp (1)

74-87: Address the previous review feedback about exit code and documentation.

The implementation still has the same issues identified in the previous review:

  • Using generic exit code 1 instead of a specific cancellation code
  • Lack of documentation about the immediate termination behaviour
  • Should use a dedicated exit code like 130 for cancellation

Please refer to the previous review comment for the detailed solution.

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

1056-1083: ⚠️ Potential issue

Validate target job & guard against silent failures

The cancel_job() method executes UPDATE statements without checking affected rows. If an invalid job_id is supplied, the function silently "succeeds", leaving the caller unaware that no job was actually cancelled. Additionally, unlike cancel_job_by_task(), this method doesn't insert into job_errors, creating an inconsistency in error tracking.


1085-1142: ⚠️ Potential issue

Add UPDATE validation and prevent duplicate error entries

Similar to cancel_job(), this method doesn't validate the affected row count after UPDATE operations. Additionally, multiple calls with the same task could insert duplicate entries into job_errors.

Consider:

  1. Checking affected rows after each UPDATE
  2. Using INSERT IGNORE or ON DUPLICATE KEY UPDATE to handle duplicate entries
-        task_statement->executeUpdate();
+        int32_t updated = task_statement->executeUpdate();
+        // Log or handle cases where no tasks were updated

...

-        job_statement->executeUpdate();  
+        updated = job_statement->executeUpdate();
+        if (updated == 0) {
+            static_cast<MySqlConnection&>(conn)->rollback();
+            return StorageErr{StorageErrType::KeyNotFoundErr,
+                            fmt::format("No job found for task {}", boost::uuids::to_string(id))};
+        }

...

-                        "INSERT INTO `job_errors` (`job_id`, `func_name`, `message`) VALUES (?, ?, "
-                        "?) "
+                        "INSERT INTO `job_errors` (`job_id`, `func_name`, `message`) VALUES (?, ?, ?) "
+                        "ON DUPLICATE KEY UPDATE `message` = VALUES(`message`)"
🧹 Nitpick comments (1)
src/spider/storage/mysql/MySqlStorage.cpp (1)

1056-1083: Consider adding optional message parameter to cancel_job for consistency

Currently, cancel_job() doesn't record any message in job_errors, while cancel_job_by_task() does. This inconsistency could make it difficult to track why jobs were cancelled. Consider either:

  1. Adding an optional message parameter to cancel_job()
  2. Always inserting a default message like "Cancelled by user" when no specific message is provided

This would ensure all cancellations are properly tracked in job_errors.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 17dd4df and 1f4160b.

📒 Files selected for processing (12)
  • src/spider/CMakeLists.txt (1 hunks)
  • src/spider/client/Job.hpp (2 hunks)
  • src/spider/client/TaskContext.cpp (2 hunks)
  • src/spider/storage/MetadataStorage.hpp (2 hunks)
  • src/spider/storage/mysql/MySqlStorage.cpp (3 hunks)
  • src/spider/storage/mysql/MySqlStorage.hpp (2 hunks)
  • src/spider/worker/TaskExecutor.cpp (2 hunks)
  • src/spider/worker/TaskExecutor.hpp (1 hunks)
  • src/spider/worker/worker.cpp (8 hunks)
  • tests/CMakeLists.txt (2 hunks)
  • tests/storage/test-MetadataStorage.cpp (1 hunks)
  • tests/worker/test-TaskExecutor.cpp (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/spider/CMakeLists.txt
  • tests/worker/test-TaskExecutor.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
🔇 Additional comments (19)
src/spider/worker/TaskExecutor.cpp (2)

24-48: LGTM! Consistent method naming and proper cancellation state handling.

The method renames to use the "is_" prefix improve consistency and readability. The new is_cancelled() method follows the same thread-safe pattern as other state checking methods.


85-90: Good defensive programming for cancellation handling.

The early state check prevents unnecessary message processing when the task is no longer in an active state (Waiting or Running). This is appropriate for the cancellation feature and helps ensure clean termination.

tests/CMakeLists.txt (1)

89-99: LGTM! Proper test executable setup.

The new cancel_test executable follows the established pattern for test builds with appropriate library linking and dependency management.

Also applies to: 114-114

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

85-97: LGTM! Consistent implementation following established patterns.

The cancel() method properly handles storage connection acquisition and error propagation, following the same pattern as other methods in this class.


167-192: LGTM! Proper error retrieval implementation.

The get_error() method correctly handles both connection scenarios (null and non-null m_conn) and follows the established error handling pattern. The return type std::pair<std::string, std::string> matches the documented interface for task function name and error message.

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

158-162: Good naming convention improvement!

The renaming to is_* style for boolean predicate methods follows C++ best practices and makes the API more intuitive. The addition of is_cancelled() properly extends the state checking interface for the new cancellation feature.

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

445-518: Well-structured job cancellation test!

The test comprehensively covers the job cancellation workflow:

  • Correctly verifies that completed tasks retain their success state
  • Ensures pending tasks transition to cancelled state
  • Validates job status update

Good test coverage for the basic cancellation scenario.


520-600: Excellent test for task-initiated cancellation!

This test effectively validates the extended cancellation functionality:

  • Tests cancellation triggered by a specific task ID
  • Verifies error message storage and retrieval
  • Confirms the association between error message and originating task
  • Maintains consistency with state transition expectations

The test provides thorough coverage of the task-based cancellation feature.

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

74-83: Clean interface extension for job cancellation!

The new methods properly extend the storage interface to support the cancellation feature:

  • cancel_job and cancel_job_by_task provide two cancellation paths
  • get_job_message enables error message retrieval with associated task context
  • get_task_state adds necessary state querying capability

The interface design is consistent with existing patterns and supports the requirements shown in the tests.

Also applies to: 99-100

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

75-82: LGTM! Clean interface additions for job cancellation.

The new virtual methods are well-designed and properly documented. The separation of concerns between cancel_job (external cancellation) and cancel_job_by_task (internal cancellation with error message) is appropriate.

Also applies to: 83-94, 95-109, 130-132

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

1144-1172: LGTM!

Clean implementation with proper error handling for missing messages.


1520-1551: LGTM!

Straightforward getter implementation following the established pattern.


1836-1845: Good defensive programming!

The added check prevents unnecessary job state updates and handles race conditions where the task might already be in a terminal state.

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

50-50: LGTM!

The include is necessary for the new cancellation feature implementation.


127-159: Implementation looks good with proper thread safety.

The cancellation check logic is well-structured with appropriate error handling. The thread safety concern from previous reviews has been addressed through the mutex-protected ExecutorHandle implementation.

Note: When get_task_state fails due to storage issues, the function returns early and the potentially cancelled task continues running. This might be the intended behavior to avoid disrupting tasks due to transient storage problems, but worth documenting this decision.


160-202: Well-integrated cancellation check in heartbeat loop.

The storage connection handling uses proper RAII with shared_ptr, and the cancellation check is appropriately placed after acquiring the connection. The error handling and retry logic remain intact.


326-326: LGTM!

Method rename follows the consistent is_ prefix pattern for boolean predicates.


385-461: Proper executor handle lifecycle management and cancellation handling.

The implementation correctly:

  • Sets the executor handle before task execution
  • Clears it after completion to prevent stale references
  • Skips result processing for cancelled tasks since the storage state is already updated

The detailed comments explaining the cancellation scenarios are helpful for maintainability.


558-579: LGTM!

The ExecutorHandle instance is correctly created and shared between the heartbeat and task threads, enabling proper cancellation coordination.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/spider/storage/mysql/MySqlStorage.cpp (2)

1079-1106: Address the previous review feedback on validation

The previous review feedback about validating target job and checking affected-row counts has not been implemented. The function still unconditionally executes UPDATE statements without checking if any rows were affected, allowing invalid job IDs to silently "succeed".


1108-1165: Address the previous review feedback on validation and duplicate handling

The previous review feedback about validating UPDATE statements and preventing duplicate error rows has not been implemented. The function still doesn't check affected-row counts for UPDATE statements and uses regular INSERT instead of INSERT IGNORE for the job_errors table.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1f4160b and c0f533f.

📒 Files selected for processing (13)
  • src/spider/CMakeLists.txt (1 hunks)
  • src/spider/client/Job.hpp (2 hunks)
  • src/spider/storage/MetadataStorage.hpp (2 hunks)
  • src/spider/storage/mysql/MySqlStorage.cpp (3 hunks)
  • src/spider/storage/mysql/MySqlStorage.hpp (2 hunks)
  • src/spider/worker/ExecutorHandle.hpp (1 hunks)
  • src/spider/worker/TaskExecutor.cpp (2 hunks)
  • src/spider/worker/TaskExecutor.hpp (1 hunks)
  • src/spider/worker/worker.cpp (8 hunks)
  • tests/client/cancel-test.cpp (1 hunks)
  • tests/integration/test_cancel.py (1 hunks)
  • tests/storage/test-MetadataStorage.cpp (1 hunks)
  • tests/worker/test-TaskExecutor.cpp (5 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/spider/worker/ExecutorHandle.hpp
🚧 Files skipped from review as they are similar to previous changes (10)
  • tests/worker/test-TaskExecutor.cpp
  • src/spider/worker/TaskExecutor.cpp
  • src/spider/CMakeLists.txt
  • src/spider/worker/TaskExecutor.hpp
  • src/spider/client/Job.hpp
  • src/spider/storage/mysql/MySqlStorage.hpp
  • tests/client/cancel-test.cpp
  • src/spider/storage/MetadataStorage.hpp
  • src/spider/worker/worker.cpp
  • tests/integration/test_cancel.py
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
🔇 Additional comments (5)
tests/storage/test-MetadataStorage.cpp (2)

451-515: LGTM! Solid test coverage for job cancellation.

This test case effectively validates the basic job cancellation functionality, correctly verifying that:

  • The job status transitions to "Cancelled"
  • Already finished tasks retain their "Succeed" state
  • Pending/ready tasks transition to "Canceled" state

The test logic is sound and follows proper testing patterns.


517-589: LGTM! Comprehensive test for task-initiated cancellation.

This test case properly validates the advanced cancellation functionality including error message handling. The verification of get_error_message() functionality and correct task ID storage is excellent.

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

1167-1195: Well-implemented query method

The implementation follows proper patterns with appropriate error handling, transaction management, and meaningful error messages.


1543-1574: Consistent implementation with proper error handling

The method follows established patterns in the codebase with appropriate error handling and transaction management.


1859-1868: Good defensive programming improvements

The addition of state validation and early return when no rows are affected improves the method's robustness and consistency.

@sitaowang1998 sitaowang1998 requested a review from davidlion May 29, 2025 20:28
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.

2 participants