using Microsoft.Extensions.Logging; using StackExchange.Redis; using WIDESEAWCS_Core.Caches; using WIDESEAWCS_RedisService.Connection; using WIDESEAWCS_RedisService.Options; using WIDESEAWCS_RedisService.Serialization; using Microsoft.Extensions.Options; namespace WIDESEAWCS_RedisService.Cache { public class RedisCacheService : ICacheService { private readonly IRedisConnectionManager _connectionManager; private readonly IRedisSerializer _serializer; private readonly RedisOptions _options; private readonly ILogger _logger; private bool _disposed; public RedisCacheService( IRedisConnectionManager connectionManager, IRedisSerializer serializer, IOptions options, ILogger logger) { _connectionManager = connectionManager; _serializer = serializer; _options = options.Value; _logger = logger; } private string BuildKey(string key) => $"{_options.KeyPrefix}{key}"; private IDatabase Db => _connectionManager.GetDatabase(); public bool Exists(string key) { return Db.KeyExists(BuildKey(key)); } public bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false) { var fullKey = BuildKey(key); var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; return Db.StringSet(fullKey, value, expiry); } public bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false) { return Add(key, _serializer.Serialize(value), expireSeconds, isSliding); } public void AddOrUpdate(string key, string value, int expireSeconds = -1, bool isSliding = false) { Add(key, value, expireSeconds, isSliding); } public void AddOrUpdate(string key, object value, int expireSeconds = -1, bool isSliding = false) { AddObject(key, value, expireSeconds, isSliding); } public bool Remove(string key) { return Db.KeyDelete(BuildKey(key)); } public void Remove(IEnumerable keys) { var redisKeys = keys.Select(k => (RedisKey)BuildKey(k)).ToArray(); Db.KeyDelete(redisKeys); } public T? Get(string key) where T : class { var value = Db.StringGet(BuildKey(key)); if (value.IsNullOrEmpty) return default; return _serializer.Deserialize(value!); } public object? Get(Type type, string key) { var value = Db.StringGet(BuildKey(key)); if (value.IsNullOrEmpty) return null; return _serializer.Deserialize(value!, type); } public string? Get(string key) { var value = Db.StringGet(BuildKey(key)); return value.IsNullOrEmpty ? null : value.ToString(); } public void Dispose() { if (_disposed) return; _disposed = true; } public bool TryAdd(string key, string value, int expireSeconds = -1) { var fullKey = BuildKey(key); var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; return Db.StringSet(fullKey, value, expiry, When.NotExists); } public bool TryAdd(string key, T value, int expireSeconds = -1) where T : class { return TryAdd(key, _serializer.Serialize(value), expireSeconds); } public bool TryGetValue(string key, out string? value) { var val = Db.StringGet(BuildKey(key)); value = val.IsNullOrEmpty ? null : val.ToString(); return !val.IsNullOrEmpty; } public bool TryGetValue(string key, out T? value) where T : class { var val = Db.StringGet(BuildKey(key)); if (val.IsNullOrEmpty) { value = default; return false; } value = _serializer.Deserialize(val!); return value != null; } public bool TryRemove(string key, out string? value) { var fullKey = BuildKey(key); value = Db.StringGet(fullKey).ToString(); if (value == null) return false; return Db.KeyDelete(fullKey); } public bool TryUpdate(string key, string newValue, int expireSeconds = -1) { var fullKey = BuildKey(key); if (!Db.KeyExists(fullKey)) return false; var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; return Db.StringSet(fullKey, newValue, expiry, When.Exists); } public string GetOrAdd(string key, string value, int expireSeconds = -1) { var fullKey = BuildKey(key); var existing = Db.StringGet(fullKey); if (!existing.IsNullOrEmpty) return existing.ToString(); var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; Db.StringSet(fullKey, value, expiry, When.NotExists); return Db.StringGet(fullKey).ToString(); } public string GetOrAdd(string key, Func valueFactory, int expireSeconds = -1) { var fullKey = BuildKey(key); var existing = Db.StringGet(fullKey); if (!existing.IsNullOrEmpty) return existing.ToString(); var value = valueFactory(key); var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; Db.StringSet(fullKey, value, expiry, When.NotExists); return Db.StringGet(fullKey).ToString(); } public T GetOrAdd(string key, Func valueFactory, int expireSeconds = -1) where T : class { var fullKey = BuildKey(key); var existing = Db.StringGet(fullKey); if (!existing.IsNullOrEmpty) return _serializer.Deserialize(existing!)!; var value = valueFactory(key); var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; Db.StringSet(fullKey, _serializer.Serialize(value), expiry, When.NotExists); return value; } } }