jbogard / MediatR

Simple, unambitious mediator implementation in .NET
Apache License 2.0
11k stars 1.16k forks source link

Timeout behavior support #1058

Open zachpainter77 opened 1 month ago

zachpainter77 commented 1 month ago

This PR adds support for creating a timeout behavior.

This PR is in direct response to #1065, and the long discussion of #592. This was an older issue turned to discussion. I have solved the issue with the below implementation.

The below implementation modifies the RequestHandlerDelegate to take an optional CancellationToken. I also modify the RequestHandlerWrapperImpl to match the delegate so the casting still works. Then I modify the Aggregation to pass the token into the handle method for the next handler.

Usage:

 public class TimeoutBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
     where TRequest : notnull
 {
     public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
     {
         using (var cts = new CancellationTokenSource(someTimeoutDuration))
         {
             return await next(cts.Token);
         }
     }
 }

Test Handler:

 public class TimeoutRequestHandler : IRequestHandler<TimeoutRequest>
 {
     private readonly Dependency _dependency;

     public TimeoutRequestHandler(Dependency dependency) => _dependency = dependency;

     public async Task Handle(TimeoutRequest request, CancellationToken cancellationToken)
     {
         await Task.Delay(someTimeThatIsLongerThanTheTimeoutDuration, cancellationToken);

         _dependency.Called = true;
     }
 }

Unit Test:

 [Fact]
 public async Task TimeoutBehavior_Void_Should_Cancel_Long_Running_Task_And_Throw_Exception()
 {
     var request = new TimeoutRequest();

     var exception = await Should.ThrowAsync<TaskCanceledException>(() => _mediator.Send(request));

     exception.ShouldNotBeNull();
     exception.ShouldBeAssignableTo<TaskCanceledException>();
     _dependency.Called.ShouldBeFalse();
 }
github-actions[bot] commented 1 week ago

This PR is stale because it has been open 28 days with no activity. Remove stale label or comment or this will be closed in 14 days.

dazinator commented 1 week ago

not stale.. still waiting for feedback and hopeful merge..