Resilience
Timeout
Set execution time limits for handlers
The timeout behavior cancels handler execution if it exceeds a configured duration, preventing slow operations from blocking indefinitely.
Using the Attribute
[Timeout(5000)] // 5 seconds
public record GenerateReportQuery(DateRange Range) : IQuery<Report>;Using Configuration
builder.Services.AddTurboMediator(m =>
{
m.WithTimeout<GenerateReportQuery, Report>(TimeSpan.FromSeconds(5));
});How It Works
The behavior races the handler execution against a Task.Delay:
- Starts the handler and a delay timer in parallel
- If the handler completes first → returns the result
- If the timer completes first → throws
TimeoutException
Practical Example
// Slow external API call with 3-second timeout
[Timeout(3000)]
public record FetchWeatherQuery(string City) : IQuery<WeatherData>;
public class FetchWeatherHandler : IQueryHandler<FetchWeatherQuery, WeatherData>
{
private readonly HttpClient _httpClient;
public FetchWeatherHandler(HttpClient httpClient) => _httpClient = httpClient;
public async ValueTask<WeatherData> Handle(
FetchWeatherQuery query, CancellationToken ct)
{
var response = await _httpClient.GetFromJsonAsync<WeatherData>(
$"/api/weather/{query.City}", ct);
return response!;
}
}
// Usage
try
{
var weather = await mediator.Send(new FetchWeatherQuery("London"));
}
catch (TimeoutException)
{
// Handler took too long
return Results.StatusCode(504);
}Combining with Retry
Timeout works well with retry — each attempt has its own timeout:
[Retry(maxAttempts: 3, delayMilliseconds: 500)]
[Timeout(2000)]
public record CallApiCommand(string Endpoint) : ICommand<ApiResponse>;