# Polly
## 新手入門
## Polly 是什麼
> Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, Rate-limiting and Fallback in a fluent and thread-safe manner.
Google 翻譯告訴我,它是...
> Polly 是一個 .NET 彈性和瞬態故障處理庫,允許開發人員以流暢和線程安全的方式表達重試、斷路器、超時、隔板隔離、速率限制和回退等策略。
總結一下,它能幫我們做什麼 ?
1. 簡單的Retry策略
2. 斷路器
3. 限速器
4. 控制Thread數量
5. Cache
6. FallBack策略
7. .....
### 第一次不通,那可以打第二次、第三次阿 (Retry)
有些Api的是允許Retry的,如果說第一次打不通,那可以試試看打第二次,這時候會用到Retry這個特性
```
var asyncRetryPolicy = Policy.Handle<Exception>()
.OrResult<HttpResponseMessage>(x => x.IsSuccessStatusCode)
.RetryAsync(retryCount: 3,
(onRetry: delegatedResult, retryCount, context) =>
{
context["RetryCount"] = retryCount;
});
var httpResponseMessage = await asyncRetryPolicy
.ExecuteAsync(async context =>
{
var retryCount = (int)context["RetryCount"];
//// Call Api and return HttpResponseMessage
},
new Context { ["RetryCount"] = 0 });
```
### 另外一種Retry,過幾秒再問 (Wait And Retry)
```
var asyncRetryPolicy = Policy.Handle<Exception>()
.OrResult<HttpResponseMessage>(x => x.IsSuccessStatusCode)
.WaitAndRetryAsync(retryCount: 3,
sleepDurationProvider: currentCount => TimeSpan.FromSeconds(currentCount),
onRetry: (delegatedResult, timeSpan, context) =>
{
//// do something
});
```
### 對接Api壞掉了😢 (Circuit-breaker)
如果對接Api壞掉了,那我們是不是可以過段時間再問問 ?
```
Policy.Handle<Exception>()
.CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: 2,
durationOfBreak: TimeSpan.FromSeconds(2),
onBreak: (exception, timespan) =>
{
//// Do something when circuit break
},
onReset: () =>
{
//// Do something when circuit reset
});
```
### 不要打太快 (Rate-limit)
```
Policy.RateLimitAsync<HttpResponseMessage>(
numberOfExecutions: 5,
perTimeSpan: TimeSpan.FromSeconds(3),
maxBurst: 5);
```
### 同時最高執行數量 (Bulkhead Isolation)
```
Policy.BulkheadAsync<HttpResponseMessage>(
maxParallelization: 5,
maxQueuingActions: 2,
onBulkheadRejectedAsync: context =>
{
//// Do Something
});
```
### Cache (Cache)
```
var asyncCachePolicy = Policy
.CacheAsync<HttpResponseMessage>(cacheProvider: memoryCacheProvider,
ttl: TimeSpan.FromMinutes(5),
onCacheError: (context, key, ex) =>
{
//// Do something when Cache Error
});
var httpResponseMessage = await asyncCachePolicy
.ExecuteAsync(context =>
{
//// Do something
},
new Context("OpenDataKey"));
```
### 錯誤處理 (Fallback)
```
Policy<HttpResponseMessage>
.Handle<Exception>()
.OrResult(x => x.IsSuccessStatusCode == false)
.FallbackAsync(fallbackAction: cancellationToken =>
{
//// Do something
},
onFallbackAsync: delegatedResult =>
{
//// Do something
});
```
### 同時需要好幾個特性 (PolicyWrap)
```
Policy.WrapAsync(
Policy.CacheAsync<HttpResponseMessage>(
cacheProvider: new Extension.MemoryCacheProvider(new MemoryCache(new MemoryCacheOptions())),
ttl: TimeSpan.FromSeconds(5)),
Policy<HttpResponseMessage>.Handle<Exception>()
.RetryAsync(retryCount: 3,
onRetry: (_, retryCount, context) =>
{
//// Do something
})
);
```