72 lines
2.4 KiB
C#
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;
|
|
}
|
|
}
|