Dealing with moved files

I’m working on a script to sync scenes between Whisparr and Stash. The goal is to inform Whisparr of any scenes with a StashDB stash-id and trigger a manual import (so basically Stasharr in reverse). The end result should be that Whisparr knows about files you obtained elsewhere, making it easier for tools like Stasharr to show the right status about a scene’s availability (so you don’t reacquire something you already have).

I’ve got the bulk of this working well, but the last step is dealing with the file entries. Whisparr moves the files to its own folder structure after the import, and I need to tell Stash about it. I’m able to trigger a scan in the new location to get the new file, but scanning the old location doesn’t remove the stale file. Neither does triggering a clean on that path (which I’d like to avoid anyway because of the potential for metadata destruction).

I’ll build this into a proper plugin eventually, but right now I’m building it as a CLI application using the graphql API. What’s the best way to tell Stash that the old file has gone away without risking data loss (particularly since sometimes Whisparr’s file move fails, and I don’t want to remove a file that still exists)?

I’ll add that triggering a clean from the UI does remove the file appropriately. Just not using a metadataClean() mutation.

If you scan both old and new locations, or scan your whole library, it will work

I tried that and it didn’t work, but there are a few possible explanations depending on how that functionality works.

  • Does finding the old and new have to happen in the same scan?
    • If so, do they need to be on the same subpath? (e.g. if I list multiple paths in the scan request, do they have to both be under the same one?)
    • Does it need to be the first time it saw both locations since the move?
  • If they don’t have to be the same scan, does order matter?
    • I could see it not recognizing the move if the old location is scanned first
  • Can it work if the locations have already been scanned post-move without triggering the consolidation logic?
    • If I have a file with two file paths, one of which doesn’t exist, is it expected that scanning the non-existent path will remove the file entry? In practice this didn’t seem to work.
  • Does “rescan files” need to be enabled?
  • Does it work for graphql triggered scans as well as UI ones?

If it has to be discovered on the same scan, that poses a potential problem. When Whisparr does the manual import, it can trigger a scan of the new location (but not the old). This is generally desirable for files Whisparr manages, but could cause the new location to be scanned before I get an opportunity to scan the old location.

I think my ideal behavior would be that a file entry would be removed during a scan if it is found that both:

  • The file doesn’t exist on disk
  • The scene that references it has other files that do exist on disk

This would ensure that scans remain non-destructive but also the order in which things get scanned wouldn’t be as relevant (especially if that check is performed when file entries are added to a scene as well).

If that behavior isn’t considered desirable for scans, then a “safe clean” operation would be nice to have.