-
Notifications
You must be signed in to change notification settings - Fork 4
Destroy grading sandboxes at pipeline cleanup #279
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -24,7 +24,7 @@ LOAD_TEMPLATE -> BUILD_TREE -> SANDBOX -> PRE_FLIGHT -> AI_BATCH -> GRADE -> FOC | |||||
| 2. Each step receives the same `PipelineExecution` and appends one `StepResult`. | ||||||
| 3. If a step fails, execution stops early. | ||||||
| 4. `finish_execution()` assembles `GradingResult` from grade/focus/feedback artifacts. | ||||||
| 5. Sandbox cleanup runs at the end. | ||||||
| 5. Sandbox cleanup runs at the end and destroys any sandbox used by the submission. | ||||||
|
||||||
| 5. Sandbox cleanup runs at the end and destroys any sandbox used by the submission. | |
| 5. In the normal execution flow, sandbox cleanup is called after finalization to destroy any sandbox used by the submission. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -39,7 +39,7 @@ Key behaviors: | |||||
| - After each step, the pipeline checks the latest `StepResult`. If it failed, the pipeline sets its status to `FAILED` and breaks. | ||||||
| - Unhandled exceptions set the status to `INTERRUPTED`. | ||||||
| - After all steps (or early exit), `finish_execution()` is called to assemble the final `GradingResult`. | ||||||
| - Sandbox cleanup always runs at the end, regardless of success or failure. | ||||||
| - Sandbox cleanup always runs at the end, regardless of success or failure, and destroys the sandbox used by that submission. | ||||||
|
||||||
| - Sandbox cleanup always runs at the end, regardless of success or failure, and destroys the sandbox used by that submission. | |
| - Sandbox cleanup is attempted at the end as a best-effort step and normally destroys the sandbox used by that submission, but it is not guaranteed if finalization raises an exception before cleanup is reached. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,7 @@ def pipeline_exec(submission): | |
|
|
||
| @patch("sandbox_manager.manager.get_sandbox_manager") | ||
| def test_cleanup_sandbox_called_after_pipeline_run(mock_get_manager, pipeline_exec): | ||
| """Verifies that _cleanup_sandbox is called and releases the sandbox correctly.""" | ||
| """Verifies that _cleanup_sandbox is called and destroys the sandbox correctly.""" | ||
| mock_manager = mock_get_manager.return_value | ||
| mock_sandbox = MagicMock(spec=SandboxContainer) | ||
|
|
||
|
|
@@ -39,11 +39,11 @@ def test_cleanup_sandbox_called_after_pipeline_run(mock_get_manager, pipeline_ex | |
| # Let's test _cleanup_sandbox directly to verify it uses the property | ||
| pipeline._cleanup_sandbox(pipeline_exec) | ||
|
Comment on lines
27
to
40
|
||
|
|
||
| mock_manager.release_sandbox.assert_called_once_with(Language.PYTHON, mock_sandbox) | ||
| mock_manager.destroy_sandbox.assert_called_once_with(Language.PYTHON, mock_sandbox) | ||
|
Comment on lines
40
to
+42
|
||
|
|
||
| @patch("sandbox_manager.manager.get_sandbox_manager") | ||
| def test_cleanup_sandbox_even_on_step_failure(mock_get_manager, pipeline_exec): | ||
| """Ensures that sandbox cleanup occurs even if the pipeline status is FAILED.""" | ||
| """Ensures sandbox destruction occurs even if the pipeline status is FAILED.""" | ||
| mock_manager = mock_get_manager.return_value | ||
| mock_sandbox = MagicMock(spec=SandboxContainer) | ||
|
|
||
|
|
@@ -55,16 +55,16 @@ def test_cleanup_sandbox_even_on_step_failure(mock_get_manager, pipeline_exec): | |
| pipeline._cleanup_sandbox(pipeline_exec) | ||
|
|
||
| # Cleanup should still happen | ||
| mock_manager.release_sandbox.assert_called_once_with(Language.PYTHON, mock_sandbox) | ||
| mock_manager.destroy_sandbox.assert_called_once_with(Language.PYTHON, mock_sandbox) | ||
|
|
||
| @patch("sandbox_manager.manager.get_sandbox_manager") | ||
| def test_cleanup_no_sandbox_no_call(mock_get_manager, pipeline_exec): | ||
| """Verifies that no sandbox release call is made if no sandbox is attached.""" | ||
| """Verifies that no sandbox destroy call is made if no sandbox is attached.""" | ||
| mock_manager = mock_get_manager.return_value | ||
|
|
||
| pipeline_exec.sandbox = None | ||
|
|
||
| pipeline = AutograderPipeline() | ||
| pipeline._cleanup_sandbox(pipeline_exec) | ||
|
|
||
| mock_manager.release_sandbox.assert_not_called() | ||
| mock_manager.destroy_sandbox.assert_not_called() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
finish_execution()can raise (e.g., missing grade step data / feedback step produced None), which would skip sandbox destruction because cleanup is not in afinally. Wrapfinish_execution()/return intry/finally(or move cleanup tofinally) so sandbox destruction truly runs even when finalization errors out or the pipeline is INTERRUPTED.