问题描述
我正在使用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(例如
OperationKey
,PolicyKey
,CorrelationId
) - 以及它的implements
IDictionary<string,object>
接口,以使使用者提供任何键值对。
如果您查看this line of the source code或the 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()" } });