1

I am trying to figure out how i can resubscribe the same observable for every hour when we have got an error from server for 5 attempts.I know about retryWhen but really not able to understand how i can use it in my case.I am using retrofit for server calls and rxjava to subscribe.

Here is the method where i am making a call using retrofit.Please help with this.

@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); } 

1 Answer 1

1

Here's a recipe for you.

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); } }); } } 

Then in your code use it like this

// 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)); 
Sign up to request clarification or add additional context in comments.

2 Comments

Cool ! Thanks a lot dude. Can you tell me which case i can use the inner class with retryWhen , just to understand the concept.
Sorry, I've edited my post. It was a bit misleading. I was not right. You can achieve the same result in other ways. This is just the way I use. The point is that in retryWhen function you have to provide an observable which has to emmit onNext or onComplete to trigger a retry. And how do you deal with the logic behind that is entirely up to you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.