Files
parr_api/PARR.DAL/Cache/Services/Base/RedisCacheService.cs

186 lines
5.7 KiB
C#
Raw Normal View History

2023-11-30 16:18:14 +10:00
using Microsoft.Extensions.Caching.Distributed;
using StackExchange.Redis;
2023-11-30 16:18:14 +10:00
using System.Text.Json;
using static System.Runtime.InteropServices.JavaScript.JSType;
2023-11-30 16:18:14 +10:00
namespace PARR.DAL.Cache.Services.Base
2023-11-30 16:18:14 +10:00
{
internal class RedisCacheService : IRedisCacheService
{
private readonly IDistributedCache cache;
private readonly IDatabase redis;
2023-11-30 16:18:14 +10:00
public RedisCacheService(
IDistributedCache cache,
IConnectionMultiplexer connectionMultiplexer
)
2023-11-30 16:18:14 +10:00
{
this.cache = cache;
this.redis = connectionMultiplexer.GetDatabase();
2023-11-30 16:18:14 +10:00
}
#region Распределенный кэш IDistributedCache
2023-11-30 16:18:14 +10:00
public async Task<T?> GetCachedDataAsync<T>(string key)
{
var jsonData = await cache.GetStringAsync(key);
2023-11-30 16:18:14 +10:00
if (jsonData == null)
return default(T);
return JsonSerializer.Deserialize<T>(jsonData);
}
public T? GetCachedData<T>(string key)
{
var jsonData = cache.GetString(key);
if (jsonData == null)
return default(T);
return JsonSerializer.Deserialize<T>(jsonData);
}
public void SetCachedData<T>(string key, T data, TimeSpan cacheDuration)
{
var options = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = cacheDuration
};
var jsonData = JsonSerializer.Serialize(data);
cache.SetString(key, jsonData, options);
}
public async Task SetCachedDataAsync<T>(string key, T data, TimeSpan cacheDuration)
{
var options = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = cacheDuration
};
var jsonData = JsonSerializer.Serialize(data);
await cache.SetStringAsync(key, jsonData, options);
}
public async Task DeleteCachedDataAsync(string key)
{
await cache.RemoveAsync(key);
}
public void DeleteCachedData(string key)
{
cache.Remove(key);
}
2023-11-30 16:18:14 +10:00
#endregion
#region Нативные операции Redis, Redis Hash
public async Task SetHashFieldAsync<T>(string hashKey, string field, T value, TimeSpan? ttl = null)
{
// меняет одно поле в Hash
var jsonData = JsonSerializer.Serialize(value);
// true - поля не было, создалось новое. false - поле было, обновили значение
var result = await redis.HashSetAsync(hashKey, field, jsonData);
// если указан ttl, обновим для всего Hash
// если не указан и ранее был создан hashKey, оставит его ttl; а если hashKey не было, то создаст его БЕССРОЧНЫМ!!!
if (ttl.HasValue)
await SetHashTtlAsync(hashKey, ttl.Value);
}
public async Task<T?> GetHashFieldAsync<T>(string hashKey, string field)
{
// получить значение поля из Hash
var value = await redis.HashGetAsync(hashKey, field);
if (value.IsNullOrEmpty)
return default;
return JsonSerializer.Deserialize<T>(value);
}
public async Task<Dictionary<string, T>> GetAllHashFieldsAsync<T>(string hashKey)
{
// получить все записи из Hash
var objs = await redis.HashGetAllAsync(hashKey);
if (objs.Length == 0)
return new Dictionary<string, T>();
var result = objs.ToDictionary(
t => t.Name.ToString(),
t => JsonSerializer.Deserialize<T>(t.Value)
);
return result!;
}
public async Task DeleteHashFieldAsync(string hashKey, string field)
{
// удалить запись из Hash
await redis.HashDeleteAsync(hashKey, field);
}
public async Task<bool> HashFieldExistsAsync(string hashKey, string field)
{
// есть ли запись в Hash
return await redis.HashExistsAsync(hashKey, field);
}
public async Task DeleteHashAsync(string hashKey)
{
// удалить весь Hash
await redis.KeyDeleteAsync(hashKey);
}
public async Task<long> GetHashLengthAsync(string hashKey)
{
// кол-во записей в hash
return await redis.HashLengthAsync(hashKey);
}
public async Task SetHashTtlAsync(string hashKey, TimeSpan ttl)
{
// Установить ttl для Hash
await redis.KeyExpireAsync(hashKey, ttl);
}
#endregion
#region Helpers
public string GetKey(string[] keyParts, bool isUseHash = false)
{
if (keyParts.Length == 0)
{
throw new ArgumentNullException("keyParts не может быть пустым");
}
var keyStr = string.Join("_", keyParts);
if (isUseHash)
{
using var sha256 = System.Security.Cryptography.SHA256.Create();
var hashedBytes = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(keyStr));
// return Convert.ToBase64String(hashedBytes).Replace('+', '-').Replace('/', '_').Substring(0, 16);
return Convert.ToBase64String(hashedBytes).Substring(0, 16);
}
return keyStr;
}
#endregion
2023-11-30 16:18:14 +10:00
}
}