public async Task TryGetCachedResponse() { const int count = 15; // Clear cache var cache = Factory.Services.GetRequiredService <Wivuu.GlobalCache.IGlobalCache>(); await cache.InvalidateAsync(CacheId.ForCategory("weather")); using var client = Factory.CreateClient(); for (var tries = 0; tries < 3; ++tries) { var resp = await client.GetAsync($"weather/us?days={count}"); if (client.DefaultRequestHeaders.TryGetValues("If-None-Match", out _)) { // Expect the response to be empty and not modified Assert.Equal(304, (int)resp.StatusCode); } else { var respBody = await resp.Content.ReadAsStringAsync(); var data = JsonConvert.DeserializeAnonymousType(respBody, new [] { new { Date = default(DateTimeOffset), TemperatureC = default(decimal) } }); Assert.NotNull(data); Assert.Equal(count, data.Length); Assert.NotEqual(default, data[0].Date);
public async Task TestGeneralCaching(Type serializerType, Type storageProviderType) { IServiceProvider services; { var collection = new ServiceCollection(); collection.AddWivuuGlobalCache(settings => { settings.RetryTimeout = TimeSpan.FromSeconds(5); if (!(Activator.CreateInstance(serializerType) is ISerializationProvider serializer)) { throw new Exception($"{serializerType} is not a serialization provider"); } settings.SerializationProvider = serializer; switch (storageProviderType.Name) { case nameof(BlobStorageProvider): var blobServiceClient = new BlobServiceClient("UseDevelopmentStorage=true"); var container = blobServiceClient.GetBlobContainerClient("globalcache"); container.CreateIfNotExists(); settings.StorageProvider = new BlobStorageProvider(container); break; case nameof(FileStorageProvider): settings.StorageProvider = new FileStorageProvider(); break; default: throw new NotSupportedException($"{nameof(storageProviderType)} is not supported"); } }); services = collection.BuildServiceProvider(); } using (var scope = services.CreateScope()) { var cache = scope.ServiceProvider.GetRequiredService <IGlobalCache>(); // Remove item await cache.InvalidateAsync(CacheId.ForCategory("cachetest")); // Get or create item var item = await cache.GetOrCreateAsync(new CacheId("cachetest", "item5"), () => { return(Task.FromResult(new { Item = 5 })); }); Assert.Equal(5, item.Item); } }
public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var hash = CalculateHashCode(context); var id = hash != 0 ? new CacheId(CalculateCategory(context, Category), hash) : CacheId.ForCategory(CalculateCategory(context, Category)); if (context.HttpContext.Items.TryGetValue(ClearCacheId, out var idsObj) && idsObj is Stack <CacheId> ids) { ids.Push(id); } else { context.HttpContext.Items.TryAdd(ClearCacheId, new Stack <CacheId>(new [] { id })); } return(next()); }
public async Task TestStorageRemove(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 id1 = new CacheId("remove", 1); var id2 = new CacheId("remove", 2); // Write two values var val1 = await OpenReadWriteAsync(id1, onWrite : stream => { stream.WriteByte(1); return(Task.FromResult(1)); }); var val2 = await OpenReadWriteAsync(id2, onWrite : stream => { stream.WriteByte(2); return(Task.FromResult(2)); }); // Clear 1 value Assert.True(await store.RemoveAsync(id1), "id1 should have been removed"); await CheckRemoved(id1, 1); // Check 2 still exists Assert.Equal(val2, await OpenReadWriteAsync(id2, onRead: stream => Task.FromResult(stream.ReadByte()))); // Clear ALL values Assert.True(await store.RemoveAsync(CacheId.ForCategory("remove")), "id1 and id2 should have been removed"); await CheckRemoved(id2, 2); async Task CheckRemoved(CacheId id, byte notExpected) { try { using var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromMilliseconds(20)); var value = await OpenReadWriteAsync( id, onRead : stream => Task.FromResult(stream.ReadByte()), cancellationToken : cts.Token ); if (value == notExpected) { throw new Exception($"Item {id} should have been removed"); } } catch (TaskCanceledException) { // Pass } } async Task <T> OpenReadWriteAsync <T>(CacheId id, Func <Stream, Task <T> >?onWrite = null, Func <Stream, Task <T> >?onRead = null, CancellationToken cancellationToken = default)