Exemplo n.º 1
0
        public async Task TestStorageConcurrence(Type storageProviderType)
        {
            IStorageProvider store;

            switch (storageProviderType.Name)
            {
            case nameof(BlobStorageProvider):
                var blobServiceClient = new BlobServiceClient("UseDevelopmentStorage=true");
                var container         = blobServiceClient.GetBlobContainerClient("globalcache");
                await container.CreateIfNotExistsAsync();

                store = new BlobStorageProvider(container);
                break;

            case nameof(FileStorageProvider):
                store = new FileStorageProvider();
                break;

            default:
                throw new NotSupportedException($"{nameof(storageProviderType)} is not supported");
            }

            var id     = new CacheId("concurrence", 1);
            var str    = "hello world" + Guid.NewGuid();
            var writes = 0;

            await store.RemoveAsync(id);

            await Task.WhenAll(new []
            {
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                store.RemoveAsync(id),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                store.RemoveAsync(id),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                store.RemoveAsync(id),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
                GetOrCreateAsync().ContinueWith(task => Assert.Equal(str, task.Result)),
            });

            // await store.RemoveAsync(id);

            async Task <string> GetOrCreateAsync()
            {
                var retries = new RetryHelper(1, 500, totalMaxDelay: TimeSpan.FromSeconds(60));

                do
                {
                    if (await store.TryOpenRead(id) is Stream readStream)
                    {
                        using (readStream)
                        {
                            using var sr = new StreamReader(readStream);

                            return(await sr.ReadToEndAsync());
                        }
                    }

                    if (await store.TryOpenWrite(id) is StreamWithCompletion writeStream)
                    {
                        using (writeStream)
                        {
                            // !!!!Expensive data generation here!!!!
                            await writeStream.WriteAsync(Encoding.Default.GetBytes(str !));

                            Interlocked.Increment(ref writes);
                            // !!!!
                        }

                        await writeStream;
                        return(str !);
                    }

                    if (await retries.DelayAsync().ConfigureAwait(false) == false)
                    {
                        throw new TimeoutException();
                    }
                }while (true);
            }
        }