diff options
| -rw-r--r-- | Jellyfin.Server/Migrations/Routines/20260115120000_FixIncorrectOwnerIdRelationships.cs | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/Jellyfin.Server/Migrations/Routines/20260115120000_FixIncorrectOwnerIdRelationships.cs b/Jellyfin.Server/Migrations/Routines/20260115120000_FixIncorrectOwnerIdRelationships.cs index 0baf261a2e..e34182fd5d 100644 --- a/Jellyfin.Server/Migrations/Routines/20260115120000_FixIncorrectOwnerIdRelationships.cs +++ b/Jellyfin.Server/Migrations/Routines/20260115120000_FixIncorrectOwnerIdRelationships.cs @@ -136,19 +136,38 @@ public class FixIncorrectOwnerIdRelationships : IAsyncMigrationRoutine if (allIdsToDelete.Count > 0) { - // Batch-resolve items for metadata path cleanup, then delete all at once - var itemsToDelete = allIdsToDelete - .Select(id => _libraryManager.GetItemById(id)) - .Where(item => item is not null) - .ToList(); - _libraryManager.DeleteItemsUnsafeFast(itemsToDelete!); - - // Fall back to direct DB deletion for any items that couldn't be resolved via LibraryManager - var deletedIds = itemsToDelete.Select(i => i!.Id).ToHashSet(); - var unresolvedIds = allIdsToDelete.Where(id => !deletedIds.Contains(id)).ToList(); - if (unresolvedIds.Count > 0) + _logger.LogInformation("Deleting {Count} duplicate database entries...", allIdsToDelete.Count); + + // Delete in batches so progress is visible (item resolution and deletion can take a + // long time on large libraries) and so we never issue one massive delete transaction. + const int deleteBatchSize = 500; + var deletedSoFar = 0; + for (var offset = 0; offset < allIdsToDelete.Count; offset += deleteBatchSize) { - _persistenceService.DeleteItem(unresolvedIds); + cancellationToken.ThrowIfCancellationRequested(); + + var batchIds = allIdsToDelete.GetRange(offset, Math.Min(deleteBatchSize, allIdsToDelete.Count - offset)); + + // Resolve items for metadata path cleanup, then delete this batch + var itemsToDelete = batchIds + .Select(id => _libraryManager.GetItemById(id)) + .Where(item => item is not null) + .ToList(); + if (itemsToDelete.Count > 0) + { + _libraryManager.DeleteItemsUnsafeFast(itemsToDelete!); + } + + // Fall back to direct DB deletion for any items that couldn't be resolved via LibraryManager + var deletedIds = itemsToDelete.Select(i => i!.Id).ToHashSet(); + var unresolvedIds = batchIds.Where(id => !deletedIds.Contains(id)).ToList(); + if (unresolvedIds.Count > 0) + { + _persistenceService.DeleteItem(unresolvedIds); + } + + deletedSoFar += batchIds.Count; + _logger.LogInformation("Deleting duplicates: {Deleted}/{Total} items", deletedSoFar, allIdsToDelete.Count); } } |
