< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.ScheduledTasks.Tasks.PluginUpdateTask
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
Line coverage
51%
Covered lines: 25
Uncovered lines: 24
Coverable lines: 49
Total lines: 124
Line coverage: 51%
Branch coverage
25%
Covered branches: 1
Total branches: 4
Branch coverage: 25%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 1/23/2026 - 12:11:06 AM Line coverage: 63.6% (7/11) Total lines: 1244/19/2026 - 12:14:27 AM Line coverage: 51% (25/49) Branch coverage: 25% (1/4) Total lines: 124 4/19/2026 - 12:14:27 AM Line coverage: 51% (25/49) Branch coverage: 25% (1/4) Total lines: 124

Coverage delta

Coverage delta 13 -13

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Name()100%11100%
get_Description()100%210%
get_Category()100%210%
get_Key()100%11100%
get_IsHidden()100%210%
get_IsEnabled()100%11100%
get_IsLogged()100%210%
GetDefaultTriggers()100%11100%
ExecuteAsync()25%10428.57%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using System.Net.Http;
 6using System.Threading;
 7using System.Threading.Tasks;
 8using MediaBrowser.Common.Updates;
 9using MediaBrowser.Model.Globalization;
 10using MediaBrowser.Model.Tasks;
 11using Microsoft.Extensions.Logging;
 12
 13namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
 14
 15/// <summary>
 16/// Plugin Update Task.
 17/// </summary>
 18public class PluginUpdateTask : IScheduledTask, IConfigurableScheduledTask
 19{
 20    private readonly ILogger<PluginUpdateTask> _logger;
 21
 22    private readonly IInstallationManager _installationManager;
 23    private readonly ILocalizationManager _localization;
 24
 25    /// <summary>
 26    /// Initializes a new instance of the <see cref="PluginUpdateTask" /> class.
 27    /// </summary>
 28    /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
 29    /// <param name="installationManager">Instance of the <see cref="IInstallationManager"/> interface.</param>
 30    /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
 31    public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager, ILocalizationMan
 32    {
 2133        _logger = logger;
 2134        _installationManager = installationManager;
 2135        _localization = localization;
 2136    }
 37
 38    /// <inheritdoc />
 5839    public string Name => _localization.GetLocalizedString("TaskUpdatePlugins");
 40
 41    /// <inheritdoc />
 042    public string Description => _localization.GetLocalizedString("TaskUpdatePluginsDescription");
 43
 44    /// <inheritdoc />
 045    public string Category => _localization.GetLocalizedString("TasksApplicationCategory");
 46
 47    /// <inheritdoc />
 348    public string Key => "PluginUpdates";
 49
 50    /// <inheritdoc />
 051    public bool IsHidden => false;
 52
 53    /// <inheritdoc />
 254    public bool IsEnabled => true;
 55
 56    /// <inheritdoc />
 057    public bool IsLogged => true;
 58
 59    /// <inheritdoc />
 60    public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
 61    {
 2162        yield return new TaskTriggerInfo
 2163        {
 2164            Type = TaskTriggerInfoType.StartupTrigger
 2165        };
 66
 2167        yield return new TaskTriggerInfo
 2168        {
 2169            Type = TaskTriggerInfoType.IntervalTrigger,
 2170            IntervalTicks = TimeSpan.FromHours(24).Ticks
 2171        };
 2172    }
 73
 74    /// <inheritdoc />
 75    public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
 76    {
 277        progress.Report(0);
 78
 279        var packageFetchTask = _installationManager.GetAvailablePluginUpdates(cancellationToken);
 280        var packagesToInstall = (await packageFetchTask.ConfigureAwait(false)).ToList();
 81
 182        progress.Report(10);
 83
 184        var numComplete = 0;
 85
 286        foreach (var package in packagesToInstall)
 87        {
 088            cancellationToken.ThrowIfCancellationRequested();
 89
 90            try
 91            {
 092                await _installationManager.InstallPackage(package, cancellationToken).ConfigureAwait(false);
 093            }
 094            catch (OperationCanceledException)
 95            {
 96                // InstallPackage has its own inner cancellation token, so only throw this if it's ours
 097                if (cancellationToken.IsCancellationRequested)
 98                {
 099                    throw;
 100                }
 0101            }
 0102            catch (HttpRequestException ex)
 103            {
 0104                _logger.LogError(ex, "Error downloading {Name}", package.Name);
 0105            }
 0106            catch (IOException ex)
 107            {
 0108                _logger.LogError(ex, "Error updating {Name}", package.Name);
 0109            }
 0110            catch (InvalidDataException ex)
 111            {
 0112                _logger.LogError(ex, "Error updating {Name}", package.Name);
 0113            }
 114
 115            // Update progress
 0116            lock (progress)
 117            {
 0118                progress.Report((90.0 * ++numComplete / packagesToInstall.Count) + 10);
 0119            }
 0120        }
 121
 1122        progress.Report(100);
 1123    }
 124}