1

当 NEST 错误在 HttpCodeResponse 范围内并且我有以下通用策略时,我想重试:

 public Policy<D> CreatePolicy<T, D>(
            PolicyType policyType)
            where T : Exception where D : IApiCallDetails
        {
            switch (policyType)
            {
                case PolicyType.WaitAndRetryAsync:

                    var httpStatusCodesWorthRetrying = new List<string>(this.policyConfiguration.HttpStatusCodesToRetrying.Split(','));

                    return Policy.Handle<T>()
                        .OrResult<D>(r => httpStatusCodesWorthRetrying.Select(int.Parse).ToList().Contains(r.HttpStatusCode.Value))
                        .WaitAndRetryAsync(
                            this.policyConfiguration.NumberOfRequestRetries,
                            retryAttempt => TimeSpan.FromSeconds(this.policyConfiguration.TimeInSecondsBetweenRetries),
                            onRetry: (exception, retryCount, context) =>
                            {
                                Log.Error($"[{context.PolicyKey}] Retry {retryCount}  due to {exception.Exception.Message}.");
                                throw exception.Exception;
                            })                        
                        .WithPolicyKey(nameof(PolicyType.WaitAndRetryAsync));

                default:
                    throw new ArgumentOutOfRangeException(nameof(policyType), policyType, null);
            }

但是当我尝试应用到 elasticClient 调用时,我收到错误:

cannot implicity convert System.Threading.Tasks.Task<Nest.ISearchResponse<Model.Product>> to System.Threading.Tasks.Task<Elasticsearch.Net.IApiCallDetails>


 Policy<IApiCallDetails> policyWaintAndRetry = this.policyFactory.CreatePolicy<ElasticsearchClientException, IApiCallDetails>(PolicyType.WaitAndRetryAsync);


        var searchResponse = await policyWaintAndRetry.ExecuteAsync
            action: () =>
                this.client.SearchAsync<Product>(s => s
                .From((request.PageNumber - 1) * request.PageSize)
                .Size(request.PageSize)
                .Index(GetIndexName(request.TenantId))
                .Query(q => tq), CancellationToken.None),
            contextData: new Polly.Context("SearchProductSearchAsync"))
        .ConfigureAwait(false);
4

3 回答 3

1

对于 NEST 5.x,我认为D应该有一个通用参数约束IResponse;NEST 中的每个响应都实现IResponse并且继承自的ApiCall属性 包含带有HTTP 状态代码的。IBodyWithApiCallDetailsIApiCallDetails

于 2017-12-19T05:02:06.160 回答
1

没有必要为处理异常和结果定义两个单独的策略。此答案中的两个单独的策略可以像这样组合:

public Policy<TResult> CreatePolicyForResultAndException<TResult, TException>(PolicyType policyType)
    where TResult : HttpResponseMessage
    where TException: Exception
{
    switch (policyType)
    {
        case PolicyType.WaitAndRetryAsync:

            var httpStatusCodesWorthRetrying = new List<string>(this.policyConfiguration.HttpStatusCodesToRetrying.Split(','));

            return Policy.HandleResult<TResult>(r => httpStatusCodesWorthRetrying.Select(int.Parse).ToList().Contains((int)r.StatusCode))
                .Or<TException>()
                .WaitAndRetryAsync(
                    this.policyConfiguration.NumberOfRequestRetries,
                    retryAttempt => TimeSpan.FromSeconds(this.policyConfiguration.TimeInSecondsBetweenRetries),
                    onRetry: (outcome, retryCount, context) =>
                        {
                            Log.Error($"[{context.PolicyKey}] Retry {retryCount} due to {outcome.Result ?? outcome.Exception.Message}.");
                            if (outcome.Exception != null) throw outcome.Exception; // [*] if desired - see note after code sample
                        })     
                 .WithPolicyKey(nameof(PolicyType.WaitAndRetryAsync));                      

        default:
            throw new ArgumentOutOfRangeException(nameof(policyType), policyType, null);
    }
}

[*] 上面代码示例中的这一行保留了onRetry原始答案中抛出的异常。但是,在 中重新抛出异常是不寻常的onRetry,因为该策略不会处理那里重新抛出的异常;throwing insideonRetry将导致策略退出而不进行进一步尝试。

于 2017-12-22T19:38:30.317 回答
0

实际上我的问题是我试图创建一个处理异常和结果的策略,而实际上我应该为每个策略创建一个,然后将它们与 policyWrap 合并

第一项政策(针对结果):

        public Policy<T> CreatePolicyForResult<T>(
        PolicyType policyType)
        where T : HttpResponseMessage
    {
        switch (policyType)
        {
            case PolicyType.WaitAndRetryAsync:

                var httpStatusCodesWorthRetrying = new List<string>(this.policyConfiguration.HttpStatusCodesToRetrying.Split(','));

                return Policy.HandleResult<T>(r => httpStatusCodesWorthRetrying.Select(int.Parse).ToList().Contains((int)r.StatusCode))
                    .WaitAndRetryAsync(
                        this.policyConfiguration.NumberOfRequestRetries,
                        retryAttempt => TimeSpan.FromSeconds(this.policyConfiguration.TimeInSecondsBetweenRetries))
                    .WithPolicyKey(nameof(PolicyType.WaitAndRetryAsync));                       

            default:
                throw new ArgumentOutOfRangeException(nameof(policyType), policyType, null);
        }
    }

第二条政策(例外):

 public Policy CreatePolicyForException<T>(
            PolicyType policyType)
            where T : Exception
        {
            switch (policyType)
            {
                case PolicyType.WaitAndRetryAsync:

                    return Policy.Handle<T>()                        
                        .WaitAndRetryAsync(
                            this.policyConfiguration.NumberOfRequestRetries,
                            retryAttempt => TimeSpan.FromSeconds(this.policyConfiguration.TimeInSecondsBetweenRetries),
                            onRetry: (exception, retryCount, context) =>
                            {
                                Log.Error($"[{context.PolicyKey}] Retry {retryCount}  due to {exception.Message}.");
                                throw exception;
                            })                        
                        .WithPolicyKey(nameof(PolicyType.WaitAndRetryAsync));

                default:
                    throw new ArgumentOutOfRangeException(nameof(policyType), policyType, null);
            }
        }

用法:

var policyWaintAndRetryForExeption = this.policyFactory.CreatePolicyForException<ElasticsearchClientException>(PolicyType.WaitAndRetryAsync);

var policyWaintAndRetryForResult = this.policyFactory.CreatePolicyForResult<HttpResponseMessage>(PolicyType.WaitAndRetryAsync);

PolicyWrap<HttpResponseMessage> policyWrap = policyWaintAndRetryForExeption.WrapAsync(policyWaintAndRetryForResult);
于 2017-12-21T15:35:13.983 回答