首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RetryWhen与异常逻辑

RetryWhen与异常逻辑
EN

Stack Overflow用户
提问于 2018-09-24 09:36:18
回答 2查看 555关注 0票数 0

我一直在考虑为一个简单的网络流实现一个基本的重试逻辑。其想法是有三种类型的例外需要处理:

  • 瞬态异常,应该重新连接并重试。
  • 永久错误连接,应该传播和让进程模具。
  • 应被吞咽并应完成可观察到的异常

当我勾勒这幅画的时候,我的结果是

代码语言:javascript
复制
var retriedObservable = observable.RetryWhen(x => x.SelectMany(ex =>
{
    if (ex is ShouldCompleteException)
    {
        return Observable.Return<Exception>(null);
    }
    else if (ex is TransientNetworkException)
    {
        return Observable.Return(ex).Delay(TimeSpan.FromSeconds(1));
    }
    else
    {
        return Observable.Throw<Exception>(ex);
    }
}).TakeUntil(ex => ex == null));

编辑:这个例子非常简单,只显示了我在代码中看到的三种典型的错误处理模式。在现实世界中,当然还有更多。

该代码工作正常,但看起来过于复杂,我不确定特殊的'null‘值是否会在某个时候击中我的脸。

我还尝试了.Where().Merge()的组合,但是代码很快就变得不可读了。

是否有更清晰的方法(即更规范的方法)来完成这一基本错误处理?

EN

回答 2

Stack Overflow用户

发布于 2018-09-26 18:40:36

这有一点帮助:

代码语言:javascript
复制
var retriedObservable2 = observable.RetryWhen(exStream => Observable.Merge(
    exStream.OfType<ShouldCompleteException>().Select(_ => (Exception)null),
    exStream.NotOfType(typeof(ShouldCompleteException)).OfType<TransientNetworkException>().Delay(TimeSpan.FromSeconds(1)),
    exStream.NotOfTypes(typeof(ShouldCompleteException), typeof(TransientNetworkException)).SelectMany(e => Observable.Throw<Exception>(e))
).TakeUntil(ex => ex == null));

它使用以下扩展消息:

代码语言:javascript
复制
public static class X
{
    public static IObservable<TSource> NotOfType<TSource>(this IObservable<TSource> source, Type t)
    {
        return source.Where(o => !t.IsInstanceOfType(o));
    }

    public static IObservable<TSource> NotOfTypes<TSource>(this IObservable<TSource> source, params Type[] ts)
    {
        return source.Where(o => ts.All(t => !t.IsInstanceOfType(o)));
    }
}
票数 2
EN

Stack Overflow用户

发布于 2018-09-24 10:00:16

这里已经有了很好的库,比如波莉。但是,如果你想实现你自己的,你可以做如下的事情。

您可以创建一个RetryPolicyHandler类。此外,您还可以使用接口对其进行抽象,如果需要,可以与任何IoC容器一起使用。使用以下实现添加类似于RetryExecuteAsync的方法。

代码语言:javascript
复制
public async Task RetryExecuteAsync(Func<Task> action)
{
    int retryCount = default(int);
    int maxNumberOfRetries = 5; // Or get from settings

    while (true)
    {
        try
        {
            await action().ConfigureAwait(false);

            break;
        }
        catch (ArgumentNullException)
        {
            // Something specific about this exception
            if (++retryCount > maxNumberOfRetries)
                throw;
        }
        catch (Exception)
        { 
            if (++retryCount > maxNumberOfRetries)
                throw;
        }
    }
}

然后你就可以这样用它了。

代码语言:javascript
复制
await this.retryPolicyHandler.RetryExecuteAsync(async () =>  
{
    // Whatever code you want to retry
}).ConfigureAwait(false);

如果需要,还可以创建其他特定方法。例如,ExecuteDeadlockRetryAsync可以捕获SqlExceptionExecuteHttpCallRetryAsync来处理HttpRequestException,并以另一种方式处理它们。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52476429

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档