< Summary - Jellyfin

Information
Class: Jellyfin.Server.Migrations.Routines.FixAudioData
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/FixAudioData.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 43
Coverable lines: 43
Total lines: 106
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
get_Id()100%210%
get_Name()100%210%
get_PerformOnNewInstall()100%210%
Perform()0%7280%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/FixAudioData.cs

#LineLine coverage
 1using System;
 2using System.Globalization;
 3using System.IO;
 4using System.Linq;
 5using System.Threading;
 6using Jellyfin.Data.Enums;
 7using MediaBrowser.Controller;
 8using MediaBrowser.Controller.Entities;
 9using MediaBrowser.Controller.Entities.Audio;
 10using MediaBrowser.Controller.Persistence;
 11using MediaBrowser.Model.Entities;
 12using Microsoft.Extensions.Logging;
 13
 14namespace Jellyfin.Server.Migrations.Routines
 15{
 16    /// <summary>
 17    /// Fixes the data column of audio types to be deserializable.
 18    /// </summary>
 19    internal class FixAudioData : IMigrationRoutine
 20    {
 21        private const string DbFilename = "library.db";
 22        private readonly ILogger<FixAudioData> _logger;
 23        private readonly IServerApplicationPaths _applicationPaths;
 24        private readonly IItemRepository _itemRepository;
 25
 26        public FixAudioData(
 27            IServerApplicationPaths applicationPaths,
 28            ILoggerFactory loggerFactory,
 29            IItemRepository itemRepository)
 30        {
 031            _applicationPaths = applicationPaths;
 032            _itemRepository = itemRepository;
 033            _logger = loggerFactory.CreateLogger<FixAudioData>();
 034        }
 35
 36        /// <inheritdoc/>
 037        public Guid Id => Guid.Parse("{CF6FABC2-9FBE-4933-84A5-FFE52EF22A58}");
 38
 39        /// <inheritdoc/>
 040        public string Name => "FixAudioData";
 41
 42        /// <inheritdoc/>
 043        public bool PerformOnNewInstall => false;
 44
 45        /// <inheritdoc/>
 46        public void Perform()
 47        {
 048            var dbPath = Path.Combine(_applicationPaths.DataPath, DbFilename);
 49
 50            // Back up the database before modifying any entries
 051            for (int i = 1; ; i++)
 52            {
 053                var bakPath = string.Format(CultureInfo.InvariantCulture, "{0}.bak{1}", dbPath, i);
 054                if (!File.Exists(bakPath))
 55                {
 56                    try
 57                    {
 058                        _logger.LogInformation("Backing up {Library} to {BackupPath}", DbFilename, bakPath);
 059                        File.Copy(dbPath, bakPath);
 060                        _logger.LogInformation("{Library} backed up to {BackupPath}", DbFilename, bakPath);
 061                        break;
 62                    }
 063                    catch (Exception ex)
 64                    {
 065                        _logger.LogError(ex, "Cannot make a backup of {Library} at path {BackupPath}", DbFilename, bakPa
 066                        throw;
 67                    }
 68                }
 69            }
 70
 071            _logger.LogInformation("Backfilling audio lyrics data to database.");
 072            var startIndex = 0;
 073            var records = _itemRepository.GetCount(new InternalItemsQuery
 074            {
 075                IncludeItemTypes = [BaseItemKind.Audio],
 076            });
 77
 078            while (startIndex < records)
 79            {
 080                var results = _itemRepository.GetItemList(new InternalItemsQuery
 081                {
 082                    IncludeItemTypes = [BaseItemKind.Audio],
 083                    StartIndex = startIndex,
 084                    Limit = 5000,
 085                    SkipDeserialization = true
 086                })
 087                .Cast<Audio>()
 088                .ToList();
 89
 090                foreach (var audio in results)
 91                {
 092                    var lyricMediaStreams = audio.GetMediaStreams().Where(s => s.Type == MediaStreamType.Lyric).Select(s
 093                    if (lyricMediaStreams.Count > 0)
 94                    {
 095                        audio.HasLyrics = true;
 096                        audio.LyricFiles = lyricMediaStreams;
 97                    }
 98                }
 99
 0100                _itemRepository.SaveItems(results, CancellationToken.None);
 0101                startIndex += results.Count;
 0102                _logger.LogInformation("Backfilled data for {UpdatedRecords} of {TotalRecords} audio records", startInde
 103            }
 0104        }
 105    }
 106}