Files
Disco/Disco.BI/BI/UserBI/UserCache.cs
T
Gary Sharp f6904d27c9 Update: User Cache Prune Seperation
Avoids other assemblies from requiring Quartz just to get CurrentUser
2013-05-16 19:24:20 +10:00

147 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using Disco.Models.Repository;
using Disco.Data.Repository;
using System.Web;
using Quartz;
using Quartz.Impl;
using Disco.Services.Tasks;
namespace Disco.BI.UserBI
{
public class UserCache
{
private static ConcurrentDictionary<string, Tuple<User, DateTime>> _Cache = new ConcurrentDictionary<string, Tuple<User, DateTime>>();
private const long CacheTimeoutTicks = 6000000000; // 10 Minutes
private const string CacheHttpRequestKey = "Disco_CurrentUser";
public static User CurrentUser
{
get
{
string username = null;
User user;
// Check for ASP.NET
if (HttpContext.Current != null)
{
if (HttpContext.Current.Request.IsAuthenticated)
{
user = (User)HttpContext.Current.Items[CacheHttpRequestKey];
if (user != null)
return user;
username = HttpContext.Current.User.Identity.Name;
}
else
{
return null;
//throw new PlatformNotSupportedException("ASP.NET Authentication is not correctly configured");
}
}
// User default User
if (username == null)
{
username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
user = GetUser(username);
if (HttpContext.Current != null && HttpContext.Current.Request.IsAuthenticated)
{
// Cache in current request
HttpContext.Current.Items[CacheHttpRequestKey] = user;
}
return user;
}
}
public static User GetUser(string Username)
{
// Check Cache
User u = TryUserCache(Username);
if (u == null)
{
// Load from Repository
using (DiscoDataContext dbContext = new DiscoDataContext())
{
u = GetUser(Username, dbContext, true);
}
}
return u;
}
public static User GetUser(string Username, DiscoDataContext dbContext, bool ForceRefresh = false)
{
User u = null;
// Check Cache
if (!ForceRefresh)
u = TryUserCache(Username);
if (u == null)
{
string username = Username.ToLower();
u = UserBI.Utilities.LoadUser(dbContext, username);
SetValue(username, u);
}
return u;
}
private static User TryUserCache(string Username)
{
string username = Username.ToLower();
Tuple<User, DateTime> userRecord;
if (_Cache.TryGetValue(username, out userRecord))
{
if (userRecord.Item2 > DateTime.Now)
return userRecord.Item1;
else
_Cache.TryRemove(username, out userRecord);
}
return null;
}
public static bool InvalidateValue(string Key)
{
Tuple<User, DateTime> userRecord;
return _Cache.TryRemove(Key.ToLower(), out userRecord);
}
private static bool SetValue(string Key, User User)
{
string key = Key.ToLower();
Tuple<User, DateTime> userRecord = new Tuple<User, DateTime>(User, DateTime.Now.AddTicks(CacheTimeoutTicks));
if (_Cache.ContainsKey(key))
{
Tuple<User, DateTime> oldUser;
if (_Cache.TryGetValue(key, out oldUser))
{
return _Cache.TryUpdate(key, userRecord, oldUser);
}
}
return _Cache.TryAdd(key, userRecord);
}
internal static void CleanStaleCache()
{
var usernames = _Cache.Keys.ToArray();
foreach (string username in usernames)
{
Tuple<User, DateTime> userRecord;
if (_Cache.TryGetValue(username, out userRecord))
{
if (userRecord.Item2 <= DateTime.Now)
_Cache.TryRemove(username, out userRecord);
}
}
}
}
}