浏览代码

close inactive sessions after 10 minutes

herby2212 2 年之前
父节点
当前提交
8bb44b85d7
共有 2 个文件被更改,包括 76 次插入4 次删除
  1. 70 4
      Emby.Server.Implementations/Session/SessionManager.cs
  2. 6 0
      MediaBrowser.Controller/Session/SessionInfo.cs

+ 70 - 4
Emby.Server.Implementations/Session/SessionManager.cs

@@ -63,6 +63,9 @@ namespace Emby.Server.Implementations.Session
         private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = new(StringComparer.OrdinalIgnoreCase);
 
         private Timer _idleTimer;
+        private Timer _inactiveTimer;
+
+        private int inactiveMinutesThreshold = 10;
 
         private DtoOptions _itemInfoDtoOptions;
         private bool _disposed = false;
@@ -171,9 +174,11 @@ namespace Emby.Server.Implementations.Session
             if (disposing)
             {
                 _idleTimer?.Dispose();
+                _inactiveTimer?.Dispose();
             }
 
             _idleTimer = null;
+            _inactiveTimer = null;
 
             _deviceManager.DeviceOptionsUpdated -= OnDeviceManagerDeviceOptionsUpdated;
 
@@ -397,6 +402,15 @@ namespace Emby.Server.Implementations.Session
                 session.LastPlaybackCheckIn = DateTime.UtcNow;
             }
 
+            if (info.IsPaused && session.LastPausedDate.HasValue == false)
+            {
+                session.LastPausedDate = DateTime.UtcNow;
+            }
+            else if (!info.IsPaused)
+            {
+                session.LastPausedDate = null;
+            }
+
             session.PlayState.IsPaused = info.IsPaused;
             session.PlayState.PositionTicks = info.PositionTicks;
             session.PlayState.MediaSourceId = info.MediaSourceId;
@@ -564,9 +578,10 @@ namespace Emby.Server.Implementations.Session
             return users;
         }
 
-        private void StartIdleCheckTimer()
+        private void StartCheckTimers()
         {
             _idleTimer ??= new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+            _inactiveTimer ??= new Timer(CheckForInactiveSteams, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
         }
 
         private void StopIdleCheckTimer()
@@ -578,6 +593,15 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
+        private void StopInactiveCheckTimer()
+        {
+            if (_inactiveTimer is not null)
+            {
+                _inactiveTimer.Dispose();
+                _inactiveTimer = null;
+            }
+        }
+
         private async void CheckForIdlePlayback(object state)
         {
             var playingSessions = Sessions.Where(i => i.NowPlayingItem is not null)
@@ -613,10 +637,52 @@ namespace Emby.Server.Implementations.Session
                 playingSessions = Sessions.Where(i => i.NowPlayingItem is not null)
                     .ToList();
             }
+            else
+            {
+                StopIdleCheckTimer();
+            }
+        }
+
+        private async void CheckForInactiveSteams(object state)
+        {
+            var pausedSessions = Sessions.Where(i =>
+                (i.NowPlayingItem is not null) &&
+                (i.PlayState.IsPaused == true) &&
+                (i.LastPausedDate is not null)).ToList();
 
+            if (pausedSessions.Count > 0)
+            {
+                var inactiveSessions = Sessions.Where(i => (DateTime.UtcNow - i.LastPausedDate).Value.TotalMinutes > inactiveMinutesThreshold).ToList();
+
+                foreach (var session in inactiveSessions)
+                {
+                    _logger.LogDebug("Session {0} has been inactive for {1} minutes. Stopping it.", session.Id, inactiveMinutesThreshold);
+
+                    try
+                    {
+                        await SendPlaystateCommand(
+                            session.Id,
+                            session.Id,
+                            new PlaystateRequest()
+                            {
+                                Command = PlaystateCommand.Stop,
+                                ControllingUserId = session.UserId.ToString(),
+                                SeekPositionTicks = session.PlayState?.PositionTicks
+                            },
+                            CancellationToken.None).ConfigureAwait(true);
+                    }
+                    catch (Exception ex)
+                    {
+                        _logger.LogDebug(ex, "Error calling SendPlaystateCommand for stopping inactive session {0}.", session.Id);
+                    }
+                }
+            }
+
+            var playingSessions = Sessions.Where(i => i.NowPlayingItem is not null)
+                .ToList();
             if (playingSessions.Count == 0)
             {
-                StopIdleCheckTimer();
+                StopInactiveCheckTimer();
             }
         }
 
@@ -696,7 +762,7 @@ namespace Emby.Server.Implementations.Session
                 eventArgs,
                 _logger);
 
-            StartIdleCheckTimer();
+            StartCheckTimers();
         }
 
         /// <summary>
@@ -790,7 +856,7 @@ namespace Emby.Server.Implementations.Session
                 session.StartAutomaticProgress(info);
             }
 
-            StartIdleCheckTimer();
+            StartCheckTimers();
         }
 
         private void OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info)

+ 6 - 0
MediaBrowser.Controller/Session/SessionInfo.cs

@@ -109,6 +109,12 @@ namespace MediaBrowser.Controller.Session
         /// <value>The last playback check in.</value>
         public DateTime LastPlaybackCheckIn { get; set; }
 
+        /// <summary>
+        /// Gets or sets the last paused date.
+        /// </summary>
+        /// <value>The last paused date.</value>
+        public DateTime? LastPausedDate { get; set; }
+
         /// <summary>
         /// Gets or sets the name of the device.
         /// </summary>