public async Task MemoizeAsync_ExistingItemReceivedRevokeAndCallAfterRevokeReturnsAnIgnoredResponseAndSettingIsTryFetchNewValueNextTimeOrUseOld_AfterRevokeCacheIsUsedAndCallIsMadeToDataSourceAndIgnored() { var firstResult = "first result"; var secondResult = "second result"; var dataSource = CreateRevokableDataSource(new[] { "revokeKey" }, firstResult, null, secondResult); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); var result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings()); result.Value.Id.ShouldBe(firstResult); dataSource.Received(1).ThingifyTaskRevokable("someString"); //New item - fetch from datasource //Post revoke message revokesSource.PostMessageSynced("revokeKey"); //We want to test that revoked item is returned (because data source response should be ignored) result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(revokedResponseBehavior: RevokedResponseBehavior.TryFetchNewValueNextTimeOrUseOld, responseKindsToCache: ResponseKinds.NonNullResponse, responseKindsToIgnore: ResponseKinds.NullResponse)); result.Value.Id.ShouldBe(firstResult); //we use old cached value dataSource.Received(2).ThingifyTaskRevokable("someString"); //tried to fetch from data source (and ignored) //Cached item is still revoked, so we do another call to data source and get a new valid response result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(revokedResponseBehavior: RevokedResponseBehavior.TryFetchNewValueNextTimeOrUseOld)); result.Value.Id.ShouldBe(secondResult); //get new value dataSource.Received(3).ThingifyTaskRevokable("someString"); }
public async Task MemoizeAsync_ExistingItemReceivedRevokeAndSettingIsTryFetchNewValueInBackgroundNextTime_AfterRevokeCacheIsUsedAndItemIsFetchedFromDataSourceInTheBackround() { var firstResult = "first result"; var secondResult = "second result"; var dataSource = CreateRevokableDataSource(new[] { "revokeKey" }, firstResult, secondResult); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); var result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings()); result.Value.Id.ShouldBe(firstResult); dataSource.Received(1).ThingifyTaskRevokable("someString"); //New item - fetch from datasource //Post revoke message revokesSource.PostMessageSynced("revokeKey"); //We want to test that revoked item is used and we fetch a new item from data source in the backround result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(revokedResponseBehavior: RevokedResponseBehavior.TryFetchNewValueInBackgroundNextTime)); result.Value.Id.ShouldBe(firstResult); //Use old cached value dataSource.Received(2).ThingifyTaskRevokable("someString"); //A backround call to the data source is made //After backround call is done, we should get new result result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(revokedResponseBehavior: RevokedResponseBehavior.TryFetchNewValueInBackgroundNextTime)); result.Value.Id.ShouldBe(secondResult); dataSource.Received(2).ThingifyTaskRevokable("someString"); //No additional data source call }
//Bug #134604 public async Task MemoizeAsync_ExistingItemWasRefreshedByTtlAndReciviedRevoke_AfterRevokeCacheIsNotUsedAndItemIsFetchedFromDataSource() { var completionSource = new TaskCompletionSource <Revocable <Thing> >(); completionSource.SetResult(new Revocable <Thing> { Value = new Thing { Id = "first Value" }, RevokeKeys = new[] { "revokeKey" } }); var dataSource = CreateRevokableDataSource(null, completionSource); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); //To cause refresh in next call await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(refreshTimeSeconds: 0)); dataSource.Received(1).ThingifyTaskRevokable("someString"); //New item - fetch from datasource await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings()); dataSource.Received(2).ThingifyTaskRevokable("someString"); //Refresh task - fetch from datasource //Post revoke message revokesSource.PostMessageSynced("revokeKey"); //We want to test that item was removed from cache after revoke and that new item is fetched from datasource await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings()); dataSource.Received(3).ThingifyTaskRevokable("someString"); //Revoke received and item removed from cache - fetch from datasource }
public async Task MemoizeAsync_RevokeBeforeRetrivalTaskCompletedCaused_NoIssues() { var completionSource = new TaskCompletionSource <Revocable <Thing> >(); var dataSource = CreateRevokableDataSource(null, completionSource); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); //Call method to get results var resultTask = (Task <Revocable <Thing> >)memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()); //Post revoke message while results had not arrived revokesSource.PostMessageSynced("revokeKey"); //Wait before sending results await Task.Delay(100); completionSource.SetResult(new Revocable <Thing> { Value = new Thing { Id = 5 }, RevokeKeys = new[] { "revokeKey" } }); //Results should arive now var actual = await resultTask; dataSource.Received(1).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(5); cache.CacheKeyCount.ShouldBe(1); }
public async Task MemoizeAsync_RevokableObjectShouldBeCachedAndRevoked() { var dataSource = CreateRevokableDataSource(new[] { "revokeKey" }, 5, 6); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); var actual = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()); dataSource.Received(1).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(5); //Read value from cache should be still 5 actual = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()); dataSource.Received(1).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(5); //A single cache key should be stored in index cache.CacheKeyCount.ShouldBe(1); //Post revoke message, no cache keys should be stored revokesSource.PostMessageSynced("revokeKey"); cache.CacheKeyCount.ShouldBe(0); //Value should change to 6 actual = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()); dataSource.Received(2).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(6); cache.CacheKeyCount.ShouldBe(1); //Post revoke message to not existing key value still should be 6 revokesSource.PostMessageSynced("NotExistin-RevokeKey"); actual = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()); dataSource.Received(2).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(6); cache.CacheKeyCount.ShouldBe(1); }
public async Task MemoizeAsync_RevokeBeforeRetrivalTaskCompletedCaused_NoIssues() { var completionSource = new TaskCompletionSource <Revocable <Thing> >(); var dataSource = CreateRevokableDataSource(null, completionSource); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); //Call method to get results var resultTask = (Task <Revocable <Thing> >)memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()); //Post revoke message while results had not arrived revokesSource.PostMessageSynced("revokeKey"); //Should have a single discarded revoke in meter GetMetricsData("Revoke").AssertEquals(new MetricsDataEquatable { MetersSettings = new MetricsCheckSetting { CheckValues = true }, Meters = new List <MetricDataEquatable> { new MetricDataEquatable { Name = "Discarded", Unit = Unit.Events, Value = 1 }, } }); //Wait before sending results await Task.Delay(100); completionSource.SetResult(new Revocable <Thing> { Value = new Thing { Id = 5 }, RevokeKeys = new[] { "revokeKey" } }); //Results should arive now var actual = await resultTask; dataSource.Received(1).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(5); cache.CacheKeyCount.ShouldBe(1); }
public async Task MemoizeAsync_ExistingItemReceivedRevokeAndSettingIsKeepUsingRevokedResponse_AfterRevokeCacheIsUsedAndNoCallIsMadeToDataSource() { var firstResult = "first result"; var dataSource = CreateRevokableDataSource(new [] { "revokeKey" }, firstResult); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); var result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings()); result.Value.Id.ShouldBe(firstResult); dataSource.Received(1).ThingifyTaskRevokable("someString"); //New item - fetch from datasource //Post revoke message revokesSource.PostMessageSynced("revokeKey"); //We want to test that revoked item is still in cache and returned result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(revokedResponseBehavior: RevokedResponseBehavior.KeepUsingRevokedResponse)); result.Value.Id.ShouldBe(firstResult); dataSource.Received(1).ThingifyTaskRevokable("someString"); //Revoke received and item was not removed from cache - do not fetch from datasource }
public async Task MemoizeAsync_ExistingItemReceivedRevokeAndSettingIsTryFetchNewValueNextTimeOrUseOld_AfterRevokeCacheIsNotUsedAndItemIsFetchedFromDataSource() { var firstResult = "first result"; var secondResult = "second result"; var dataSource = CreateRevokableDataSource(new[] { "revokeKey" }, firstResult, secondResult); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); var result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings()); result.Value.Id.ShouldBe(firstResult); dataSource.Received(1).ThingifyTaskRevokable("someString"); //New item - fetch from datasource //Post revoke message revokesSource.PostMessageSynced("revokeKey"); //We want to test that revoked item is ignored and we fetch a new item from data source result = await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetCachingSettings(revokedResponseBehavior: RevokedResponseBehavior.TryFetchNewValueNextTimeOrUseOld)); result.Value.Id.ShouldBe(secondResult); dataSource.Received(2).ThingifyTaskRevokable("someString"); }
public async Task MemoizeAsync_RevokableObjectShouldBeCachedAndRevoked() { var dataSource = CreateRevokableDataSource(new[] { "revokeKey" }, 5, 6); var revokesSource = new OneTimeSynchronousSourceBlock <string>(); var cache = CreateCache(revokesSource); var memoizer = CreateMemoizer(cache); var actual = await CallWithMemoize(memoizer, dataSource); dataSource.Received(1).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(5); //Read value from cache should be still 5 actual = await CallWithMemoize(memoizer, dataSource); dataSource.Received(1).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(5); //A single cache key should be stored in index cache.CacheKeyCount.ShouldBe(1); //No metric for Revoke GetMetricsData("Revoke").AssertEquals(new MetricsDataEquatable { Meters = new List <MetricDataEquatable> () }); //Post revoke message, no cache keys should be stored revokesSource.PostMessageSynced("revokeKey"); cache.CacheKeyCount.ShouldBe(0); //Should have a single revoke in meter GetMetricsData("Revoke").AssertEquals(new MetricsDataEquatable { MetersSettings = new MetricsCheckSetting { CheckValues = true }, Meters = new List <MetricDataEquatable> { new MetricDataEquatable { Name = "Succeeded", Unit = Unit.Events, Value = 1 }, } }); //Should have a single item removed in meter GetMetricsData("Items").AssertEquals(new MetricsDataEquatable { MetersSettings = new MetricsCheckSetting { CheckValues = true }, Meters = new List <MetricDataEquatable> { new MetricDataEquatable { Name = CacheEntryRemovedReason.Removed.ToString(), Unit = Unit.Items, Value = 1 }, } }); //Value should change to 6 actual = await CallWithMemoize(memoizer, dataSource); dataSource.Received(2).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(6); cache.CacheKeyCount.ShouldBe(1); //Post revoke message to not existing key value still should be 6 revokesSource.PostMessageSynced("NotExistin-RevokeKey"); actual = await CallWithMemoize(memoizer, dataSource); dataSource.Received(2).ThingifyTaskRevokable("someString"); actual.Value.Id.ShouldBe(6); cache.CacheKeyCount.ShouldBe(1); }