Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion src/backend/core/management/commands/clean_pending_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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).")
19 changes: 19 additions & 0 deletions src/backend/core/tests/commands/test_clean_pending_items.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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)