You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes #1287. When the API cancels a synchronous ingest (POST /asset-ingest) partway through, Engine left files behind on the scratch disk and didn't record the outcome in the DB.
1. Partial downloads left on scratch disk
For "file" channel assets (e.g. the PDFs in the issue), AssetToS3.IndirectAssetCopyBucketToBucket downloads the origin to disk, uploads it to S3, then deletes the local copy in a finally. The file path was only recorded after the download completed, so:
Cancelled mid-download:FileSaver.SaveResponseToDisk threw partway through writing and the partial file was orphaned.
Asset exceeds storage allowance: the early return happened before the path was recorded, so the whole download was left behind.
Changes:
FileSaver.SaveResponseToDisk now deletes the partially written file if writing fails (including cancellation), then re-throws. This is best-effort: a failed delete logs a warning and never replaces the original exception.
AssetToS3 records the downloaded file path before the allowance check, so the finally always cleans it up.
Deleting the whole per-asset download folder was avoided because adjunct downloads are nested under it (…/{image}/adjuncts/{id}), so it could remove files belonging to a concurrent adjunct ingest.
Image ingests weren't affected because ImageIngestPostProcessing already deletes the working folder regardless of outcome.
2. Error finalising item <id> in DB
IngestExecutor passed the request's (now cancelled) token into the final DB write, so UpdateIngestedDeliverable failed immediately. The item was left in an "ingesting" state with no error recorded.
Changes in IngestExecutor:
CompleteAssetInDatabase / CompleteAdjunctInDatabase always use CancellationToken.None, so the outcome is recorded even if the caller has gone away.
AdjustAdjunctStoredSize also uses CancellationToken.None. Otherwise an adjunct could be finalised without its size delta being applied, and the customer's storage totals would drift.
The storage pre-checks that run before the workers (GetStorageMetrics, GetImageSize) also use CancellationToken.None. Cancelling during these would otherwise throw before the DB write, with the same "stuck ingesting" result.
Only the workers now honour cancellation. They already catch their own exceptions and record them as a failure on the asset/adjunct.
Tests
AssetToS3Tests: the local file is deleted when the download exceeds the allowance and when the S3 upload throws.
IngestExecutorTests: for assets and adjuncts, cancelling either during a worker or before the workers run still results in the DB write (and adjunct size adjustment) using CancellationToken.None.
Merged without review due to annual leave. Reviewed by Claude
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this change?
Resolves #1287
Makes it so that if an ingest is cancelled, it will be cleaned up in the attached storage, and makes sure that the database records the failure.