You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Cache/TimerCachee.cs

138 lines
4.3 KiB

using System;
using System.Collections.Generic;
using ZeroLevel.Services.Shedulling;
namespace ZeroLevel.Services.Cache
{
internal sealed class TimerCachee<T>
: IDisposable
{
private sealed class CacheeItem<I>
{
public I Value { get; set; }
public DateTime LastAcessTime { get; set; }
}
private readonly IDictionary<string, CacheeItem<T>> _cachee;
private readonly object _cacheeLock = new object();
private readonly ISheduller _sheduller;
private readonly Func<string, T> _factory;
private readonly Action<T> _onDisposeAction;
private readonly TimeSpan _expirationPeriod;
public TimerCachee(TimeSpan expirationPeriod, Func<string, T> factory, Action<T> onDisposeAction, int capacity = 512)
{
_factory = factory;
_onDisposeAction = onDisposeAction;
_sheduller = Sheduller.Create();
_cachee = new Dictionary<string, CacheeItem<T>>(capacity);
_expirationPeriod = expirationPeriod;
var ts = TimeSpan.FromSeconds(60);
if (ts.TotalSeconds > expirationPeriod.TotalSeconds)
{
ts = expirationPeriod;
}
_sheduller.RemindEvery(ts, _ => CheckAndCleacnCachee());
}
public T Get(string key)
{
lock (_cacheeLock)
{
if (_cachee.TryGetValue(key, out var v))
{
v.LastAcessTime = DateTime.UtcNow;
return v.Value;
}
}
var obj = _factory.Invoke(key);
var item = new CacheeItem<T> { Value = obj, LastAcessTime = DateTime.UtcNow };
lock (_cacheeLock)
{
_cachee[key] = item;
}
return obj;
}
public void Drop(string key)
{
lock (_cacheeLock)
{
if (_cachee.TryGetValue(key, out var v))
{
try
{
if (_onDisposeAction != null)
{
_onDisposeAction.Invoke(v.Value);
}
}
catch (Exception ex)
{
Log.SystemError(ex, $"[TimerCachee.Drop] Key '{key}'. Fault dispose.");
}
_cachee.Remove(key);
}
}
}
private void CheckAndCleacnCachee()
{
lock (_cacheeLock)
{
var keysToRemove = new List<string>(_cachee.Count);
foreach (var pair in _cachee)
{
if ((DateTime.UtcNow - pair.Value.LastAcessTime) > _expirationPeriod)
{
keysToRemove.Add(pair.Key);
}
}
foreach (var key in keysToRemove)
{
try
{
if (_onDisposeAction != null)
{
_onDisposeAction.Invoke(_cachee[key].Value);
}
}
catch (Exception ex)
{
Log.SystemError(ex, $"[TimerCachee.CheckAndCleacnCachee] Key '{key}'");
}
_cachee.Remove(key);
}
}
}
public void DropAll()
{
lock (_cacheeLock)
{
foreach (var pair in _cachee)
{
try
{
if (_onDisposeAction != null)
{
_onDisposeAction.Invoke(pair.Value.Value);
}
}
catch (Exception ex)
{
Log.SystemError(ex, $"[TimerCachee.DropAll] Key '{pair.Key}'");
}
}
_cachee.Clear();
}
}
public void Dispose()
{
_sheduller?.Clean();
_sheduller?.Dispose();
DropAll();
}
}
}

Powered by TurnKey Linux.