Skip to content

Fix error on task kill#311

Open
Lucius1274 wants to merge 6 commits intomainfrom
fix_error_on_task_kill
Open

Fix error on task kill#311
Lucius1274 wants to merge 6 commits intomainfrom
fix_error_on_task_kill

Conversation

@Lucius1274
Copy link
Copy Markdown
Collaborator

@Lucius1274 Lucius1274 commented Mar 16, 2026

In the admin view, if clicking on the "kill task" button, the task was failed with an error. After the fix the task is properly canceled and the job the task belongs to is canceled accordingly.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Fixed cancellation workflow to properly recognize and report cancelled job and task states throughout the system.
    • Improved system reliability by ensuring all cancelled operations are consistently tracked and displayed with accurate status messages.
    • Enhanced error handling during operation cancellation to prevent status inconsistencies and provide clearer feedback to users.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

The pull request adds comprehensive support for handling canceled DICOM jobs and tasks. It extends the job post-processing logic to recognize canceled states, adds an exception handler for task cancellation events, and includes tests validating the new cancellation workflow for both job and task entities.

Changes

Cohort / File(s) Summary
Core Cancellation Logic
adit/core/models.py, adit/core/tasks.py
Updated job post-processing to treat CANCELING and CANCELED as incomplete states and compute final job status as CANCELED when all tasks are canceled. Added dedicated exception handler for futures.CancelledError to mark tasks as canceled with appropriate messaging and logging.
Cancellation Tests
adit/core/tests/test_models.py, adit/core/tests/test_tasks.py
New test cases validating job post-processing when all tasks are canceled and task-level cancellation through abort context signaling with state transition assertions.

Sequence Diagram

sequenceDiagram
    participant Context as Abort Context
    participant Task as process_dicom_task
    participant Processor as ExampleProcessor
    participant DicomTask as DicomTask (DB)
    participant Job as DicomJob (DB)
    
    Context->>Task: should_abort() → True
    Task->>Processor: process()
    Note over Processor: Blocking operation (sleep)
    Task->>Task: Check abort signal
    Task->>Processor: Raise CancelledError
    Processor-->>Task: futures.CancelledError
    Task->>DicomTask: Set status = CANCELED
    Task->>DicomTask: Set message = "Task was canceled."
    Task->>DicomTask: Commit to DB
    Note over Task: Task cancellation logged
    
    Job->>Job: post_process()
    Job->>DicomTask: Query all tasks
    DicomTask-->>Job: [CANCELED, CANCELED, ...]
    Job->>Job: No success/warning/failure found
    Job->>Job: At least one CANCELED exists
    Job->>Job: Set status = CANCELED
    Job->>Job: Set message = "All tasks were canceled."
    Job->>Job: Set end timestamp
    Job->>Job: Commit to DB
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 When tasks go quiet mid-process flow,
We catch the signal, off they go—
Mark them canceled, neat and true,
Jobs follow suit when all are through,
A graceful end to work half-done! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix error on task kill' directly matches the PR's objective to fix an error that occurred when clicking the kill task button in the admin view.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix_error_on_task_kill

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where attempting to kill a task in the admin view would result in an error rather than a proper cancellation. The changes ensure that when a task is canceled, it and its associated job are correctly marked with a 'CANCELED' status, providing a more accurate and functional cancellation mechanism within the system.

Highlights

  • Task Cancellation Handling: Implemented robust handling for task cancellations, ensuring that individual tasks and their parent jobs correctly transition to a 'CANCELED' state instead of failing.
  • Job Status Propagation: Updated the DicomJob.post_process method to recognize and propagate the 'CANCELED' status from its constituent tasks to the overall job status.
  • Error Handling for Canceled Futures: Added specific exception handling for futures.CancelledError within the task monitoring logic, allowing tasks to be gracefully marked as canceled.
  • Comprehensive Test Coverage: Introduced new unit tests to validate the correct behavior of job and task cancellation flows, including scenarios where all tasks within a job are canceled.
Changelog
  • adit/core/models.py
    • Modified post_process method to correctly transition a job to CANCELED status if it was CANCELING or already CANCELED.
    • Introduced a check for DicomTask.Status.CANCELED within a job's tasks.
    • Added logic to set a DicomJob's status to CANCELED and message to 'All tasks were canceled.' if all its tasks are canceled.
  • adit/core/tasks.py
    • Added futures.CancelledError exception handling in _monitor_task to properly mark a DicomTask as CANCELED when its processing is interrupted.
  • adit/core/tests/test_models.py
    • Added test_job_post_process_all_tasks_canceled to ensure DicomJob.post_process correctly handles jobs with all tasks in CANCELED status.
  • adit/core/tests/test_tasks.py
    • Added necessary imports for testing task cancellation, including sleep, cast, JobContext, and process_dicom_task.
    • Implemented test_process_dicom_task_that_gets_canceled_via_abort_context to test the DicomTask and DicomJob cancellation flow.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request implements a comprehensive cancellation mechanism for DICOM jobs and tasks. This includes handling futures.CancelledError to mark individual tasks as CANCELED, and updating job statuses to CANCELED when tasks are canceled or the job is in a CANCELING state. New tests were added to validate these cancellation flows. A review comment suggests an improvement in adit/core/models.py to prevent an unnecessary database write when a job is already in the CANCELED status.

