2
0
Эх сурвалжийг харах

Make migration handle parent cleanup (#14817)

* Make migration handle parent cleanup

* Remove speed improvement

* Update MigrateLibraryDb.cs
JPVenson 4 өдөр өмнө
parent
commit
0949212993

+ 44 - 4
Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs

@@ -99,6 +99,7 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine
         var baseItemIds = new HashSet<Guid>();
         using (var operation = GetPreparedDbContext("Moving TypedBaseItem"))
         {
+            IDictionary<Guid, (BaseItemEntity BaseItem, string[] Keys)> allItemsLookup = new Dictionary<Guid, (BaseItemEntity BaseItem, string[] Keys)>();
             const string typedBaseItemsQuery =
             """
             SELECT guid, type, data, StartDate, EndDate, ChannelId, IsMovie,
@@ -115,12 +116,49 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine
                 foreach (SqliteDataReader dto in connection.Query(typedBaseItemsQuery))
                 {
                     var baseItem = GetItem(dto);
-                    operation.JellyfinDbContext.BaseItems.Add(baseItem.BaseItem);
-                    baseItemIds.Add(baseItem.BaseItem.Id);
-                    foreach (var dataKey in baseItem.LegacyUserDataKey)
+                    allItemsLookup.Add(baseItem.BaseItem.Id, baseItem);
+                }
+            }
+
+            bool DoesResolve(Guid? parentId, HashSet<(BaseItemEntity BaseItem, string[] Keys)> checkStack)
+            {
+                if (parentId is null)
+                {
+                    return true;
+                }
+
+                if (!allItemsLookup.TryGetValue(parentId.Value, out var parent))
+                {
+                    return false; // item is detached and has no root anymore.
+                }
+
+                if (!checkStack.Add(parent))
+                {
+                    return false; // recursive structure. Abort.
+                }
+
+                return DoesResolve(parent.BaseItem.ParentId, checkStack);
+            }
+
+            using (new TrackedMigrationStep("Clean TypedBaseItems hierarchy", _logger))
+            {
+                var checkStack = new HashSet<(BaseItemEntity BaseItem, string[] Keys)>();
+
+                foreach (var item in allItemsLookup)
+                {
+                    var cachedItem = item.Value;
+                    if (DoesResolve(cachedItem.BaseItem.ParentId, checkStack))
                     {
-                        legacyBaseItemWithUserKeys[dataKey] = baseItem.BaseItem;
+                        checkStack.Add(cachedItem);
+                        operation.JellyfinDbContext.BaseItems.Add(cachedItem.BaseItem);
+                        baseItemIds.Add(cachedItem.BaseItem.Id);
+                        foreach (var dataKey in cachedItem.Keys)
+                        {
+                            legacyBaseItemWithUserKeys[dataKey] = cachedItem.BaseItem;
+                        }
                     }
+
+                    checkStack.Clear();
                 }
             }
 
@@ -128,6 +166,8 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine
             {
                 operation.JellyfinDbContext.SaveChanges();
             }
+
+            allItemsLookup.Clear();
         }
 
         using (var operation = GetPreparedDbContext("Moving ItemValues"))