微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我的Polly重试策略中OperationKey为空?

如何解决为什么我的Polly重试策略中OperationKey为空?

我正在使用Polly版本7.1.1

我有一个简单的Polly重试策略,如果操作失败,并以NpgsqlException重试,它将重试一次:

var policy = Policy
    .Handle<NpgsqlException>()
    .Retry(
        retryCount: 1,onRetry: (exception,retryCount,context) =>
        {
            _logger.Log(LogLevel.Warning,$"Retry {retryCount} of {context.OperationKey},due to {exception.Message}",exception);
        })
    .WithPolicyKey("PostgresConnectionPolicy");

我有一种方法尝试连接到Postgresql数据库并使用上述策略运行查询

using (var conn = new NpgsqlConnection("myConnectionString"))
{
    conn.open()

    using(var command = GetCommand())
    {
        policy.Execute(
            action: context => command.ExecuteNonQuery(),contextData: new Context("Command.ExecuteNonQuery"));
    }
}

方法失败,被重试,并且记录器打印以下内容

由于42P01,请重试1个:关系“ myDatabase”不存在

我希望将记录以下内容

Command.ExecuteNonQuery 的重试1,由于42P01:关系“ myDatabase”不存在

当策略记录重试时,OperationKey为什么为空?

编辑:以添加简化的控制台应用程序为例。

这会将以下内容打印到控制台:

Retry 1 of,due to Testing Polly
Error.

示例:

using Polly;
using System;

namespace TestPolly
{
    class Program
    {
        static void Main(string[] args)
        {
            var policy = Policy
                .Handle<Exception>()
                .Retry(
                    retryCount: 1,context) =>
                    {
                        Console.WriteLine($"Retry {retryCount} of {context.OperationKey},due to {exception.Message}");
                    })
                .WithPolicyKey("PostgresConnectionPolicy");

            try
            {
                policy.Execute(
                    action: context => TestPolly(),contextData: new Context("TestPolly"));
            }
            catch (Exception e)
            {
                Console.WriteLine("Error.");
            }

            Console.ReadKey();
        }

        private static void TestPolly()
        {
            throw new Exception("Testing Polly");
        }
    }
}

解决方法

上下文对象

  • 定义一些predefined fields(例如OperationKeyPolicyKeyCorrelationId
  • 以及它的implements IDictionary<string,object>接口,以使使用者提供任何键值对。

如果您查看this line of the source codethe documentation,您会发现有一个接受OperationKey的构造函数重载。

因此,您可以这样定义Execute调用:

policy.Execute(
    action: context => command.ExecuteNonQuery(),contextData: new Context("Command.ExecuteNonQuery()"));

我认为这是一种更好的方法,因为您不依赖于基于字符串的键插入和检索。


更新:我发现了问题。

您使用了错误的Execute重载。

policy.Execute(
    action: context => command.ExecuteNonQuery(),context: new Context("Command.ExecuteNonQuery()"));

使用context代替contextData,然后出现OperationKey

,

通过使用自定义上下文解决此问题。

政策:

var policy = Policy
            .Handle<NpgsqlException>()
            .Retry(
                retryCount: 1,onRetry: (exception,retryCount,context) =>
                {
                    _logger.Log(LogLevel.Warning,$"Retry {retryCount} of {context["Operation"]},due to {exception.Message}",exception);
                })
            .WithPolicyKey("PostgresConnectionPolicy");

执行:

policy.Execute(
    action: context => command.ExecuteNonQuery(),contextData: new Context() { { "Operation","Command.ExecuteNonQuery()" } });

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。