Comment on lines +276 to 279
if self.status in [DicomJob.Status.CANCELING, DicomJob.Status.CANCELED]:
self.status = DicomJob.Status.CANCELED
self.save()
return False
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.

medium

This condition correctly includes DicomJob.Status.CANCELED, but it leads to an unnecessary database write if the job status is already CANCELED. You can avoid this by checking the status before saving.

Suggested change
if self.status in [DicomJob.Status.CANCELING, DicomJob.Status.CANCELED]:
self.status = DicomJob.Status.CANCELED
self.save()
return False
if self.status in (DicomJob.Status.CANCELING, DicomJob.Status.CANCELED):
if self.status == DicomJob.Status.CANCELING:
self.status = DicomJob.Status.CANCELED
self.save()
return False

Copy link
Copy Markdown
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.

🧹 Nitpick comments (2)
adit/core/tests/test_tasks.py (1)

184-194: Consider adding a proper job attribute to FakeContext for future-proofing.

The FakeContext.job = object() works for this test since the CancelledError path doesn't access context.job.attempts. However, if the code evolves to access job attributes in the cancellation path, this test would fail unexpectedly.

💡 Optional: Add a minimal job mock
     class FakeContext:
         def __init__(self):
-            self.job = object()
+            class FakeJob:
+                attempts = 0
+            self.job = FakeJob()

         def should_abort(self):
             return True
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adit/core/tests/test_tasks.py` around lines 184 - 194, FakeContext currently
sets job = object(), which may break if cancellation paths read job attributes;
update FakeContext used in the process_dicom_task test to provide a minimal job
mock with the attributes the code might access (e.g., an attempts integer and
any other small fields expected), so replace the plain object with a lightweight
stub (e.g., an instance or simple namespace) that defines .attempts (and any
other referenced properties) to avoid future brittle tests referencing
JobContext, ExampleTransferTask, or process_dicom_task.
adit/core/models.py (1)

303-305: Add tests to document behavior for mixed canceled/completed task scenarios.

The code correctly prioritizes completed task outcomes (SUCCESS/FAILURE/WARNING) over CANCELED status due to the elif chain. When a job has mixed task statuses (e.g., 1 SUCCESS + 1 CANCELED), the job reflects the completed task's outcome. Current tests cover all-CANCELED scenarios but lack coverage for mixed scenarios; adding tests for 1 SUCCESS + 1 CANCELED and 1 FAILURE + 1 CANCELED cases would explicitly document this expected behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adit/core/models.py` around lines 303 - 305, Add unit tests that assert
mixed-task behavior: create a DicomJob with two tasks where one task is
DicomJob.Status.SUCCESS and the other is DicomJob.Status.CANCELED, and another
test with one DicomJob.Status.FAILURE plus one DicomJob.Status.CANCELED; run
whatever routine sets the job status (the logic that sets self.status using
DicomJob.Status.*) and assert the job.status reflects SUCCESS in the first test
and FAILURE in the second (not CANCELED), and that job.message is not "All tasks
were canceled." to document the precedence of completed outcomes over CANCELED.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@adit/core/models.py`:
- Around line 303-305: Add unit tests that assert mixed-task behavior: create a
DicomJob with two tasks where one task is DicomJob.Status.SUCCESS and the other
is DicomJob.Status.CANCELED, and another test with one DicomJob.Status.FAILURE
plus one DicomJob.Status.CANCELED; run whatever routine sets the job status (the
logic that sets self.status using DicomJob.Status.*) and assert the job.status
reflects SUCCESS in the first test and FAILURE in the second (not CANCELED), and
that job.message is not "All tasks were canceled." to document the precedence of
completed outcomes over CANCELED.

In `@adit/core/tests/test_tasks.py`:
- Around line 184-194: FakeContext currently sets job = object(), which may
break if cancellation paths read job attributes; update FakeContext used in the
process_dicom_task test to provide a minimal job mock with the attributes the
code might access (e.g., an attempts integer and any other small fields
expected), so replace the plain object with a lightweight stub (e.g., an
instance or simple namespace) that defines .attempts (and any other referenced
properties) to avoid future brittle tests referencing JobContext,
ExampleTransferTask, or process_dicom_task.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4e4c11bf-260a-4954-ab38-9b5e08aa13ce

📥 Commits

Reviewing files that changed from the base of the PR and between 303f13e and 8cc909f.

📒 Files selected for processing (4)
  • adit/core/models.py
  • adit/core/tasks.py
  • adit/core/tests/test_models.py
  • adit/core/tests/test_tasks.py

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