Skip to content

Backfill legacy sound filenames with a resumable command (#991) - #992

Open
vjpixel wants to merge 1 commit into
feature/699-uuid-media-filenamesfrom
feature/991-backfill-sound-names
Open

vjpixel wants to merge 1 commit into
feature/699-uuid-media-filenamesfrom
feature/991-backfill-sound-names

Conversation

@vjpixel

@vjpixel vjpixel commented Sep 17, 2026

Copy link
Copy Markdown
Member

Description

#982 makes new sound uploads land at sounds/<uuid>.<ext>. This handles the rows that predate it, which still point at files stored under the name their uploader chose — the ones actually exposed today.

#699 asked for a data migration and I'd recommend against it: a migration renames live S3 objects inside a deploy, cannot be resumed after a partial run, and gives no way to see what would change before it changes. python manage.py backfill_sound_filenames instead.

Based on feature/699-uuid-media-filenames, not develop — it reuses the sound_file_path helper that #982 introduces, so backfilled names match new ones instead of reimplementing the pattern. Retarget to develop once #982 lands.

Resolves (Issues)

Closes #991

How it behaves

  • Idempotent, so resuming an interrupted run is just running it again: rows already matching sounds/<32 hex>[.ext] are skipped, and a clean run reports "Nothing to do".
  • Ordered for safety — write the new object, update the row, then delete the old one. Interrupted at any point, the worst outcome is an orphaned old file, never a row pointing at a key that no longer exists.
  • --dry-run lists every old -> new without touching storage or the database.
  • --limit N so the first batch can be small and inspected.
  • Per-row error isolation: an unreadable or unwritable object is logged with its key, reported on stderr, and the rest of the batch still completes. That is the main reason to prefer a command here — a migration would abort with no record of how far it got.
  • Backfills file_name_original from the old key when it's empty, so the original name is preserved as Save media content with random names #699 asks. Rows that already have it are left alone.

General tasks performed

  • Added src/core/management/commands/backfill_sound_filenames.py.
  • Added src/core/tests/test_backfill_sound_filenames.py — 8 tests: the rename itself, content surviving the move, the old object being removed, file_name_original preserved, a second run being a no-op, --dry-run changing nothing, --limit stopping early, and one failing row not aborting the batch.

Before running it in production

This moves live files, so it wants a human deciding when: rehearse with --dry-run, then a small --limit batch, then the rest in a quiet window. Nothing here schedules itself.

Verification: full suite pytest src/core src/users src/blog passes — 285 passed. ruff format --diff src/ clean, zero I001, no pending migrations.

Have you confirmed the application builds locally without error? See here.

  • Yes

🤖 Generated with Claude Code

https://claude.ai/code/session_01HXUw7kyELDu8ycGQxtaFbb


Generated by Claude Code

#982 makes new uploads land at sounds/<uuid>.<ext>, but the rows that
predate it still point at files stored under the name their uploader chose —
which are the ones actually exposed.

#699 asked for a data migration. This is a management command instead: a
migration renames live S3 objects inside a deploy, cannot be resumed after a
partial run, and offers no way to see what would change first.

The command is idempotent, so resuming is just running it again. It writes
the new object, points the row at it, then deletes the old one, so an
interruption leaves an orphan rather than a row pointing at nothing. It
takes --dry-run and --limit, backfills file_name_original when empty, and
isolates per-row failures so one unreadable object cannot abort the batch.

Closes #991

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXUw7kyELDu8ycGQxtaFbb

This branch has not been deployed

No deployments
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.

2 participants