Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/advanced/resilience-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ The resilience context exposes several properties:
- `Properties`: An instance of `ResilienceProperties` for attaching custom data to the context.
- `ContinueOnCapturedContext`: Specifies whether the asynchronous execution should continue on the captured context.

> [!IMPORTANT]
> When using a custom `ResilienceContext`, ensure that your usage is correct to avoid the context being treated as custom
> _state_ for the execution instead of as the _context_ for the execution. Otherwise, the delegate invoked by the resilience
> pipeline will be a different instance obtained from the shared pool, rather than the value specified for your execution.

## Usage

Below is an example demonstrating how to work with `ResilienceContext`:
Expand Down
50 changes: 50 additions & 0 deletions test/Polly.Core.Tests/Issues/IssuesTests .OnRetryContext_2597.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace Polly.Core.Tests.Issues;

public partial class IssuesTests
{
[Fact]
public async Task OnRetry_Contains_User_Context_2597()
{
// Arrange
var propertyKey = Guid.NewGuid().ToString();
var propertyValue = Guid.NewGuid().ToString();

var key = new ResiliencePropertyKey<string>(propertyKey);

var pipeline = new ResiliencePipelineBuilder()
.AddRetry(new()
{
MaxRetryAttempts = 2,
OnRetry = (args) =>
{
args.Context.Properties.TryGetValue(key, out var actualValue).ShouldBeTrue();
actualValue.ShouldBe(propertyValue);
return default;
}
})
.Build();

var executed = false;

// Act
var context = ResilienceContextPool.Shared.Get();
context.Properties.Set(key, propertyValue);

var actual = await Should.ThrowAsync<InvalidOperationException>(
async () => await pipeline.ExecuteAsync(
(context) =>
{
context.Properties.TryGetValue(key, out var actualValue).ShouldBeTrue();
actualValue.ShouldBe(propertyValue);

executed = true;

throw new InvalidOperationException(propertyValue);
},
context));

// Assert
actual.Message.ShouldBe(propertyValue);
executed.ShouldBeTrue();
}
}