SPMS_API/SPMS.Infrastructure/Caching/TokenCacheService.cs

103 lines
3.2 KiB
C#

using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SPMS.Application.Interfaces;
using SPMS.Application.Settings;
using StackExchange.Redis;
namespace SPMS.Infrastructure.Caching;
public class TokenCacheService : ITokenCacheService
{
private readonly RedisConnection _redis;
private readonly RedisSettings _settings;
private readonly ILogger<TokenCacheService> _logger;
private static readonly TimeSpan CacheTtl = TimeSpan.FromHours(1);
public TokenCacheService(
RedisConnection redis,
IOptions<RedisSettings> settings,
ILogger<TokenCacheService> logger)
{
_redis = redis;
_settings = settings.Value;
_logger = logger;
}
public async Task<CachedDeviceInfo?> GetDeviceInfoAsync(long serviceId, string deviceId)
{
try
{
var db = await _redis.GetDatabaseAsync();
var value = await db.StringGetAsync(BuildKey(serviceId, deviceId));
if (value.IsNullOrEmpty)
return null;
return JsonSerializer.Deserialize<CachedDeviceInfo>(value!);
}
catch (Exception ex)
{
_logger.LogError(ex, "토큰 캐시 조회 실패: serviceId={ServiceId}, deviceId={DeviceId}",
serviceId, deviceId);
return null;
}
}
public async Task SetDeviceInfoAsync(long serviceId, string deviceId, CachedDeviceInfo info)
{
try
{
var db = await _redis.GetDatabaseAsync();
var json = JsonSerializer.Serialize(info);
await db.StringSetAsync(BuildKey(serviceId, deviceId), json, CacheTtl);
}
catch (Exception ex)
{
_logger.LogError(ex, "토큰 캐시 저장 실패: serviceId={ServiceId}, deviceId={DeviceId}",
serviceId, deviceId);
}
}
public async Task InvalidateAsync(long serviceId, string deviceId)
{
try
{
var db = await _redis.GetDatabaseAsync();
await db.KeyDeleteAsync(BuildKey(serviceId, deviceId));
}
catch (Exception ex)
{
_logger.LogError(ex, "토큰 캐시 무효화 실패: serviceId={ServiceId}, deviceId={DeviceId}",
serviceId, deviceId);
}
}
public async Task InvalidateByServiceAsync(long serviceId)
{
try
{
var db = await _redis.GetDatabaseAsync();
var server = _redis.GetServer();
if (server == null) return;
var pattern = $"{_settings.InstanceName}device:token:{serviceId}:*";
var keys = server.Keys(pattern: pattern).ToArray();
if (keys.Length > 0)
await db.KeyDeleteAsync(keys);
_logger.LogInformation("서비스 토큰 캐시 전체 무효화: serviceId={ServiceId}, 삭제={Count}건",
serviceId, keys.Length);
}
catch (Exception ex)
{
_logger.LogError(ex, "서비스 토큰 캐시 전체 무효화 실패: serviceId={ServiceId}", serviceId);
}
}
private string BuildKey(long serviceId, string deviceId) =>
$"{_settings.InstanceName}device:token:{serviceId}:{deviceId}";
}