MediatR pipeline for retrying Db deadlocks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Data.Common; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using MediatR; | |
namespace Foo | |
{ | |
public class DbDeadlockRetryHandlerProcessor<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> | |
{ | |
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next) | |
{ | |
// Retry a deadlock 5 times | |
return await HandleWithCountDown(next, 5); | |
} | |
private async Task<TResponse> HandleWithCountDown(RequestHandlerDelegate<TResponse> next, int count) | |
{ | |
TResponse response; | |
try | |
{ | |
response = await next(); | |
} | |
catch (Exception ex) | |
{ | |
// Only catch deadlock exceptions | |
if (count <= 0 || !IsDeadlockException(ex)) | |
{ | |
throw; | |
} | |
await Task.Delay(300); | |
response = await HandleWithCountDown(next, count - 1); | |
} | |
return response; | |
} | |
private static bool IsDeadlockException(Exception ex) | |
{ | |
while (ex != null) | |
{ | |
if (ex is DbException && ex.Message.Contains("deadlock")) | |
{ | |
return true; | |
} | |
ex = ex.InnerException; | |
} | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment