Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Add an antipattern to the DI documentation page #1624

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
58 changes: 58 additions & 0 deletions docs/advanced/dependency-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,61 @@ ResiliencePipeline instanceA = pipelineProvider.GetPipeline(new MyPipelineKey("m
ResiliencePipeline instanceB = pipelineProvider.GetPipeline(new MyPipelineKey("my-pipeline", "instance-B"));
```
<!-- endSnippet -->


## Patterns and Anti-patterns
peter-csala marked this conversation as resolved.
Show resolved Hide resolved

Over the years, many developers have used Polly in various ways. Some of these recurring patterns may not be ideal. This section highlights the recommended practices and those to avoid.

### 1 - Accessing the `IServiceCollection` instead of `IServiceProvider`

❌ DON'T

Capture `IServiceCollection` inside `AddResiliencePipeline`
peter-csala marked this conversation as resolved.
Show resolved Hide resolved

<!-- snippet: di-anti-pattern-1 -->
```cs
var services = new ServiceCollection();
services.AddResiliencePipeline("myFavoriteStrategy", builder =>
{
builder.AddRetry(new()
{
OnRetry = args =>
{
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger>();
// ...
return ValueTask.CompletedTask;
peter-csala marked this conversation as resolved.
Show resolved Hide resolved
}
});
});
```
<!-- endSnippet -->

**Reasoning**:
peter-csala marked this conversation as resolved.
Show resolved Hide resolved
This approach builds a new `ServiceProvider` before each retry attempt _unnecessarily_.

✅ DO

Use another overload of `AddResiliencePipeline` which allows access to `IServiceProvider`
peter-csala marked this conversation as resolved.
Show resolved Hide resolved

<!-- snippet: di-pattern-1 -->
```cs
var services = new ServiceCollection();
services.AddResiliencePipeline("myFavoriteStrategy", static (builder, context) =>
{
builder.AddRetry(new()
{
OnRetry = args =>
{
var logger = context.ServiceProvider.GetService<ILogger>();
// ...
return ValueTask.CompletedTask;
peter-csala marked this conversation as resolved.
Show resolved Hide resolved
}
});
});
```
<!-- endSnippet -->

**Reasoning**:
peter-csala marked this conversation as resolved.
Show resolved Hide resolved
This approach uses the already built `ServiceProvider` and uses the same instance before every retry attempts.
3 changes: 2 additions & 1 deletion docs/strategies/circuit-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ await manualControl.CloseAsync();


## Patterns and Anti-patterns
Throughout the years many people have used Polly in so many different ways. Some reoccuring patterns are suboptimal. So, this section shows the donts and dos.

Over the years, many developers have used Polly in various ways. Some of these recurring patterns may not be ideal. This section highlights the recommended practices and those to avoid.

### 1 - Using different sleep duration between retry attempts based on Circuit Breaker state

Expand Down
39 changes: 39 additions & 0 deletions src/Snippets/Docs/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,43 @@ public static async Task ConfigureRegistry(IServiceProvider serviceProvider)

#endregion
}

public static void AntiPattern_1()
{
#region di-anti-pattern-1
var services = new ServiceCollection();
services.AddResiliencePipeline("myFavoriteStrategy", builder =>
{
builder.AddRetry(new()
{
OnRetry = args =>
{
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger>();
// ...
return ValueTask.CompletedTask;
}
});
});
#endregion
}

public static void Pattern_1()
{
#region di-pattern-1
var services = new ServiceCollection();
services.AddResiliencePipeline("myFavoriteStrategy", static (builder, context) =>
{
builder.AddRetry(new()
{
OnRetry = args =>
{
var logger = context.ServiceProvider.GetService<ILogger>();
// ...
return ValueTask.CompletedTask;
}
});
});
#endregion
}
}
Loading