ASP.NET C # Ejecución de consulta MySQL reintentar cuando falla

asp.net c# dapper mysql

Pregunta

¿Hay algún paquete / DLL ASP.NET que permita la ejecución de la consulta MySQL para volver a intentarlo en caso de falla?

He leído sobre Transient Fault Handling e incluso encontré un problema de Dapper que muestra un ejemplo, pero según mi investigación, esto solo funciona con SqlServer y / o Azure.

Mi stack tecnológico es el siguiente:

  • .NET 4.5.2
  • Dapper 1.50.2.0
  • MySQL 5.6 (usando Amazon Aurora)

En última instancia, estoy tratando de resolver un problema de falla esporádica y creo que implementar alguna lógica de reintento ayudaría a aliviar el problema.

Intenté implementar algún código de este problema Dapper, pero debido a que estoy usando MySql.Data para conectarme a mi base de datos MySql, no funciona con los diversos métodos que son específicos de las conexiones SqlServer.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Dapper;
using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;

namespace TransientDapper
{
    public static class TransientDapperExtensions
    {
        private static readonly RetryManager SqlRetryManager = GetDefaultRetryManager();
        private static readonly RetryPolicy SqlCommandRetryPolicy = SqlRetryManager.GetDefaultSqlCommandRetryPolicy();
        private static readonly RetryPolicy SqlConnectionRetryPolicy =
            SqlRetryManager.GetDefaultSqlConnectionRetryPolicy();

        private static RetryManager GetDefaultRetryManager()
        {
            const int retryCount = 4;
            const int minBackoffDelayMilliseconds = 2000;
            const int maxBackoffDelayMilliseconds = 8000;
            const int deltaBackoffMilliseconds = 2000;

            var exponentialBackoffStrategy =
                new ExponentialBackoff(
                    "exponentialBackoffStrategy",
                    retryCount,
                    TimeSpan.FromMilliseconds(minBackoffDelayMilliseconds),
                    TimeSpan.FromMilliseconds(maxBackoffDelayMilliseconds),
                    TimeSpan.FromMilliseconds(deltaBackoffMilliseconds)
                    );

            var manager = new RetryManager(
                new List<RetryStrategy>
                {
                    exponentialBackoffStrategy
                },
                exponentialBackoffStrategy.Name
                );

            return manager;
        }

        public static void OpenWithRetry(this SqlConnection cnn)
        {
            cnn.OpenWithRetry(SqlConnectionRetryPolicy);
        }

        public static IEnumerable<T> QueryWithRetry<T>(
            this SqlConnection cnn, string sql, object param = null, IDbTransaction transaction = null,
            bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
            )
        {
            return SqlCommandRetryPolicy.ExecuteAction(
                () => cnn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType)
                );
        }
    }
}

Respuesta aceptada

Poco después de publicar esto, encontré un paquete llamado Polly que parece resolver este problema de "reintento". Lo rastreé a través de esta pregunta de StackOverflow .

Aquí está mi implementación para consultar desde una base de datos MySQL y reintentar al momento de la falla:

var policy = Policy
    .Handle<AuthenticationException>(ex => ex.InnerException is Win32Exception)
    .Or<AuthenticationException>()
    .Retry((exception, attempt) =>
    {                        
        Log.Error(exception, "Class: {Class} | Method: {Method} | Failure executing query, on attempt number: {Attempt}", GetType().Name,
            MethodBase.GetCurrentMethod().Name, attempt);
    });

try
{
    var token = new Token();

    policy.Execute(() =>
    {
        using (var connection = _mySqlDatabase.GetConnection())
        {
            token = connection.Query<Token>("SELECT * FROM Token...").FirstOrDefault();
        }
    });

    return token;
}
catch (Exception ex)
{
    Log.Error(ex, "Class: {Class} | Method: {Method} | Ultimately failed to retrieve data from the database", GetType().Name,
        MethodBase.GetCurrentMethod().Name);
    throw new HttpError(HttpStatusCode.InternalServerError);
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué