aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations
diff options
context:
space:
mode:
authorCody Robibero <cody@robibe.ro>2026-09-06 07:34:30 -0400
committerGitHub <noreply@github.com>2026-09-06 07:34:30 -0400
commitedb6cd11da0c3772ff897757a8364b309e6f7e1a (patch)
tree939047416b59c5f69722c0190c098b8b1ee70017 /Jellyfin.Server.Implementations
parent63553803b19446ea9b5cb9b335015ab8727a3799 (diff)
parenta0a42c630ef724fa92b61b261eab8132cb3116d7 (diff)
Merge branch 'master' into fix-code-migration
Diffstat (limited to 'Jellyfin.Server.Implementations')
-rw-r--r--Jellyfin.Server.Implementations/Item/ItemPersistenceService.cs29
1 files changed, 20 insertions, 9 deletions
diff --git a/Jellyfin.Server.Implementations/Item/ItemPersistenceService.cs b/Jellyfin.Server.Implementations/Item/ItemPersistenceService.cs
index efff3457a3..c8672e189b 100644
--- a/Jellyfin.Server.Implementations/Item/ItemPersistenceService.cs
+++ b/Jellyfin.Server.Implementations/Item/ItemPersistenceService.cs
@@ -176,14 +176,6 @@ public class ItemPersistenceService : IItemPersistenceService
var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
await using (context.ConfigureAwait(false))
{
- if (!await context.BaseItems
- .AnyAsync(bi => bi.Id == item.Id, cancellationToken)
- .ConfigureAwait(false))
- {
- _logger.LogWarning("Unable to save ImageInfo for non existing BaseItem");
- return;
- }
-
await context.BaseItemImageInfos
.Where(e => e.ItemId == item.Id)
.ExecuteDeleteAsync(cancellationToken)
@@ -193,7 +185,26 @@ public class ItemPersistenceService : IItemPersistenceService
.AddRangeAsync(images, cancellationToken)
.ConfigureAwait(false);
- await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
+ try
+ {
+ await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
+ }
+ catch (DbUpdateException)
+ {
+ // Checking that the item exists before writing leaves a gap a scan can delete it
+ // through, turning the insert into a foreign key violation that fails the whole
+ // refresh instead of the no-op intended here. Let the insert be the check: it is the
+ // only point at which the answer cannot go stale. Nothing is orphaned by the delete
+ // above, because deleting the item cascades to its images anyway.
+ if (await context.BaseItems
+ .AnyAsync(bi => bi.Id == item.Id, cancellationToken)
+ .ConfigureAwait(false))
+ {
+ throw;
+ }
+
+ _logger.LogWarning("Unable to save ImageInfo for non existing BaseItem {ItemId}", item.Id);
+ }
}
}