private SemaphoreSlim GetOrCreateLock( string key, DistributedCacheEntryOptions?distributedCacheEntryOptions) { KeySemaphore.Wait(); try { return(L1Cache.GetOrCreate( $"{L1L2RedisCacheOptions.LockKeyPrefix}{key}", cacheEntry => { cacheEntry.AbsoluteExpiration = distributedCacheEntryOptions?.AbsoluteExpiration; cacheEntry.AbsoluteExpirationRelativeToNow = distributedCacheEntryOptions?.AbsoluteExpirationRelativeToNow; cacheEntry.SlidingExpiration = distributedCacheEntryOptions?.SlidingExpiration; return new SemaphoreSlim(1, 1); }) ?? new SemaphoreSlim(1, 1)); } finally { KeySemaphore.Release(); } }
private async Task <SemaphoreSlim> GetOrCreateLockAsync( string key, DistributedCacheEntryOptions?distributedCacheEntryOptions, CancellationToken cancellationToken = default) { await KeySemaphore.WaitAsync(cancellationToken); try { return(await L1Cache.GetOrCreateAsync( $"{L1L2RedisCacheOptions.LockKeyPrefix}{key}", cacheEntry => { cacheEntry.AbsoluteExpiration = distributedCacheEntryOptions?.AbsoluteExpiration; cacheEntry.AbsoluteExpirationRelativeToNow = distributedCacheEntryOptions?.AbsoluteExpirationRelativeToNow; cacheEntry.SlidingExpiration = distributedCacheEntryOptions?.SlidingExpiration; return Task.FromResult(new SemaphoreSlim(1, 1)); }) ?? new SemaphoreSlim(1, 1)); } finally { KeySemaphore.Release(); } }
public void SemaphoreWithKeyDecorator_SingleConcurrency_KeySemaphore_No_KeySelector_Tests() { var keySemaphore = new KeySemaphore <string>(1, StringComparer.OrdinalIgnoreCase); Assert.Throws <KeySelectorMissingException>( () => { Create.SimpleFunc <string>(b => b.FireAndForget().Semaphore(c => c.KeySemaphore(keySemaphore)).Handler(async m => { await Task.Delay(500); })); }); }
public async Task SemaphoreWithKeyDecorator_SingleConcurrency_KeySemaphore_Tests() { var count = 0; var keySemaphore = new KeySemaphore <string>(1, StringComparer.OrdinalIgnoreCase); var func = Create.SimpleFunc <string>( b => b .FireAndForget() .Semaphore(c => c.KeySemaphore(keySemaphore).KeySelector(m => m)) .Handler( async m => { await Task.Delay(500); Interlocked.Increment(ref count); })); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed func("A"); func("a"); func("a"); func("a"); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed await Task.Delay(200); Assert.Equal(0, count); await Task.Delay(600); Assert.Equal(1, count); await Task.Delay(500); Assert.Equal(2, count); }
/// <summary> /// Sets the key semaphore /// </summary> /// <typeparam name="TKeyType">The key types</typeparam> /// <param name="keySemaphore">A key semaphore</param> /// <returns>A SemaphoreWithKeyDecoratorBuilder</returns> public SemaphoreWithKeyDecoratorBuilder <TMessageType, TKeyType> KeySemaphore <TKeyType>(KeySemaphore <TKeyType> keySemaphore) { var newBuilder = new SemaphoreWithKeyDecoratorBuilder <TMessageType, TKeyType>().MaxNumberOfConcurrentMessages(this.maxNumberOfConcurrentMessages) .KeySemaphore(keySemaphore); this.buildFunc = newBuilder.Build; return(newBuilder); }