2022-03-13 09:28:21 +01:00
|
|
|
|
using System;
|
2022-05-24 08:45:40 +02:00
|
|
|
|
using System.Collections.Concurrent;
|
2022-03-13 09:28:21 +01:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
2022-05-29 05:32:31 +02:00
|
|
|
|
using System.Threading;
|
2022-03-13 09:28:21 +01:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Teknik.Utilities
|
|
|
|
|
{
|
|
|
|
|
public class ObjectCache
|
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
private readonly int _defaultCacheTime;
|
|
|
|
|
private static object _cacheLock = new object();
|
2022-03-13 09:28:21 +01:00
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
private readonly static ConcurrentDictionary<string, CacheEntry> _objectCache = new ConcurrentDictionary<string, CacheEntry>();
|
|
|
|
|
|
|
|
|
|
public ObjectCache(int defaultCacheTime)
|
|
|
|
|
{
|
|
|
|
|
_defaultCacheTime = defaultCacheTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public T AddOrGetObject<T>(string key, Func<string, T> getObjectFunc)
|
2022-03-13 09:28:21 +01:00
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
return AddOrGetObject(key, new TimeSpan(0, 0, _defaultCacheTime), getObjectFunc);
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
public T AddOrGetObject<T>(string key, TimeSpan cacheTime, Func<string, T> getObjectFunc)
|
2022-03-13 09:28:21 +01:00
|
|
|
|
{
|
|
|
|
|
T foundObject;
|
2022-05-29 05:32:31 +02:00
|
|
|
|
lock (_cacheLock)
|
|
|
|
|
{
|
|
|
|
|
if (_objectCache.TryGetValue(GenerateKey<T>(key), out var result) &&
|
|
|
|
|
CacheValid(result))
|
|
|
|
|
{
|
|
|
|
|
if (result.RollingExpiration)
|
|
|
|
|
{
|
|
|
|
|
result.LastUpdate = DateTime.UtcNow;
|
|
|
|
|
}
|
|
|
|
|
return (T)result.Data;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
foundObject = getObjectFunc(key);
|
|
|
|
|
// Update the cache for this key
|
|
|
|
|
if (foundObject != null)
|
|
|
|
|
UpdateObject(key, foundObject, cacheTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return foundObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateObject<T>(string key, T data)
|
|
|
|
|
{
|
|
|
|
|
UpdateObject(key, data, null, DateTime.UtcNow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateObject<T>(string key, T data, TimeSpan cacheTime)
|
|
|
|
|
{
|
|
|
|
|
UpdateObject(key, data, cacheTime, DateTime.UtcNow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateObject<T>(string key, T data, TimeSpan? cacheTime, DateTime lastUpdate)
|
|
|
|
|
{
|
|
|
|
|
if (_objectCache.TryGetValue(GenerateKey<T>(key), out var result))
|
2022-03-13 09:28:21 +01:00
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
result.Data = data;
|
|
|
|
|
if (cacheTime.HasValue)
|
|
|
|
|
result.CacheTime = cacheTime.Value;
|
|
|
|
|
result.LastUpdate = lastUpdate;
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
if (!cacheTime.HasValue)
|
|
|
|
|
cacheTime = new TimeSpan(0, 0, _defaultCacheTime);
|
|
|
|
|
_objectCache[GenerateKey<T>(key)] = CreateCacheEntry(data, cacheTime.Value, lastUpdate);
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
2022-05-29 05:32:31 +02:00
|
|
|
|
}
|
2022-03-13 09:28:21 +01:00
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
public void DeleteObject<T>(string key)
|
|
|
|
|
{
|
|
|
|
|
_objectCache.TryRemove(GenerateKey<T>(key), out _);
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
public bool CacheValid(CacheEntry entry)
|
2022-03-13 09:28:21 +01:00
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
return entry.LastUpdate > DateTime.UtcNow.Subtract(entry.CacheTime);
|
2022-03-14 07:21:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
public void CleanCache()
|
2022-03-14 07:21:00 +01:00
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
lock (_cacheLock)
|
|
|
|
|
{
|
|
|
|
|
foreach (var obj in _objectCache)
|
|
|
|
|
{
|
|
|
|
|
if (!CacheValid(obj.Value))
|
|
|
|
|
_objectCache.TryRemove(obj.Key, out _);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
public string GenerateKey<T>(string key)
|
2022-03-13 09:28:21 +01:00
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
var typeKey = typeof(T).ToString();
|
|
|
|
|
return $"{typeKey}.{key}";
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
2022-03-14 07:21:00 +01:00
|
|
|
|
|
2022-05-29 05:32:31 +02:00
|
|
|
|
public CacheEntry CreateCacheEntry<T>(T data, TimeSpan cacheTime, DateTime lastUpdate)
|
2022-03-14 07:21:00 +01:00
|
|
|
|
{
|
2022-05-29 05:32:31 +02:00
|
|
|
|
return new CacheEntry(false, cacheTime, lastUpdate, data);
|
2022-03-14 07:21:00 +01:00
|
|
|
|
}
|
2022-03-13 09:28:21 +01:00
|
|
|
|
}
|
|
|
|
|
}
|