VEU.WathBody/3-app/1-lib/Kit.Helpers/Service/DistributedPg/PgTableDistributedCacheServ...

80 lines
2.9 KiB
C#

using Kit.Helpers.Postgres;
namespace Kit.Helpers;
/// <summary>
/// Провайдер кэша через самописную схему (и её элементы) distributed. <br />
/// </summary>
public class PgTableDistributedCacheService : IDistributedCacheService
{
private readonly IDistributedLockService _distributedLockService;
private readonly string _connectionString;
private const string _lockType = "PgTableDistributedCacheService";
public PgTableDistributedCacheService(
IConfigurationDistributedPg configuration,
IDistributedLockService distributedLockService)
{
_distributedLockService = distributedLockService;
_connectionString = configuration.DistributedConnectionString;
}
public void ExecuteOnLock(string key, Action action)
{
_distributedLockService.ExecuteOnLock(_lockType, key, action);
}
public TResult ExecuteOnLock<TResult>(string key, Func<TResult> action)
{
return _distributedLockService.ExecuteOnLock(_lockType, key, action);
}
public void SetCacheData<TObject>(string cacheName, TObject data, DistributedCacheOptions setProperties)
{
this.ExecuteOnLock(cacheName, () =>
{
var parameters = new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("_key", cacheName),
new KeyValuePair<string, object>("_value", data.JsonSerialize())
};
if (setProperties.AbsoluteExpirationRelativeToNow.HasValue)
{
parameters.Add(new KeyValuePair<string, object>("_absolute_expiration_seconds", (int)setProperties.AbsoluteExpirationRelativeToNow.Value.TotalSeconds));
}
if (setProperties.SlidingExpiration.HasValue)
{
parameters.Add(new KeyValuePair<string, object>("_sliding_expiration_seconds", (int)setProperties.SlidingExpiration.Value.TotalSeconds));
}
_connectionString.ExecuteNonQuery("distributed.cache_insert", isStoredProcedure: true, parameters);
});
}
public TResult? GetCacheData<TResult>(string cacheName)
{
return this.ExecuteOnLock(cacheName, () =>
{
var parameters = new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("_key", cacheName)
};
object? result = _connectionString.ExecuteScalar<object>("distributed.cache_select", isStoredProcedure: true, parameters:parameters);
if (result is not string jsonString)
{
return default;
}
try
{
return jsonString.JsonDeserialize<TResult>();
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error while deserializing json value of cache. cacheName: {cacheName}", ex);
}
});
}
}