Files
git.stella-ops.org/src/__Libraries/StellaOps.Provcache.Valkey/ValkeyProvcacheStore.cs

72 lines
2.4 KiB
C#

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System.Text.Json;
namespace StellaOps.Provcache.Valkey;
public sealed partial class ValkeyProvcacheStore : IProvcacheStore, IAsyncDisposable
{
private const int DefaultScanPageSize = 200;
private const int DefaultDeleteBatchSize = 500;
private readonly IConnectionMultiplexer _connectionMultiplexer;
private readonly ProvcacheOptions _options;
private readonly ILogger<ValkeyProvcacheStore> _logger;
private readonly TimeProvider _timeProvider;
private readonly JsonSerializerOptions _jsonOptions;
private readonly SemaphoreSlim _connectionLock = new(1, 1);
private IDatabase? _database;
public string ProviderName => "valkey";
public ValkeyProvcacheStore(
IConnectionMultiplexer connectionMultiplexer,
IOptions<ProvcacheOptions> options,
ILogger<ValkeyProvcacheStore> logger,
TimeProvider? timeProvider = null)
{
_connectionMultiplexer = connectionMultiplexer ?? throw new ArgumentNullException(nameof(connectionMultiplexer));
_options = options?.Value ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_timeProvider = timeProvider ?? TimeProvider.System;
_jsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false
};
}
private string BuildKey(string veriKey) => $"{_options.ValkeyKeyPrefix}{veriKey}";
private async Task<IDatabase> GetDatabaseAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (_database is not null)
{
return _database;
}
await _connectionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
_database ??= _connectionMultiplexer.GetDatabase();
return _database;
}
finally
{
_connectionLock.Release();
}
}
public async ValueTask DisposeAsync()
{
_connectionLock.Dispose();
// Note: Don't dispose the connection multiplexer if it's shared (injected via DI)
// The DI container will handle its lifetime
await Task.CompletedTask;
}
}