An item keeps a parent that has stopped being a row #34

Closed
opened 2026-08-03 08:34:16 +02:00 by Claude · 1 comment
Collaborator

An item a rescan leaves alone keeps the ParentId it was filed with. When the
folder that column names stops being a row, the item goes with it and comes
back on the next scan.

Reproduced with a film dropped directly into a folder that until then only held
other folders:

/movies/A/B/Film 1 (2020)/Film 1 (2020).mkv    films on record: ["Film 1 (2020)"]
add /movies/A/B/Loose (2021).mkv               films on record: ["Loose"]
scan again                                     ["Film 1 (2020)", "Loose"]

B stops keeping a row of its own — the movies resolver files a folder only
while it holds no film — so remove_missing deletes it, and
FK_BaseItems_BaseItems_ParentId ON DELETE CASCADE takes Film 1 with it.
Film 1 is unchanged, so nothing rewrote its ParentId to the folder it now
belongs to.

The ancestor chain of an unchanged row is compared against what is on record
and filed again when it differs (crates/jellyfin-app/src/scan/run.rs). Its
ParentId is not: that column is only written when the row is. Whatever the
fix, it wants a test beside the ones in
crates/jellyfin-app/tests/scan_incremental.rs.

The item does come back, so this is a library that is briefly wrong rather than
one that stays wrong — unlike [#33].

An item a rescan leaves alone keeps the `ParentId` it was filed with. When the folder that column names stops being a row, the item goes with it and comes back on the next scan. Reproduced with a film dropped directly into a folder that until then only held other folders: ``` /movies/A/B/Film 1 (2020)/Film 1 (2020).mkv films on record: ["Film 1 (2020)"] add /movies/A/B/Loose (2021).mkv films on record: ["Loose"] scan again ["Film 1 (2020)", "Loose"] ``` `B` stops keeping a row of its own — the movies resolver files a folder only while it holds no film — so `remove_missing` deletes it, and `FK_BaseItems_BaseItems_ParentId ON DELETE CASCADE` takes `Film 1` with it. `Film 1` is unchanged, so nothing rewrote its `ParentId` to the folder it now belongs to. The ancestor chain of an unchanged row is compared against what is on record and filed again when it differs (`crates/jellyfin-app/src/scan/run.rs`). Its `ParentId` is not: that column is only written when the row is. Whatever the fix, it wants a test beside the ones in `crates/jellyfin-app/tests/scan_incremental.rs`. The item does come back, so this is a library that is briefly wrong rather than one that stays wrong — unlike [#33].
Author
Collaborator

Fixed and merged.

What a row hangs under is on record now — Known carries its parent — and a
pass compares it by id rather than by path, so a folder that stopped being a row
and a folder whose id changed are both caught. The row is filed again under the
folder it now belongs to, rather than being taken with the old one by the
cascade and coming back on the next scan.

Comparing by id matters where two libraries file one path as two kinds; the
path alone would not tell them apart.

Settles: the scenario in the issue writes the row once and then nothing on every
later pass, including the variant where the film lands two levels up.

Fixed and merged. What a row hangs under is on record now — `Known` carries its parent — and a pass compares it by id rather than by path, so a folder that stopped being a row and a folder whose id changed are both caught. The row is filed again under the folder it now belongs to, rather than being taken with the old one by the cascade and coming back on the next scan. Comparing by id matters where two libraries file one path as two kinds; the path alone would not tell them apart. Settles: the scenario in the issue writes the row once and then nothing on every later pass, including the variant where the film lands two levels up.
Sign in to join this conversation.
No description provided.