Browse Source

Add exponential backoff when trying to pull signaling messages again

When pulling signaling messages failed the source observable was
immediately subscribed again, which immediately triggered another pull.
Rather than hammering the server or a flaky network with new requests
again and again now further requests are performed with an incremental
delay (up to 16 seconds).

The delay is increased only when several requests fail in a row, and it
is reset as soon as a request succeeds.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Daniel Calviño Sánchez 2 năm trước cách đây
mục cha
commit
4b4b9da2b1

+ 11 - 1
app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

@@ -138,6 +138,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.inject.Inject;
 
@@ -1472,6 +1473,8 @@ public class CallActivity extends CallBaseActivity {
                             int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser,
                                                                              new int[]{ApiUtils.APIv3, 2, 1});
 
+                            AtomicInteger delayOnError = new AtomicInteger(0);
+
                             ncApi.pullSignalingMessages(credentials,
                                                         ApiUtils.getUrlForSignaling(apiVersion,
                                                                                     baseUrl,
@@ -1480,13 +1483,20 @@ public class CallActivity extends CallBaseActivity {
                                 .observeOn(AndroidSchedulers.mainThread())
                                 .repeatWhen(observable -> observable)
                                 .takeWhile(observable -> isConnectionEstablished())
+                                .doOnNext(value -> delayOnError.set(0))
                                 .retryWhen(errors -> errors
                                     .flatMap(error -> {
                                         if (!isConnectionEstablished()) {
                                             return Observable.error(error);
                                         }
 
-                                        return Observable.just(0l);
+                                        if (delayOnError.get() == 0) {
+                                            delayOnError.set(1);
+                                        } else if (delayOnError.get() < 16) {
+                                            delayOnError.set(delayOnError.get() * 2);
+                                        }
+
+                                        return Observable.timer(delayOnError.get(), TimeUnit.SECONDS);
                                     })
                                 )
                                 .subscribe(new Observer<SignalingOverall>() {