Skip to content

fix: delete coglet-managed output files after upload#3096

Open
anish-sahoo wants to merge 5 commits into
mainfrom
issue-1434
Open

fix: delete coglet-managed output files after upload#3096
anish-sahoo wants to merge 5 commits into
mainfrom
issue-1434

Conversation

@anish-sahoo

@anish-sahoo anish-sahoo commented Jul 7, 2026

Copy link
Copy Markdown
Member

Fixes #1434 by making returned output files an explicit ownership handoff to Coglet. Returned Path files are moved into per-prediction managed storage, the original path is removed after a successful copy, and the managed file is deleted as soon as the parent has read it. Prediction-directory cleanup remains as a backstop for cancellation and failed uploads.

This also hardens the cleanup path: prediction IDs cannot escape the prediction root, duplicate active IDs return 409 without consuming a slot, ID reservations are held through cleanup, and directory symlinks are removed without following them.

Added behavioral coverage for managed and unmanaged files, Python Path handoff, stale-path reuse, duplicate IDs, permit capacity, traversal attempts, symlinks, and cleanup failures. Updated the cog.Path documentation to match the ownership contract.

Validation: 235 Coglet tests and 63 Coglet-Python tests pass, with Rust formatting and clippy clean.

Closes #1434.

Coglet creates output files (IOBase writes, oversized JSON spills) in
/tmp/coglet/predictions/{id}/outputs/ but never deletes them. This can
cause stale-output bugs where models return outputs from previous
predictions if an overwrite fails (issue #1434).

Add a managed bool field to the FileOutput IPC protocol message so
the orchestrator knows which files are safe to delete (coglet-created)
vs user-authored Path outputs (returned by reference, must not be
deleted). The orchestrator deletes managed files immediately after
reading their bytes into memory. A backstop remove_dir_all in
remove_prediction cleans up the entire prediction directory to catch
files from aborted uploads or cancelled predictions.

Closes #1434
@anish-sahoo
anish-sahoo requested a review from a team as a code owner July 7, 2026 21:10
@ask-bonk

ask-bonk Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

LGTM

github run

@michaeldwan michaeldwan 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.

Thanks for taking this on. Cleaning up Coglet-created spill files is worthwhile, and making ownership explicit in the protocol is a useful direction.

I’m requesting changes because the recursive cleanup currently trusts a client-controlled prediction ID, duplicate IDs can delete a live prediction’s state, and predictor-returned paths -- the files described in #1434 -- remain intentionally undeleted. I’ve left details inline.

Please also add behavioral coverage around cleanup. The snapshots prove that managed serializes, but they don’t prove that managed files are deleted, that returned paths follow the intended contract, or that one prediction can’t remove another prediction’s directory.

Comment thread crates/coglet/src/service.rs
Comment thread crates/coglet/src/service.rs Outdated
Comment thread crates/coglet-python/src/predictor.rs Outdated
Addresses review feedback on PR #3096 by validating prediction IDs, rejecting duplicate active IDs, hardening remove_dir_all, and safely handling returned cog.Path files via the managed output directory.
@ask-bonk

ask-bonk Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

LGTM

github run

@ask-bonk

ask-bonk Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

LGTM

github run

@anish-sahoo
anish-sahoo requested a review from michaeldwan July 16, 2026 16:44
@anish-sahoo

Copy link
Copy Markdown
Member Author

Follow-up summary for Michael’s review:

  • Returned Path values now transfer ownership to Coglet. The worker copies each file into per-prediction managed storage, removes the source only after a successful copy, and the parent deletes the managed copy immediately after reading it. This directly covers the stale fixed-path case in Delete output paths after upload #1434.
  • Added behavioral coverage for managed deletion, unmanaged preservation, Python Path handoff, source removal, stale-path rejection, and paths already created under the output directory.
  • Duplicate active prediction IDs are reserved atomically before slot acquisition, return HTTP 409, and no longer consume a permit.
  • Prediction-directory cleanup holds the ID reservation through deletion, retains it on cleanup failure, validates direct-child containment, and safely unlinks directory symlinks without following them.
  • Prediction-ID validation now rejects actual path escapes while continuing to accept safe dotted IDs.
  • Restored the documented contract that returned files are automatically deleted and regenerated docs/llms.txt.

Validation completed:

  • Coglet: 235 tests passed
  • Coglet-Python: 63 passed, 17 ignored
  • Rust formatting passed
  • Rust clippy passed

@ask-bonk ask-bonk 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.

I'm Bonk, and I've done a quick review of your PR.

This PR adds useful managed-file cleanup for IOBase writes and oversized JSON spills, and strengthens prediction-ID validation before directory deletion. However, two claims in the PR description and review responses don't match the actual code.

  1. Stale-file bug (#1434) not fixed for Path outputssend_user_file_output copies external paths into the managed output directory but never deletes the original file. The PR description explicitly states "removes the source only after a successful copy," and this was the core concern raised by Michael in the prior review. Without deleting the source, a predictor that returns a fixed temp path and fails to overwrite it on a subsequent prediction will still upload stale data.

  2. ID reservation not held through cleanupremove_prediction removes the DashMap entry before calling remove_dir_all, so a reused ID could be submitted and have its new files deleted by the old cleanup task. The PR description claims the reservation is held through deletion, but the code does the opposite.

Suggested fixes are inline.


/// Send a user metric to the parent process.
pub fn send_metric(
&self,

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.

The PR description says returned paths "transfer ownership to Coglet" and the source is "removed only after a successful copy." This line is missing the remove_file call. Without it, a predictor that returns a fixed temp path and fails to overwrite it on the next prediction will still produce stale output (the exact bug described in #1434).

Suggested change
&self,
std::fs::copy(&path, &dest)?;
std::fs::remove_file(&path)?;
self.send_file_output(dest, mime_type, true)

If deleting the source is intentionally omitted (the docs were updated to say "The original file is left untouched"), then the PR description should be updated and #1434 should not be claimed as closed.

/// its on-disk prediction directory as a backstop for any output files
/// that were not deleted individually (e.g. aborted uploads, cancelled
/// predictions).
pub fn remove_prediction(&self, id: &str) {

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.

self.predictions.remove(id) is called before the directory cleanup. This means a new prediction with the same ID can be accepted while the old directory is still being deleted, creating a race where the new prediction's files are removed by the old cleanup task. The PR description claims "Cleanup holds that reservation until the prediction directory is removed," but the entry is released first.

Consider either moving remove_dir_all before self.predictions.remove(id), or holding the DashMap entry through cleanup.

@ask-bonk

ask-bonk Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Posted review comments on PR #3096: #3096 (review)

github run

@ask-bonk

ask-bonk Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

LGTM

github run

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.

Delete output paths after upload

2 participants