Skip to content

Delete stale generated files on same-path content change instead of renaming - #7158

Open
lurkfueh wants to merge 2 commits into
stashapp:developfrom
lurkfueh:fix/stale-generated-files-on-rescan
Open

Delete stale generated files on same-path content change instead of renaming#7158
lurkfueh wants to merge 2 commits into
stashapp:developfrom
lurkfueh:fix/stale-generated-files-on-rescan

Conversation

@lurkfueh

@lurkfueh lurkfueh commented Aug 14, 2026

Copy link
Copy Markdown

Description

Deletes generated content when a file is modified (i.e. trimmed) but the file path remains the same. Also modifies the UI scene player to track media fingerprint instead of just scene id when deciding to update the player.

Related Issue

Fixes #7155

Testing

  • built the executable in wsl and tested the changes I made on windows
  • Confirmed that generated content is deleted after file modification and rescan
  • Confirmed that after a refetch, the player will pick up changes to rescanned file
  • Added tests to pkg/scene/scan_test.go covering my changes

Screenshots

Checklist

  • I have read and understood the Contributing document.
  • I have read and understood the AI Usage Policy document.
  • I have made corresponding changes to the documentation (if applicable).

AI Usage Disclosure

  • I have used AI tools to assist with this pull request, and I have disclosed the tools and how I used them below.
    used claude to make the code changes, tested and verified that the changes work

Additional Context

Note, this does not touch transcodes (I think they should be removed also but want to hear from maintainers)

…enaming

When a scene's file changes at the same path, the scan handler called
MigrateHash, which renames the old hash's sprite/preview/transcode files
onto the new hash's path instead of regenerating them. Every generator's
"does this already exist" check then found a file already sitting there
and skipped, leaving stale pre-edit content wearing the new hash's name -
and the cover (a DB blob, never touched by MigrateHash) stayed stale too.

Add InvalidateGeneratedFiles, used only for the same-path content-change
case: deletes the old hash's generated files instead of renaming them,
and clears the scene's cover. MigrateHash itself is unchanged and still
renames for its real use case (the hash-naming-algorithm migration task,
where content is unchanged). With the stale files/cover actually gone,
every generator's existing exists-check works correctly on its own for
any future regeneration path - scan, manual Generate, or scheduled.

Also fixes ScenePlayer never refreshing a scene's video source/duration
after such an edit: its player-(re)init effect only fired on scene ID
change, so an in-place file edit under the same scene ID left the player
showing the pre-edit duration/sources indefinitely.

Fixes stashapp#7155

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@lurkfueh
lurkfueh marked this pull request as ready for review August 14, 2026 07:33

@Gykes Gykes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a quick pass through. No actual testing was done.

Comment thread pkg/scene/scan.go
// so stale content doesn't pass as valid for the new content
InvalidateGeneratedFiles(h.Paths, oldHash)

for _, s := range existing {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about secondary files? I think this would clear for every scene even if it's the secondary file that gets modified, is that expected? I think this should be guarded to the primary file only, no?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could I get more context on what secondary files are or a pointer to what file to start at?

Comment thread pkg/scene/migrate_hash.go
// where the old hash's generated files are no longer valid and should be
// deleted rather than renamed onto the new hash.
func InvalidateGeneratedFiles(p *paths.Paths, hash string) {
removeSceneFolder(filepath.Join(p.Generated.Markers, hash))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not essentially the same as line 67?

Comment thread pkg/scene/migrate_hash.go
scenePaths := p.Scene
removeSceneFile(scenePaths.GetVideoPreviewPath(hash))
removeSceneFile(scenePaths.GetWebpPreviewPath(hash))
removeSceneFile(scenePaths.GetTranscodePath(hash))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes transcodes but your PR description said you're not touching them yet.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad, but do we want to remove them? I think they should be removed since they would now differ from the source.

// scene id changing, and still needs new sources/duration pushed
// into the player
if (!file) return;
const fingerprint = getFileFingerprint(file.fingerprints);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to join all fingerprint types. I would think if one gets added (phash, MD5) the next scene refetch would throw the viewer back to the resume position. I would compare only types present in both or key off the file id + size + mod time

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.

Stale sprite/preview/cover/transcode after a same path file content change

2 participants