mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-04-25 03:12:54 -04:00
perf(cache): use ValueTask on hot sync paths
This commit is contained in:
@@ -170,17 +170,22 @@ public class RedisCacheService
|
||||
/// Gets a cached value as a string.
|
||||
/// Checks L1 memory cache first, falls back to L2 Redis.
|
||||
/// </summary>
|
||||
public async Task<string?> GetStringAsync(string key)
|
||||
public ValueTask<string?> GetStringAsync(string key)
|
||||
{
|
||||
// L1: Try in-memory cache first (sub-microsecond)
|
||||
if (TryGetMemoryValue(key, out var memoryValue))
|
||||
{
|
||||
_logger.LogDebug("L1 memory cache HIT: {Key}", key);
|
||||
return memoryValue;
|
||||
return new ValueTask<string?>(memoryValue);
|
||||
}
|
||||
|
||||
if (!IsEnabled) return null;
|
||||
if (!IsEnabled) return new ValueTask<string?>((string?)null);
|
||||
|
||||
return new ValueTask<string?>(GetStringFromRedisAsync(key));
|
||||
}
|
||||
|
||||
private async Task<string?> GetStringFromRedisAsync(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
// L2: Fall back to Redis
|
||||
@@ -219,7 +224,7 @@ public class RedisCacheService
|
||||
/// Uses source-generated serializer for registered types (3-8x faster),
|
||||
/// with automatic fallback to reflection-based serialization.
|
||||
/// </summary>
|
||||
public async Task<T?> GetAsync<T>(string key) where T : class
|
||||
public async ValueTask<T?> GetAsync<T>(string key) where T : class
|
||||
{
|
||||
var json = await GetStringAsync(key);
|
||||
if (string.IsNullOrEmpty(json)) return null;
|
||||
@@ -243,13 +248,18 @@ public class RedisCacheService
|
||||
/// Sets a cached value with TTL.
|
||||
/// Writes to both L1 memory cache and L2 Redis.
|
||||
/// </summary>
|
||||
public async Task<bool> SetStringAsync(string key, string value, TimeSpan? expiry = null)
|
||||
public ValueTask<bool> SetStringAsync(string key, string value, TimeSpan? expiry = null)
|
||||
{
|
||||
// Always update L1 (even if Redis is down — provides degraded caching)
|
||||
SetMemoryValue(key, value, expiry);
|
||||
|
||||
if (!IsEnabled) return false;
|
||||
if (!IsEnabled) return new ValueTask<bool>(false);
|
||||
|
||||
return new ValueTask<bool>(SetStringWithRedisAsync(key, value, expiry));
|
||||
}
|
||||
|
||||
private async Task<bool> SetStringWithRedisAsync(string key, string value, TimeSpan? expiry)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await SetStringInternalAsync(key, value, expiry);
|
||||
@@ -349,7 +359,7 @@ public class RedisCacheService
|
||||
/// Uses source-generated serializer for registered types (3-8x faster),
|
||||
/// with automatic fallback to reflection-based serialization.
|
||||
/// </summary>
|
||||
public async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null) where T : class
|
||||
public async ValueTask<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null) where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -386,14 +396,19 @@ public class RedisCacheService
|
||||
/// <summary>
|
||||
/// Deletes a cached value from both L1 memory and L2 Redis.
|
||||
/// </summary>
|
||||
public async Task<bool> DeleteAsync(string key)
|
||||
public ValueTask<bool> DeleteAsync(string key)
|
||||
{
|
||||
// Always evict from L1
|
||||
_memoryCache.Remove(key);
|
||||
_memoryKeys.TryRemove(key, out _);
|
||||
|
||||
if (!IsEnabled) return false;
|
||||
if (!IsEnabled) return new ValueTask<bool>(false);
|
||||
|
||||
return new ValueTask<bool>(DeleteFromRedisAsync(key));
|
||||
}
|
||||
|
||||
private async Task<bool> DeleteFromRedisAsync(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _db!.KeyDeleteAsync(key);
|
||||
@@ -408,15 +423,20 @@ public class RedisCacheService
|
||||
/// <summary>
|
||||
/// Checks if a key exists.
|
||||
/// </summary>
|
||||
public async Task<bool> ExistsAsync(string key)
|
||||
public ValueTask<bool> ExistsAsync(string key)
|
||||
{
|
||||
if (ShouldUseMemoryCache(key) && _memoryCache.TryGetValue(key, out _))
|
||||
{
|
||||
return true;
|
||||
return new ValueTask<bool>(true);
|
||||
}
|
||||
|
||||
if (!IsEnabled) return false;
|
||||
if (!IsEnabled) return new ValueTask<bool>(false);
|
||||
|
||||
return new ValueTask<bool>(ExistsInRedisAsync(key));
|
||||
}
|
||||
|
||||
private async Task<bool> ExistsInRedisAsync(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _db!.KeyExistsAsync(key);
|
||||
@@ -451,11 +471,16 @@ public class RedisCacheService
|
||||
/// Deletes all keys matching a pattern (e.g., "search:*").
|
||||
/// WARNING: Use with caution as this scans all keys.
|
||||
/// </summary>
|
||||
public async Task<int> DeleteByPatternAsync(string pattern)
|
||||
public ValueTask<int> DeleteByPatternAsync(string pattern)
|
||||
{
|
||||
var memoryDeleted = RemoveMemoryKeysByPattern(pattern);
|
||||
if (!IsEnabled) return memoryDeleted;
|
||||
if (!IsEnabled) return new ValueTask<int>(memoryDeleted);
|
||||
|
||||
return new ValueTask<int>(DeleteByPatternFromRedisAsync(pattern, memoryDeleted));
|
||||
}
|
||||
|
||||
private async Task<int> DeleteByPatternFromRedisAsync(string pattern, int memoryDeleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
var server = _redis!.GetServer(_redis.GetEndPoints().First());
|
||||
|
||||
Reference in New Issue
Block a user