From 2df020ac597f94f7ed141b399c3ed604b6aff076 Mon Sep 17 00:00:00 2001 From: neilcroft Date: Thu, 30 Apr 2026 15:46:02 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(backend)=20clean=20storage=20files?= =?UTF-8?q?=20in=20clean=5Fpending=5Fitems?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use process_item_purge to delete stale pending items so that eventual files on the storage are also removed. Closes #600 --- CHANGELOG.md | 1 + .../commands/clean_pending_items.py | 4 +++- .../commands/test_clean_pending_items.py | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e71b6c8f6..777818083 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to - 🐛(backend) accept CDFV2 mimetype from newer libmagic - 🐛(backend) better transaction management on duplicate action +- 🐛(backend) clean storage files in clean_pending_items ### Removed diff --git a/src/backend/core/management/commands/clean_pending_items.py b/src/backend/core/management/commands/clean_pending_items.py index 2a2693a2d..8b6996a05 100644 --- a/src/backend/core/management/commands/clean_pending_items.py +++ b/src/backend/core/management/commands/clean_pending_items.py @@ -6,6 +6,7 @@ from django.utils import timezone from core.models import Item, ItemUploadStateChoices +from core.tasks.item import process_item_purge class Command(BaseCommand): @@ -33,7 +34,8 @@ def handle(self, *args, **options): count = 0 for item in items.iterator(): item.soft_delete() - item.delete() + item.hard_delete() + process_item_purge.delay(item.id) count += 1 self.stdout.write(f"Cleaned {count} stale pending item(s).") diff --git a/src/backend/core/tests/commands/test_clean_pending_items.py b/src/backend/core/tests/commands/test_clean_pending_items.py index aeb30c69c..5dd9a6b38 100644 --- a/src/backend/core/tests/commands/test_clean_pending_items.py +++ b/src/backend/core/tests/commands/test_clean_pending_items.py @@ -1,7 +1,9 @@ """Tests for the clean_pending_items management command.""" from datetime import timedelta +from io import BytesIO +from django.core.files.storage import default_storage from django.core.management import call_command from django.utils import timezone @@ -80,3 +82,20 @@ def test_clean_pending_items_custom_hours(): call_command("clean_pending_items", "--hours=8") assert not models.Item.objects.filter(pk=item.pk).exists() + + +def test_clean_pending_items_removes_orphan_file_from_storage(): + """Stale pending items must also have their storage file removed.""" + old_date = timezone.now() - timedelta(hours=49) + item = factories.ItemFactory( + type=models.ItemTypeChoices.FILE, + filename="pending.txt", + update_upload_state=models.ItemUploadStateChoices.PENDING, + ) + models.Item.objects.filter(pk=item.pk).update(created_at=old_date) + default_storage.save(item.file_key, BytesIO(b"orphan data")) + + call_command("clean_pending_items") + + assert not models.Item.objects.filter(pk=item.pk).exists() + assert not default_storage.exists(item.file_key)