我有一个可以从很多来源获取物品的观察物:
Source { List<Item> data }
源和项目之间的关系是多对多的,在不同的来源中,项目可能会自行复制。 Item是应该上传到服务器的实体,服务器不接受重复项。为了实现这一点,我合并了Sources并通过它们的ID区分它们的Items,然后将唯一的项目上传到服务器。如下所示:
Observable.merge(source1(), source2(), source3())
.flatMapIterable(sources -> sources)
.flatMapIterable(source::getItems)
.distinct(item -> item.getId())
.flatMapCompletabale(item -> uploadItem(item))
项目上传可能会发出多个错误,其中一些错误我应该稍后再次尝试上传项目,然后在“失败”的情况下继续执行其他项目。一个正在等待它的重试。
如何推迟重试上传&#39;失败&#39;项目并继续其他项目,而这个项目正在尝试尝试?
提前致谢!
答案 0 :(得分:2)
要处理一次上传失败,您可以在最后一步添加运算符:
.flatMapCompletable(item->uploadItem(item))
应该成为
.flatMapCompletable(item->uploadItem(item)
.retryWhen(throwable ->
throwable.delay(5, TimeUnit.SECONDS)))
编辑:我从this Dan Lew blog entry了解了很多retryWhen()
运算符。您会找到几个示例,包括使用zip()
运算符和Observable.range(3)
来限制重试次数。
答案 1 :(得分:0)
我将此函数放入retryWhen方法并使其正常工作。
public class RetryWithDelay implements Function<Observable<? extends Throwable>, Observable<?>> {
private final int maxRetryCount;
private final int retryDelay;
private int retryCount;
private TimeUnit timeUnit;
public RetryWithDelay(final int maxRetryCount, final int retryDelay, final TimeUnit timeUnit) {
this.maxRetryCount = maxRetryCount;
this.retryDelay = retryDelay;
this.timeUnit = timeUnit;
this.retryCount = 0;
}
@Override
public Observable<?> apply(final Observable<? extends Throwable> attempts) {
return attempts.flatMap((Function<Throwable, Observable<?>>) throwable -> {
if (++retryCount < maxRetryCount) {
return Observable.timer(retryDelay, timeUnit);
}
return Observable.error(throwable);
});
}
}
答案 2 :(得分:0)
我必须修改以上示例以创建一个Flowable以便在RxJava2项目中的Single时重试:
import io.reactivex.Flowable; import io.reactivex.functions.Function;
import java.util.concurrent.TimeUnit;
public class RetryWithDelay implements Function<Flowable<? extends Throwable>, Flowable<?>> {
private final int maxRetryCount;
private final int retryDelay;
private int retryCount;
private TimeUnit timeUnit;
public RetryWithDelay(final int maxRetryCount, final int retryDelay, final TimeUnit timeUnit) {
this.maxRetryCount = maxRetryCount;
this.retryDelay = retryDelay;
this.timeUnit = timeUnit;
this.retryCount = 0;
}
@Override
public Flowable<?> apply(final Flowable<? extends Throwable> attempts) {
return attempts.flatMap((Function<Throwable, Flowable<?>>) throwable -> {
if (++retryCount < maxRetryCount) {
return Flowable.timer(retryDelay, timeUnit);
}
return Flowable.error(throwable);
});
} }
并将其应用到我的单曲中:
.retryWhen(new RetryWithDelay(5, 2, TimeUnit.SECONDS))