Как повторять запрос каждый час для 5 попыток в rxjava и дооснащение

Я пытаюсь выяснить, как я могу повторно подписаться на одно и то же наблюдаемое для каждого часа, когда у нас есть ошибка с сервера для 5 попыток. Я знаю о retryWhen, но действительно не могу понять, как я могу использовать его в моем случае. Я использую модернизация для вызовов сервера и rxjava для подписки.

Вот метод, по которому я звоню с помощью дооснащения. Пожалуйста, помогите с этим.

@Override
public Observable<Integer> uploadFileToServer(FileUploadData fileUploadData, File file) {
    //  log.i(TAG, "uploadFileToServer");
    FileUploadEndpoint fileUploadEndpoint = null;
    try {
        fileUploadEndpoint = retrofitServiceFactory.getService(FileUploadEndpoint.class);
    } catch (BaseUrlNotFoundException e) {
        e.printStackTrace();
        // log.i(TAG, "uploadFileToServer" + e.getMessage());
        return Observable.just(FileUploadConstants.EXCEPTION_FILE_UPLOAD);
    }

    // create RequestBody instance from file
    RequestBody requestFile =
            RequestBody.create(okhttp3.MultipartBody.FORM, file);

    // MultipartBody.Part is used to send also the actual file name
    MultipartBody.Part body =
            MultipartBody.Part.createFormData("uploadfile", file.getName(), requestFile);

    // add another part within the multipart request
    String descriptionString = "file upload";
    RequestBody description =
            RequestBody.create(
                    okhttp3.MultipartBody.FORM, descriptionString);

    Map<String, String> queryMap = new HashMap<>();
    queryMap.put("SENDER", fileUploadData.getSender());
    queryMap.put("SOURCE", fileUploadData.getSource());
    queryMap.put("SCHEMEID", fileUploadData.getSchemeId());
    queryMap.put("ISPROCESSINGREQ", "false");
    queryMap.put("ISENCRYPTED", "true");
    queryMap.put("UID", fileUploadData.getSchemeId());
    queryMap.put("METADATA", fileUploadData.getMetaData());


    final Observable<FileUploadResponse> requestObservable = fileUploadEndpoint.upload(queryMap, description, body);
    return requestObservable.map(new Function<FileUploadResponse, Integer>() {
        @Override
        public Integer apply(FileUploadResponse fileUploadResponse) throws Exception {
            if (fileUploadResponse != null) {
                int code = fileUploadResponse.getStatusCode();
                switch (code) {
                    case 100:
                        return FileUploadConstants.FILE_UPLOAD_SUCCESSFUL;
                }
            }
            return FileUploadConstants.EXCEPTION_FILE_UPLOAD;
        }
    }).retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
        @Override
        public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
            return throwableObservable.zipWith(Observable.range(1, 5), new BiFunction<Throwable, Integer, FileUploadResponse>() {
                @Override
                public FileUploadResponse apply(Throwable throwable, Integer integer) throws Exception {
                    return null;//not able to write the logic :(
                }
            });
        }
    });
}

@Override
public void setBaseUrl(String baseUrl) {
    retrofitServiceFactory.setBaseUrl(baseUrl);
}

private interface FileUploadEndpoint {

    @Multipart
    @POST("da/appupload/file")
    Observable<FileUploadResponse> upload(@QueryMap Map<String, String> additionValues,
                                          @Part("description") RequestBody description,
                                          @Part MultipartBody.Part file);
}

person anshul    schedule 25.01.2017    source источник


Ответы (1)


Вот вам рецепт.

public class RetryWithDelay implements
        Func1<Observable<? extends Throwable>, Observable<?>> {
    private static final String TAG = "RetryWithDelay";

    private static final int DEFAULT_RETRY_COUNT = 5;
    private static final int DEFAULT_RETRY_DELAY = 1000 * 60;

    private final int maxRetries;
    private final int retryDelayMillis;
    private int retryCount;

    public RetryWithDelay() {
        this.maxRetries = DEFAULT_RETRY_COUNT;
        this.retryDelayMillis = DEFAULT_RETRY_DELAY;
        this.retryCount = 0;
    }

    public RetryWithDelay(final int maxRetries, final int retryDelayMillis) {
        this.maxRetries = maxRetries;
        this.retryDelayMillis = retryDelayMillis;
        this.retryCount = 0;
    }

    @Override
    public Observable<?> call(Observable<? extends Throwable> attempts) {
        return attempts.flatMap(new Func1<Throwable, Observable<?>>() {
                    @Override
                    public Observable<?> call(Throwable throwable) {
                        if (throwable instanceof HttpException) {
                            LOGD(TAG, "Caught http exception.");
                        }

                        if (throwable instanceof IOException) {
                            LOGD(TAG, "Network error");
                        }

                        if (++retryCount < maxRetries) {
                            // When this Observable calls onNext, the original
                            // Observable will be retried (i.e. re-subscribed).
                            return Observable.timer(retryDelayMillis, TimeUnit.MILLISECONDS);
                        }

                        // Max retries hit. Just pass the error along.
                        return Observable.error(throwable);
                    }
                });
    }
}

Затем в своем коде используйте это так

// Leave constructor empty for default values
.retryWhen(new RetryWithDelay());

// Or setup different values
// In this case retry 3 times, with 5s delay
.retryWhen(new RetyryWithDelay(3, 5000));
person Andrej Jurkin    schedule 25.01.2017
comment
Прохладный ! Большое спасибо, чувак. Можете ли вы сказать мне, в каком случае я могу использовать внутренний класс с retryWhen, просто чтобы понять концепцию. - person anshul; 25.01.2017
comment
Извините, я отредактировал свой пост. Это немного вводило в заблуждение. Я был не прав. Вы можете добиться того же результата другими способами. Я так и использую. Дело в том, что в функции retryWhen вы должны предоставить наблюдаемый объект, который должен выдавать onNext или onComplete для запуска повторной попытки. А как вы справляетесь с логикой, лежащей в основе этого, полностью зависит от вас. - person Andrej Jurkin; 25.01.2017