具有可观察性的重试机制

时间:2018-05-02 13:19:03

标签: c# system.reactive

我试图使用C#observables编写重试机制。

  1. 重试具有重试计数和重试间隔
  2. 重试应执行" OnExecute"方法
  3. 在每个例外情况下都会执行" OnCatch"方法
  4. 这是我尝试做的事情:

    public static IObservable<T> Retry(GenericRetryExecutorRequest<T> request)
    {
        var source = Observable.Timer(TimeSpan.Zero, request.Interval)
            .Select(item =>
            {
              return request.GenericRetryActions.OnExecute();
            });
    
        var retryObservable = source
            .Retry(request.RetryCount)
            .Catch(source);
    
        return retryObservable;
    }
    
    public class GenericRetryExecutorRequest<T>
    {
        public int RetryCount { get; set; } = 3; 
        public TimeSpan Interval { get; set; } = new TimeSpan(0,0,0,5);
        public IGenericRetryActions<T> GenericRetryActions { get; set; }
    }
    
    public interface IGenericRetryActions<out T>
    {
        T OnExecute();
        void OnCatch();
    }
    

    不幸的是 - 它表现不佳:

    1. 我不知道在抛出异常时如何执行OnCatch。 我尝试了许多方法但没有成功。
    2. OnExecute似乎没有重复执行(请求 如果它抛出异常,则为

1 个答案:

答案 0 :(得分:1)

试试这个:

public void setMessageToSend(Message message) {
    messagesToSend.add(message.getMessageHandler().getBytes());
    messagesToSend.notify();
}

通常在观察者中使用try-catch是不受欢迎的;最好使用可观察的On-Error异常处理。但是,您的界面public static IObservable<T> Retry<T>(this GenericRetryExecutorRequest<T> request) { return Observable.Timer(Timespan.Zero, request.Interval) .Select(item => { try { var value = request.GenericRetryActions.OnExecute(); return Notification.CreateOnNext(value); } catch(Exception e) { request.GenericRetryActions.OnCatch(); return Notification.CreateOnError<T>(e); } }) .Dematerialize() .Retry(request.RetryCount); } 不会返回OnExecute,而只会返回IObservable<T>。所以你被迫使用try-catch。如果您要更改界面以返回T,那么我认为这样可行:

IObservable<T>

这就是假设您希望机制继续成功。如果没有,请在任一解决方案的末尾添加public class GenericRetryExecutorRequest2<T> { public int RetryCount { get; set; } = 3; public TimeSpan Interval { get; set; } = new TimeSpan(0, 0, 0, 5); public IGenericRetryActions2<T> GenericRetryActions { get; set; } } public interface IGenericRetryActions2<out T> { IObservable<T> OnExecute(); void OnCatch(); } public static IObservable<T> Retry2<T>(this GenericRetryExecutorRequest2<T> request) { return Observable.Timer(Timespan.Zero, request.Interval) .SelectMany(_ => request.GenericRetryActions.OnExecute()) .Catch((Exception e) => Observable.Return(Unit.Default) .Do(_ => request.GenericRetryActions.OnCatch()) .SelectMany(Observable.Throw<T>(e)) ) .Retry(request.RetryCount); }