using Newtonsoft.Json; using System.Reflection; using System.Security.Cryptography; using System.Text; using HealthMonitor.Core.Common; using HealthMonitor.Util.Common.Cache; using HealthMonitor.Util.Entities.Base; using HealthMonitor.Util.Models; using HealthMonitor.Util.Entities.GpsCard; namespace HealthMonitor.Core.Cache { public class DurableEntityManager : IDurableEntityManager, IDisposable { private const string DurableCacheKey = "Entity"; private static object _syncLocker = new object(); private readonly Dictionary _dictDurableEntities; private MD5? _md5; public DurableEntityManager() { var typesDurable = Assembly.GetAssembly(typeof(EntityBase))?.GetTypes() .Where(type => !string.IsNullOrEmpty(type.Namespace) && type.Namespace.StartsWith("HealthMonitor.Util.Entities")) .Where(type => type.IsSubclassOf(typeof(EntityBase)) && type.GetCustomAttribute() != null) .ToList(); _dictDurableEntities = new Dictionary(); typesDurable?.ForEach(e => { var attr = e.GetCustomAttribute(); _dictDurableEntities.Add(e, new EntityCacheHandler(e, attr!.Duration)); }); _md5 = MD5.Create(); } public IEntityCacheHandler? GetCacheHandler(Type entityType) { return _dictDurableEntities.ContainsKey(entityType) ? _dictDurableEntities[entityType] : null; } public string CalcCacheKey(Type entityType, string id) { string typeName = entityType.Name; return $"{DurableCacheKey}_{typeName}#{id}"; } public string CalcCacheKey(Type entityType, GeneralParam conditions) { string typeName = entityType.Name; string hash = ComputeHash(conditions); var key = $"{DurableCacheKey}_{typeName}${hash}"; return key; } public string CalcHistoryCacheKey(Type entityType, string id, string imei, DateTime? date = null) { string typeName = entityType.Name; var historyDate = date ?? DateTime.Now; if (entityType == typeof(GpsBloodPressReferenceValue)) id = $"{historyDate.ToString("yyyyMM")}_{DeviceUtils.GetImeiSuffix(imei)}_{id}"; else id = $"{historyDate.ToString("yyyyMM")}_{id}"; return $"{DurableCacheKey}_{typeName}#{id}"; } public string CalcHistoryCacheKey(Type entityType, GeneralParam conditions, string imei, DateTime? date = null) { string typeName = entityType.Name; var historyDate = date ?? DateTime.Now; string hash = ComputeHash(conditions); if (entityType == typeof(GpsBloodPressReferenceValue)) hash = $"{historyDate.ToString("yyyyMM")}_{DeviceUtils.GetImeiSuffix(imei)}_{hash}"; else hash = $"{historyDate.ToString("yyyyMM")}_{hash}"; var key = $"{DurableCacheKey}_{typeName}${hash}"; return key; } public void CleanUpEntitiesMapper() { foreach (var key in _dictDurableEntities.Keys) { _dictDurableEntities[key].CleanUpExpiredMapper(); } } private string ComputeHash(object data) { lock (_syncLocker) { var value = JsonConvert.SerializeObject(data); //value = BitConverter.ToString(_md5.ComputeHash(Encoding.UTF8.GetBytes(value))); value = Convert.ToBase64String(_md5!.ComputeHash(Encoding.UTF8.GetBytes(value))); return value; } } public void Dispose() { if (_md5 != null) { _md5.Dispose(); _md5 = null; } } } }