public async Task <(IDatabase database, CancellationToken databaseLifetimeToken)> GetDatabaseWithKeyPrefix(Context context, string keySpace) { if (_resetConnectionMultiplexerCts.IsCancellationRequested) { using (await SemaphoreSlimToken.WaitAsync(_creationSemaphore)) { if (_resetConnectionMultiplexerCts.IsCancellationRequested) { context.Debug("Shutting down current connection multiplexer."); await _connectionMultiplexerShutdownFunc(_connectionMultiplexer); context.Debug("Creating new multiplexer instance."); var newConnectionMultiplexer = await _connectionMultiplexerFactory(); // Using volatile operation to prevent the instruction reordering. // We really want the cts change to be the last one. Volatile.Write(ref _connectionMultiplexer, newConnectionMultiplexer); // Need to change the source at the end to avoid the race condition when // another thread can see a non-canceled CancellationTokenSource // and at the end still get an old connection multiplexer. _resetConnectionMultiplexerCts = new CancellationTokenSource(); } } } return(_connectionMultiplexer.GetDatabase().WithKeyPrefix(keySpace), _resetConnectionMultiplexerCts.Token); }
public async Task GetHashCodeThrows() { using (var sempahore = new SemaphoreSlim(2, 2)) { using (SemaphoreSlimToken waitToken = await sempahore.WaitToken()) { Action a = () => waitToken.GetHashCode().Should().BePositive(); a.Should().Throw <InvalidOperationException>(); } } }
public async Task NotEqualsThrows() { using (var sempahore = new SemaphoreSlim(2, 2)) { using (SemaphoreSlimToken waitToken1 = await sempahore.WaitToken(), waitToken2 = await sempahore.WaitToken()) { Action a = () => (waitToken1 != waitToken2).Should().BeTrue(); a.Should().Throw <InvalidOperationException>(); } } }
/// <summary> /// Gets a Redis Database object with a specified key prefix. /// </summary> public async Task <IDatabase> GetDatabaseWithKeyPrefix(Context context, string keySpace) { if (_resetConnectionMultiplexer) { using (await SemaphoreSlimToken.Wait(_creationSemaphore)) { if (_resetConnectionMultiplexer) { ConfigurationOptions options = ConfigurationOptions.Parse(_connectionMultiplexer.Configuration); await RedisConnectionMultiplexer.ForgetAsync(options); _connectionMultiplexer = await RedisConnectionMultiplexer.CreateAsync(context, _connectionStringProvider); _resetConnectionMultiplexer = false; } } } return(_connectionMultiplexer.GetDatabase().WithKeyPrefix(keySpace)); }
public async Task <IDatabase> GetDatabaseWithKeyPrefix(Context context, string keySpace) { if (_resetConnectionMultiplexer) { using (await SemaphoreSlimToken.WaitAsync(_creationSemaphore)) { if (_resetConnectionMultiplexer) { context.Debug("Shutting down current connection multiplexer."); await _connectionMultiplexerShutdownFunc(_connectionMultiplexer); context.Debug("Creating new multiplexer instance."); _connectionMultiplexer = await _connectionMultiplexerFactory(); _resetConnectionMultiplexer = false; } } } return(_connectionMultiplexer.GetDatabase().WithKeyPrefix(keySpace)); }
public async Task <(IDatabase database, CancellationToken databaseLifetimeToken)> GetDatabaseWithKeyPrefix(Context context, string keySpace) { if (_resetConnectionMultiplexerCts.IsCancellationRequested) { using (await SemaphoreSlimToken.WaitAsync(_creationSemaphore)) { if (_resetConnectionMultiplexerCts.IsCancellationRequested) { context.Debug("Shutting down current connection multiplexer."); // The clients already notified about the cancellation so we just // need to re-create a cancellation token source. _resetConnectionMultiplexerCts = new CancellationTokenSource(); await _connectionMultiplexerShutdownFunc(_connectionMultiplexer); context.Debug("Creating new multiplexer instance."); _connectionMultiplexer = await _connectionMultiplexerFactory(); } } } return(_connectionMultiplexer.GetDatabase().WithKeyPrefix(keySpace), _resetConnectionMultiplexerCts.Token); }