Try your search with a different keyword or use * as a wildcard.
using System.Net;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
namespace Nop.Services.Caching;
/// <summary>
/// Redis connection wrapper
/// </summary>
/// <remarks>
/// This class should be registered on IoC as singleton instance
/// </remarks>
public partial class RedisConnectionWrapper : IRedisConnectionWrapper
{
#region Fields
protected readonly SemaphoreSlim _connectionLock = new(1, 1);
protected volatile IConnectionMultiplexer _connection;
protected readonly RedisCacheOptions _options;
#endregion
#region Ctor
public RedisConnectionWrapper(IOptions<RedisCacheOptions> optionsAccessor)
{
_options = optionsAccessor.Value;
}
#endregion
#region Utilities
/// <summary>
/// Create a new ConnectionMultiplexer instance
/// </summary>
/// <returns></returns>
protected virtual async Task<IConnectionMultiplexer> ConnectAsync()
{
IConnectionMultiplexer connection;
if (_options.ConnectionMultiplexerFactory is null)
{
if (_options.ConfigurationOptions is not null)
connection = await ConnectionMultiplexer.ConnectAsync(_options.ConfigurationOptions);
else
connection = await ConnectionMultiplexer.ConnectAsync(_options.Configuration);
}
else
{
connection = await _options.ConnectionMultiplexerFactory();
}
if (_options.ProfilingSession != null)
connection.RegisterProfiler(_options.ProfilingSession);
return connection;
}
/// <summary>
/// Create a new ConnectionMultiplexer instance
/// </summary>
/// <returns></returns>
protected virtual IConnectionMultiplexer Connect()
{
IConnectionMultiplexer connection;
if (_options.ConnectionMultiplexerFactory is null)
connection = _options.ConfigurationOptions is not null ? ConnectionMultiplexer.Connect(_options.ConfigurationOptions) : ConnectionMultiplexer.Connect(_options.Configuration);
else
connection = _options.ConnectionMultiplexerFactory().GetAwaiter().GetResult();
if (_options.ProfilingSession != null)
connection.RegisterProfiler(_options.ProfilingSession);
return connection;
}
/// <summary>
/// Get connection to Redis servers, and reconnects if necessary
/// </summary>
/// <returns></returns>
protected virtual async Task<IConnectionMultiplexer> GetConnectionAsync()
{
if (_connection?.IsConnected == true)
return _connection;
await _connectionLock.WaitAsync();
try
{
if (_connection?.IsConnected == true)
return _connection;
//Connection disconnected. Disposing connection...
_connection?.Dispose();
//Creating new instance of Redis Connection
_connection = await ConnectAsync();
}
finally
{
_connectionLock.Release();
}
return _connection;
}
/// <summary>
/// Get connection to Redis servers, and reconnects if necessary
/// </summary>
/// <returns></returns>
protected virtual IConnectionMultiplexer GetConnection()
{
if (_connection?.IsConnected == true)
return _connection;
_connectionLock.Wait();
try
{
if (_connection?.IsConnected == true)
return _connection;
//Connection disconnected. Disposing connection...
_connection?.Dispose();
//Creating new instance of Redis Connection
_connection = Connect();
}
finally
{
_connectionLock.Release();
}
return _connection;
}
#endregion
#region Methods
/// <summary>
/// Obtain an interactive connection to a database inside Redis
/// </summary>
/// <returns>Redis cache database</returns>
public virtual async Task<IDatabase> GetDatabaseAsync()
{
return (await GetConnectionAsync()).GetDatabase();
}
/// <summary>
/// Obtain an interactive connection to a database inside Redis
/// </summary>
/// <returns>Redis cache database</returns>
public virtual IDatabase GetDatabase()
{
return GetConnection().GetDatabase();
}
/// <summary>
/// Obtain a configuration API for an individual server
/// </summary>
/// <param name="endPoint">The network endpoint</param>
/// <returns>Redis server</returns>
public virtual async Task<IServer> GetServerAsync(EndPoint endPoint)
{
return (await GetConnectionAsync()).GetServer(endPoint);
}
/// <summary>
/// Gets all endpoints defined on the server
/// </summary>
/// <returns>Array of endpoints</returns>
public virtual async Task<EndPoint[]> GetEndPointsAsync()
{
return (await GetConnectionAsync()).GetEndPoints();
}
/// <summary>
/// Gets a subscriber for the server
/// </summary>
/// <returns>Array of endpoints</returns>
public virtual async Task<ISubscriber> GetSubscriberAsync()
{
return (await GetConnectionAsync()).GetSubscriber();
}
/// <summary>
/// Gets a subscriber for the server
/// </summary>
/// <returns>Array of endpoints</returns>
public virtual ISubscriber GetSubscriber()
{
return GetConnection().GetSubscriber();
}
/// <summary>
/// Delete all the keys of the database
/// </summary>
public virtual async Task FlushDatabaseAsync()
{
var endPoints = await GetEndPointsAsync();
await Task.WhenAll(endPoints.Select(async endPoint =>
{
var server = await GetServerAsync(endPoint);
if (!server.IsReplica)
{
await server.FlushDatabaseAsync();
}
}));
}
/// <summary>
/// Release all resources associated with this object
/// </summary>
public virtual void Dispose()
{
//dispose ConnectionMultiplexer
_connection?.Dispose();
}
#endregion
#region Properties
/// <summary>
/// The Redis instance name
/// </summary>
public string Instance => _options.InstanceName ?? string.Empty;
#endregion
}