Skip to content

Commit 51044c5

Browse files
authored
[Docs] Add clarification about property precedence (#1918)
1 parent f40fa29 commit 51044c5

File tree

5 files changed

+118
-3
lines changed

5 files changed

+118
-3
lines changed

Diff for: docs/chaos/index.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Chaos strategies (formerly known as Monkey strategies) are in essence a [Resilie
6666
| [Fault](fault.md) | No | Injects exceptions in your system. |
6767
| [Outcome](outcome.md) | Yes | Injects fake outcomes (results or exceptions) in your system. |
6868
| [Latency](latency.md) | No | Injects latency into executions before the calls are made. |
69-
| [Behavior](behavior.md) | No | Allows you to inject *any* extra behaviour, before a call is placed. |
69+
| [Behavior](behavior.md) | No | Allows you to inject *any* extra behavior, before a call is placed. |
7070

7171
## Common options across strategies
7272

@@ -85,6 +85,8 @@ All the strategies' options implement the [`ChaosStrategyOptions`](xref:Polly.Si
8585
| `EnabledGenerator` | `null` | The generator that indicates whether the chaos strategy is enabled for a given execution. |
8686

8787
> [!NOTE]
88+
> If both `InjectionRate` and `InjectionRateGenerator` are specified then `InjectionRate` will be ignored.
89+
>
8890
> If both `Enabled` and `EnabledGenerator` are specified then `Enabled` will be ignored.
8991
9092
[simmy]: https://github.com/Polly-Contrib/Simmy

Diff for: docs/strategies/circuit-breaker.md

+3
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ new ResiliencePipelineBuilder<HttpResponseMessage>().AddCircuitBreaker(optionsSt
105105
| `ManualControl` | `null` | Allows for manual control to isolate or close the circuit. |
106106
| `StateProvider` | `null` | Enables the retrieval of the current state of the circuit. |
107107

108+
> [!NOTE]
109+
> If both `BreakDuration` and `BreakDurationGenerator` are specified then `BreakDuration` will be ignored.
110+
108111
## Diagrams
109112

110113
### State diagram

Diff for: docs/strategies/hedging.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,22 @@ new ResiliencePipelineBuilder<HttpResponseMessage>().AddHedging(optionsDefaults)
6060
## Defaults
6161

6262
| Property | Default Value | Description |
63-
| ------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
63+
|---------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
6464
| `ShouldHandle` | Predicate that handles all exceptions except `OperationCanceledException`. | Predicate that determines what results and exceptions are handled by the retry strategy. |
6565
| `MaxHedgedAttempts` | 1 | The maximum number of hedged actions to use, in addition to the original action. |
6666
| `Delay` | 2 seconds | The maximum waiting time before spawning a new hedged action. |
6767
| `ActionGenerator` | Returns the original callback that was passed to the hedging strategy. | Generator that creates hedged actions. |
68-
| `DelayGenerator` | `null` | Used for generating custom delays for hedging. If `null` then `Delay` is used. |
68+
| `DelayGenerator` | `null` | Used for generating custom delays for hedging. |
6969
| `OnHedging` | `null` | Event that is raised when a hedging is performed. |
7070

7171
You can use the following special values for `Delay` or in `DelayGenerator`:
7272

7373
- `0 seconds` - the hedging strategy immediately creates a total of `MaxHedgedAttempts` and completes when the fastest acceptable result is available.
7474
- `-1 millisecond` - this value indicates that the strategy does not create a new hedged task before the previous one completes. This enables scenarios where having multiple concurrent hedged tasks can cause side effects.
7575

76+
> [!NOTE]
77+
> If both `Delay` and `DelayGenerator` are specified then `Delay` will be ignored.
78+
7679
## Concurrency modes
7780

7881
In the sections below, explore the different concurrency modes available in the hedging strategy. The behavior is primarily controlled by the `Delay` property value.

Diff for: docs/strategies/retry.md

+104
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,110 @@ new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(optionsExtractDela
108108
| `OnRetry` | `null` | Action executed when retry occurs. |
109109
| `MaxDelay` | `null` | Caps the calculated retry delay to a specified maximum duration. |
110110

111+
## Calculation of the next delay
112+
113+
If the `ShouldHandle` predicate returns `true` and the next attempt number is not greater than `MaxRetryAttempts` then the retry strategy calculates the next delay.
114+
115+
There are many properties that may contribute to this calculation:
116+
117+
- `BackoffType`: Specifies which calculation algorithm should run.
118+
- `Delay`: If only this property is specified then it will be used as-is. If others are also specified then this will be used as a *base delay*.
119+
- `DelayGenerator`: If specified, will override other property-based calculations, **except** if it returns `null` or a negative `TimeSpan`, in which case the other property-based calculations are used.
120+
- `MaxDelay`: If specified, caps the delay if the calculated delay is greater than this value, **except** if `DelayGenerator` is used, where no capping is applied.
121+
- `UseJitter`: If enabled, then adds a random value between between -25% of `Delay` and +25% of `Delay`, **except** if `BackoffType` is `Exponential`, where a bit more complex jitter calculation is used.
122+
123+
> [!IMPORTANT]
124+
> The summarized description below is an implementation detail. It may change in the future without notice.
125+
126+
The `BackoffType` property's data type is the [`DelayBackoffType`](xref:Polly.DelayBackoffType) enumeration. This primarily controls how the calculation is done.
127+
128+
### Constant
129+
130+
Even though the `Constant` name could imply that only the `Delay` property is used, in reality all the above listed properties are used.
131+
132+
Step 1: Calculating the base delay:
133+
134+
- If `UseJitter` is set to `false` and `Delay` is specified then `Delay` will be used.
135+
- If `UseJitter` is set to `true` and `Delay` is specified then a random value is added to the `Delay`.
136+
- The random value is between -25% and +25% of `Delay`.
137+
138+
Step 2: Capping the delay if needed:
139+
140+
- If `MaxDelay` is not set then the previously calculated delay will be used.
141+
- If `MaxDelay` is set and the previously calculated delay is greater than `MaxDelay` then `MaxDelay` will be used.
142+
143+
Step 3: Using the generator if supplied
144+
145+
- If the returned `TimeSpan` of the `DelayGenerator` method call is positive then it will be used.
146+
- If the returned `TimeSpan` of the `DelayGenerator` method call is negative then it will use the step 2's result.
147+
- If the `DelayGenerator` method call is `null` then it will use the step 2's result.
148+
149+
> [!NOTE]
150+
> The `DelayGenerator`'s returned value is not capped with the `MaxDelay`.
151+
152+
#### Constant examples
153+
154+
The delays column contains an example series of five values to depict the patterns.
155+
156+
| Settings | Delays in milliseconds |
157+
|--|--|
158+
| `Delay`: `1sec` | [1000,1000,1000,1000,1000] |
159+
| `Delay`: `1sec`, `UseJitter`: `true` | [986,912,842,972,1007] |
160+
| `Delay`: `1sec`, `UseJitter`: `true`, `MaxDelay`: `1100ms` | [1100,978,1100,1041,916] |
161+
162+
### Linear
163+
164+
This algorithm increases the delays for every attempt in a linear fashion if no jitter is used.
165+
166+
Step 1: Calculating the base delay:
167+
168+
- If `UseJitter` is set to `false` and `Delay` is specified then `Delay` multiplied by the actual attempt number will be used.
169+
- If `UseJitter` is set to `true` and `Delay` is specified then a random value is added to the `Delay` multiplied by the actual attempt number.
170+
- The random value is between -25% and +25% of the newly calculated `Delay`.
171+
172+
> [!NOTE]
173+
> Because the jitter calculation is based on the newly calculated delay, the new delay could be less than the previous value.
174+
175+
Step 2 and 3 are the same as for the Constant algorithm.
176+
177+
#### Linear examples
178+
179+
The delays column contains an example series of five values to depict the patterns.
180+
181+
| Settings | Delays in milliseconds |
182+
|--|--|
183+
| `Delay`: `1sec` | [1000,2000,3000,4000,5000] |
184+
| `Delay`: `1sec`, `UseJitter`: `true` | [1129,2147,2334,4894,4102] |
185+
| `Delay`: `1sec`, `UseJitter`: `true`, `MaxDelay`: `4500ms` | [907,2199,2869,4500,4500] |
186+
187+
### Exponential
188+
189+
This algorithm increases the delays for every attempt in an exponential fashion if no jitter is used.
190+
191+
- If `UseJitter` is set to `false` and `Delay` is specified then squaring actual attempt number multiplied by the `Delay` will be used (*`attempt^2 * delay`*).
192+
- If `UseJitter` is set to `true` and the `Delay` is specified then a `DecorrelatedJitterBackoffV2` formula (based on [Polly.Contrib.WaitAndRetry](https://github.com/Polly-Contrib/Polly.Contrib.WaitAndRetry)) will be used.
193+
194+
> [!NOTE]
195+
> Because the jitter calculation is based on the newly calculated delay, the new delay could be less than the previous value.
196+
197+
Step 2 and 3 are the same as for the Constant algorithm.
198+
199+
#### Exponential examples
200+
201+
The delays column contains an example series of five values to depict the patterns.
202+
203+
| Settings | Delays in milliseconds |
204+
|--|--|
205+
| `Delay`: `1sec` | [1000,2000,4000,8000,16000] |
206+
| `Delay`: `1sec`, `UseJitter`: `true` | [393,1453,4235,5369,16849] |
207+
| `Delay`: `1sec`, `UseJitter`: `true`, `MaxDelay`: `15000ms` | [477,793,2227,5651,15000] |
208+
209+
---
210+
211+
> [!TIP]
212+
> For more details please check out the [`RetryHelper`](https://github.com/App-vNext/Polly/blob/main/src/Polly.Core/Retry/RetryHelper.cs)
213+
> and the [`RetryResilienceStrategy`](https://github.com/App-vNext/Polly/blob/main/src/Polly.Core/Retry/RetryResilienceStrategy.cs) classes.
214+
111215
## Diagrams
112216

113217
Let's suppose we have a retry strategy with `MaxRetryAttempts`: `2`.

Diff for: docs/strategies/timeout.md

+3
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ The `OnTimeout` delegate can be useful when you define a resilience pipeline whi
125125
| `TimeoutGenerator` | `null` | Generates the timeout for a given execution. |
126126
| `OnTimeout` | `null` | Event that is raised when timeout occurs. |
127127

128+
> [!NOTE]
129+
> If both `Timeout` and `TimeoutGenerator` are specified then `Timeout` will be ignored.
130+
128131
## Diagrams
129132

130133
### Happy path sequence diagram

0 commit comments

Comments
 (0)