aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs
blob: 361656ff2fae72429c57f43bb40b62d1b371d418 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Threading;
using Microsoft.Extensions.Logging;

namespace Emby.Server.Implementations.EntryPoints
{
    public class AutomaticRestartEntryPoint : IServerEntryPoint
    {
        private readonly IServerApplicationHost _appHost;
        private readonly ILogger _logger;
        private readonly ITaskManager _iTaskManager;
        private readonly ISessionManager _sessionManager;
        private readonly IServerConfigurationManager _config;
        private readonly ILiveTvManager _liveTvManager;
        private readonly ITimerFactory _timerFactory;

        private ITimer _timer;

        public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager, ITimerFactory timerFactory)
        {
            _appHost = appHost;
            _logger = logger;
            _iTaskManager = iTaskManager;
            _sessionManager = sessionManager;
            _config = config;
            _liveTvManager = liveTvManager;
            _timerFactory = timerFactory;
        }

        public Task RunAsync()
        {
            if (_appHost.CanSelfRestart)
            {
                _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
            }

            return Task.CompletedTask;
        }

        void _appHost_HasPendingRestartChanged(object sender, EventArgs e)
        {
            DisposeTimer();

            if (_appHost.HasPendingRestart)
            {
                _timer = _timerFactory.Create(TimerCallback, null, TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15));
            }
        }

        private async void TimerCallback(object state)
        {
            if (_config.Configuration.EnableAutomaticRestart)
            {
                var isIdle = await IsIdle().ConfigureAwait(false);

                if (isIdle)
                {
                    DisposeTimer();

                    _logger.LogInformation("Automatically restarting the system because it is idle and a restart is required.");

                    try
                    {
                        _appHost.Restart();
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error restarting server");
                    }
                }
            }
        }

        private async Task<bool> IsIdle()
        {
            if (_iTaskManager.ScheduledTasks.Any(i => i.State != TaskState.Idle))
            {
                return false;
            }

            if (_liveTvManager.Services.Count == 1)
            {
                try
                {
                    var timers = await _liveTvManager.GetTimers(new TimerQuery(), CancellationToken.None).ConfigureAwait(false);
                    if (timers.Items.Any(i => i.Status == RecordingStatus.InProgress))
                    {
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error getting timers");
                }
            }

            var now = DateTime.UtcNow;

            return !_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 30);
        }

        public void Dispose()
        {
            _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged;

            DisposeTimer();
        }

        private void DisposeTimer()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }
        }
    }
}