aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations/Item/PeopleRepository.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Server.Implementations/Item/PeopleRepository.cs')
-rw-r--r--Jellyfin.Server.Implementations/Item/PeopleRepository.cs32
1 files changed, 32 insertions, 0 deletions
diff --git a/Jellyfin.Server.Implementations/Item/PeopleRepository.cs b/Jellyfin.Server.Implementations/Item/PeopleRepository.cs
index aaa363b046..da2ad033ec 100644
--- a/Jellyfin.Server.Implementations/Item/PeopleRepository.cs
+++ b/Jellyfin.Server.Implementations/Item/PeopleRepository.cs
@@ -194,13 +194,45 @@ public class PeopleRepository(IDbContextFactory<JellyfinDbContext> dbProvider, I
listOrder++;
}
+ var droppedCredits = existingMaps.Select(e => e.PeopleId).Distinct().ToArray();
context.PeopleBaseItemMap.RemoveRange(existingMaps);
context.SaveChanges();
+
+ // Nothing else ever deletes a credit row, so one left without a single mapping outlives the
+ // credit it stood for: it keeps a person of that name off the dead-person sweep, which only
+ // sees items no credit names, and keeps the name in every by-name list. That is how a credit
+ // a provider dropped, or one a broken provider result invented, becomes impossible to clean up.
+ DeleteCreditsWithoutMapping(context, droppedCredits);
+
+ context.SaveChanges();
transaction.Commit();
}
/// <inheritdoc/>
+ public int DeleteOrphanedCredits()
+ {
+ using var context = _dbProvider.CreateDbContext();
+
+ return DeleteCreditsWithoutMapping(context, null);
+ }
+
+ // A null candidate list sweeps every credit, anything else only the ones just unmapped.
+ private int DeleteCreditsWithoutMapping(JellyfinDbContext context, IReadOnlyList<Guid>? candidates)
+ {
+ if (candidates is not null && candidates.Count == 0)
+ {
+ return 0;
+ }
+
+ var credits = candidates is null
+ ? context.Peoples.AsQueryable()
+ : context.Peoples.WhereOneOrMany(candidates, e => e.Id);
+
+ return credits.Where(e => !context.PeopleBaseItemMap.Any(f => f.PeopleId == e.Id)).ExecuteDelete();
+ }
+
+ /// <inheritdoc/>
public IReadOnlyDictionary<Guid, IReadOnlyList<string>> GetPeopleNamesByItems(IReadOnlyList<Guid> itemIds, IReadOnlyList<string> personTypes)
{
using var context = _dbProvider.CreateDbContext();