Skip to content

Instantly share code, notes, and snippets.

@vkhorikov
Created July 2, 2019 02:47
Show Gist options
  • Save vkhorikov/4c386608ada3323e969828f6230f2430 to your computer and use it in GitHub Desktop.
Save vkhorikov/4c386608ada3323e969828f6230f2430 to your computer and use it in GitHub Desktop.
Decorators for both commands and queries
public sealed class DatabaseCommandRetryDecorator<TCommand> : DatabaseRetryDecorator, ICommandHandler<TCommand>
where TCommand : ICommand
{
private readonly ICommandHandler<TCommand> _handler;
public DatabaseCommandRetryDecorator(ICommandHandler<TCommand> handler, Config config)
: base(config)
{
_handler = handler;
}
public Result Handle(TCommand command)
{
return InvokeWithRetry(_handler.Handle, command);
}
}
public sealed class DatabaseQueryRetryDecorator<TQuery, TResult> : DatabaseRetryDecorator, IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
{
private readonly IQueryHandler<TQuery, TResult> _handler;
public DatabaseQueryRetryDecorator(IQueryHandler<TQuery, TResult> handler, Config config)
: base(config)
{
_handler = handler;
}
public TResult Handle(TQuery query)
{
return InvokeWithRetry(_handler.Handle, query);
}
}
public abstract class DatabaseRetryDecorator
{
private readonly Config _config;
protected DatabaseRetryDecorator(Config config)
{
_config = config;
}
protected TOut InvokeWithRetry<TIn, TOut>(Func<TIn, TOut> func, TIn parameter)
{
for (int i = 0; ; i++)
{
try
{
TOut result = func(parameter);
return result;
}
catch (Exception ex)
{
if (i >= _config.NumberOfDatabaseRetries || !IsDatabaseException(ex))
throw;
}
}
}
private bool IsDatabaseException(Exception exception)
{
string message = exception.InnerException?.Message;
if (message == null)
return false;
return message.Contains("The connection is broken and recovery is not possible")
|| message.Contains("error occurred while establishing a connection");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment