Попробуйте это:
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);
}
Как правило, использование try-catch внутри наблюдаемого недовольно; предпочтительно использовать наблюдаемую обработку исключений On-Error. Тем не менее, OnExecute
вашего интерфейса не возвращает IObservable<T>
, а просто T
. Так что вы вынуждены использовать try-catch. Если бы вы изменили интерфейс, чтобы вернуть 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);
}
Это все, если вы хотите, чтобы механизм продолжал срабатывать на успех. Если нет, добавьте Take(1)
в конце любого решения.