When a handler constructor throws an exception, a subsequent request hangs indefinitely.
Mediator 3.0.2 dotnet 10
Steps to reproduce
- Handler constructor throws an exception on the first attempt.
- Send another request through Mediator.
Expected behavior
The next request should retry handler creation or return an exception.
Actual behavior
The second attempt enters an infinite spin wait.
This appears to be related to FastLazyValue remaining in the INITING state after an exception.
Reproduction
#:property TargetFramework=net10.0
#:package Mediator.Abstractions@3.0.2
#:package Mediator.SourceGenerator@3.0.2
#:package Microsoft.Extensions.DependencyInjection@10.0.0
using Mediator;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddMediator();
await using var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
Console.WriteLine("first call");
try
{
await mediator.Send(new Request());
}
catch (Exception ex)
{
Console.WriteLine($"first call failed: {ex.GetType().Name}: {ex.Message}");
}
Console.WriteLine("second call");
await mediator.Send(new Request()); //hangs forever
Console.WriteLine("second call finished - ok");
public sealed record Request() : IRequest<string>;
public sealed class Handler : IRequestHandler<Request, string>
{
private static int _constructorAttempts;
public Handler()
{
var attempt = Interlocked.Increment(ref _constructorAttempts);
Console.WriteLine($"Handler constructor attempt - {attempt}");
if (attempt == 1)
{
throw new InvalidOperationException("Failing first constructor call");
}
Console.WriteLine("Handler constructor succeeded");
}
public ValueTask<string> Handle(Request request, CancellationToken cancellationToken)
=> ValueTask.FromResult("result");
}
When a handler constructor throws an exception, a subsequent request hangs indefinitely.
Mediator 3.0.2 dotnet 10
Steps to reproduce
Expected behavior
The next request should retry handler creation or return an exception.
Actual behavior
The second attempt enters an infinite spin wait.
This appears to be related to FastLazyValue remaining in the INITING state after an exception.
Reproduction