public async Task ExecuteAsync_MultiplePolicies_WorkAsExpected() { // cache string url = "/api/cache"; string result = await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey1")); // typically cache key would be dynamic string result2 = await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey1")); Assert.IsTrue(!string.IsNullOrWhiteSpace(result)); Assert.AreEqual(result, result2); // inner timeout (500 ms), retry (5), outer timeout (this will exception as the inner timeouts will be retried enough times to trigger outer timeout) url = "/api/timeout/slow"; bool timeout = false; try { await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey2")); } catch (TimeoutRejectedException) { timeout = true; } Assert.IsTrue(timeout); // trying this again will trip circuit breaker before we get a chance to hit the outer timeout bool circuitIsBroken = false; try { string result3 = await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey3")); } catch (BrokenCircuitException) { circuitIsBroken = true; } Assert.IsTrue(circuitIsBroken); // lets try a fallback url = "/api/circuitbreaker/success"; var fallbackWrapper = FallbackPolicy <string> .Handle <Exception>() .FallbackAsync(context => Task.Run(() => "default")) .WrapAsync(_policyWrapper); string result4 = await fallbackWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey4")); Assert.AreEqual("default", result4); // let circuit breaker reset Task.Delay(3000).Wait(); string result5 = await fallbackWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey5")); Assert.IsTrue(!string.IsNullOrWhiteSpace(result5)); Assert.AreNotEqual("default", result5); }
private async Task <string> CallApiWithFallback(string action, Func <Task <string> > fallback) { var fallbackWrapper = FallbackPolicy <string> .Handle <Exception>() .FallbackAsync(context => fallback()) .WrapAsync(_circuitBreaker); string response = await fallbackWrapper.ExecuteAsync(async context => await _client.GetStringAsync($"{_url}/{action}"), new Context()); return(response); }