2017-01-25 7 views
1

5回の試行でサーバーからのエラーが発生したときに、毎回同じ観測情報を再サブスクライブできる方法を見つけようとしています。実際に私のケースでどのように使うことができるのか理解できません。私はサーバコールにレトロフィットを、rxjavaにはサブスクライブを使用しています。rxjavaで5回試行して1時間ごとにリクエストを再試行する方法

私はretrofitを使用して電話をかけています。これを手伝ってください。

@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

これはあなたのためのレシピです。あなたのコード内で次に

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)); 
+0

クールのようにそれを使用します!大変ありがとう。 retryWhenを使って内部クラスを使用できるケースを教えてください。概念を理解するだけです。 – anshul

+0

申し訳ありませんが、投稿を編集しました。それは少し誤解を招いていた。私は正しくありませんでした。あなたは他の方法で同じ結果を達成することができます。これは私が使う方法です。要点はretryWhen関数で、リトライを開始するためにonNextまたはonCompleteを送出する必要があるオブザーバブルを提供する必要があることです。そして、それはあなた次第であるという背後にある論理にどのように対処していますか? –

+0

ありがとう – anshul

関連する問題