Browse Source

added session disposal

Luke Pulverenti 11 years ago
parent
commit
e657a1cdab
1 changed files with 79 additions and 23 deletions
  1. 79 23
      MediaBrowser.Server.Implementations/Session/SessionManager.cs

+ 79 - 23
MediaBrowser.Server.Implementations/Session/SessionManager.cs

@@ -69,6 +69,8 @@ namespace MediaBrowser.Server.Implementations.Session
 
         private IEnumerable<ISessionControllerFactory> _sessionFactories = new List<ISessionControllerFactory>();
 
+        private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
+
         /// <summary>
         /// Initializes a new instance of the <see cref="SessionManager" /> class.
         /// </summary>
@@ -146,7 +148,7 @@ namespace MediaBrowser.Server.Implementations.Session
             var userId = user == null ? (Guid?)null : user.Id;
             var username = user == null ? null : user.Name;
 
-            var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, remoteEndPoint, userId, username);
+            var session = await GetSessionInfo(clientType, appVersion, deviceId, deviceName, remoteEndPoint, userId, username).ConfigureAwait(false);
 
             session.LastActivityDate = activityDate;
 
@@ -171,6 +173,46 @@ namespace MediaBrowser.Server.Implementations.Session
             return session;
         }
 
+        public async Task ReportSessionEnded(Guid sessionId)
+        {
+            var session = GetSession(sessionId);
+
+            if (session == null)
+            {
+                throw new ArgumentException("Session not found");
+            }
+
+            var key = GetSessionKey(session.Client, session.ApplicationVersion, session.DeviceId);
+
+            await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
+
+            try
+            {
+                SessionInfo removed;
+
+                if (_activeConnections.TryRemove(key, out removed))
+                {
+                    var disposable = removed.SessionController as IDisposable;
+
+                    if (disposable != null)
+                    {
+                        try
+                        {
+                            disposable.Dispose();
+                        }
+                        catch (Exception ex)
+                        {
+                            _logger.ErrorException("Error disposing session controller", ex);
+                        }
+                    }
+                }
+            }
+            finally
+            {
+                _sessionLock.Release();
+            }
+        }
+
         /// <summary>
         /// Updates the now playing item id.
         /// </summary>
@@ -207,6 +249,11 @@ namespace MediaBrowser.Server.Implementations.Session
             }
         }
 
+        private string GetSessionKey(string clientType, string appVersion, string deviceId)
+        {
+            return clientType + deviceId + appVersion;
+        }
+
         /// <summary>
         /// Gets the connection.
         /// </summary>
@@ -218,36 +265,45 @@ namespace MediaBrowser.Server.Implementations.Session
         /// <param name="userId">The user identifier.</param>
         /// <param name="username">The username.</param>
         /// <returns>SessionInfo.</returns>
-        private SessionInfo GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Guid? userId, string username)
+        private async Task<SessionInfo> GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Guid? userId, string username)
         {
-            var key = clientType + deviceId + appVersion;
+            var key = GetSessionKey(clientType, appVersion, deviceId);
+
+            await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
 
-            var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo
+            try
             {
-                Client = clientType,
-                DeviceId = deviceId,
-                ApplicationVersion = appVersion,
-                Id = Guid.NewGuid()
-            });
+                var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo
+                {
+                    Client = clientType,
+                    DeviceId = deviceId,
+                    ApplicationVersion = appVersion,
+                    Id = Guid.NewGuid()
+                });
 
-            connection.DeviceName = deviceName;
-            connection.UserId = userId;
-            connection.UserName = username;
-            connection.RemoteEndPoint = remoteEndPoint;
+                connection.DeviceName = deviceName;
+                connection.UserId = userId;
+                connection.UserName = username;
+                connection.RemoteEndPoint = remoteEndPoint;
 
-            if (!userId.HasValue)
-            {
-                connection.AdditionalUsers.Clear();
-            }
+                if (!userId.HasValue)
+                {
+                    connection.AdditionalUsers.Clear();
+                }
 
-            if (connection.SessionController == null)
+                if (connection.SessionController == null)
+                {
+                    connection.SessionController = _sessionFactories
+                        .Select(i => i.GetSessionController(connection))
+                        .FirstOrDefault(i => i != null);
+                }
+
+                return connection;
+            }
+            finally
             {
-                connection.SessionController = _sessionFactories
-                    .Select(i => i.GetSessionController(connection))
-                    .FirstOrDefault(i => i != null);
+                _sessionLock.Release();
             }
-
-            return connection;
         }
 
         private List<User> GetUsers(SessionInfo session)