2015-01-20 16 views
7

Tôi mới sử dụng ReactiveX và chương trình phản ứng nói chung. Tôi cần phải thực hiện một cơ chế thử lại cho các hoạt động Couchbase CAS, nhưng ví dụ trên trang web của Couchbase cho thấy một lần thử lạiKhi có vẻ như thử lại vô thời hạn. Tôi cần phải có một giới hạn thử lại và thử lại đếm ở đâu đó trong đó.RxJava: thử lạiKhi thử lại giới hạn

Thử lại đơn giản() sẽ hoạt động, vì nó chấp nhận retryLimit, nhưng tôi không muốn thử lại trên mọi ngoại lệ, chỉ trên CASMismatchException.

Bất kỳ ý tưởng nào? Tôi đang sử dụng thư viện RxJava.

Trả lời

2

retryWhen rõ ràng là một chút phức tạp hơn retry đơn giản, nhưng đây là ý chính của nó:

  • bạn vượt qua một chức năng notificationHandler để retryWhen mà phải mất một Observable<Throwable> và kết quả đầu ra một Observable<?>
  • sự phát xạ của điều này trở lại Quan sát xác định khi thử lại sẽ xảy ra hoặc dừng
  • vì vậy, đối với mỗi Ngoại lệ xảy ra trong luồng gốc, nếu trình xử lý phát ra 1 mục, sẽ có 1 lần thử lại. Nếu nó phát ra 2 mục, sẽ có 2 ...
  • ngay sau khi luồng xử lý phát ra lỗi, thử lại bị hủy.

Sử dụng này, bạn có thể vừa:

  • làm việc chỉ trên CasMismatchExceptions: chỉ có chức năng của bạn trả về một Observable.error(t) trong các trường hợp khác
  • retry chỉ dành cho một số cụ thể của lần: đối với từng ngoại lệ, flatMap từ một số Observable.range đại diện cho số lần thử lại tối đa, có trả lại số Observable.timer bằng cách thử lại # nếu bạn cần sự chậm trễ tăng lên.

trường hợp sử dụng của bạn là khá gần với một trong RxJava doc here

+0

Tôi muốn thử lại khi có giới hạn số lượng. Tôi đã thử Observable.range (0, 10) nhưng nó không hoạt động. –

8

Ngoài những gì Simon Basle nói, đây là một phiên bản nhanh chóng với backoff tuyến tính:

.retryWhen(notification -> 
    notification 
    .zipWith(Observable.range(1, 5), Tuple::create) 
    .flatMap(att -> 
      att.value2() == 3 ? Observable.error(att.value1()) : Observable.timer(att.value2(), TimeUnit.SECONDS) 
    ) 
) 

Lưu ý rằng " att "đây là một tuple bao gồm cả throwable và số retries, vì vậy bạn có thể thực hiện rất cụ thể một logic trả về dựa trên hai params đó.

Nếu bạn muốn tìm hiểu nhiều hơn, bạn có thể lén nhìn doc kiên cường Tôi hiện đang viết: https://gist.github.com/daschl/db9fcc9d2b932115b679#retry-with-delay

+0

Ai có thể giải thích, tại sao flatMap được yêu cầu ở đây? Dường như sự chậm trễ không hoạt động mà không có nó – deviant

2

phục hồi chủ đề này vì trong Couchbase Java SDK 2.1.2 có một cách mới đơn giản hơn để làm điều đó : sử dụng số RetryBuilder:

Observable<Something> retryingObservable = 
sourceObservable.retryWhen(
    RetryBuilder 
    //will limit to the relevant exception 
    .anyOf(CASMismatchException.class) 
    //will retry only 5 times 
    .max(5) 
    //delay doubling each time, from 100ms to 2s 
    .delay(Delay.linear(TimeUnit.MILLISECONDS, 2000, 100, 2.0)) 
    .build() 
); 
+0

Bạn có thể nối thêm một số ngoại lệ khác nhau với các độ trễ khác nhau không? Và bạn cũng có thể đặt độ trễ mặc định cho tất cả phần còn lại không? –

+0

Không, bạn phải chỉ đơn giản là chuỗi một số retryWhen, mỗi với xây dựng của nó, giống như bạn muốn chuỗi một số khối catch trong mã bắt buộc –

Các vấn đề liên quan