question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

MissingBackpressureException even .onBackpressureDrop() is added?

See original GitHub issue

Hey. I’m using RxAndroidBle for connection / writing data etc stuffs. And with long stream operation like subscribe to resource ( 1-3min) I got MissingBackpressureException ( bottom of source code with Log.e). Any idea what is wrong here?

// Setup notifications for incoming data
                           RxBleConnection connection = connectionMap.get(bleMac);
                           Subscription notifySubscription = connection.setupNotification(notifyCharacteristic)
                                   .doOnNext(new Action1<Observable<byte[]>>() {
                                       @Override
                                       public void call(Observable<byte[]> observable) {
                                           Log.d(TAG, "Notifications set, calling bypassConnect()");

                                           // Bypass connect in WB to make it aware of this new device
                                           String wbAddress = addressMap.getOrCreateWbAddress(bleMac);
                                           bleWrapper.bypassConnect(wbAddress);
                                       }
                                   })
                                   .flatMap(new Func1<Observable<byte[]>, Observable<byte[]>>() {
                                       @Override
                                       public Observable<byte[]> call(Observable<byte[]> observable) {
                                           return observable;
                                       }
                                   })
                                   .onBackpressureDrop()
                                   .subscribe(new Action1<byte[]>() {
                                       @Override
                                       public void call(byte[] bytes) {
                                           dataAvailable(bleMac, bytes);
                                       }
                                   }, new Action1<Throwable>() {
                                       @Override
                                       public void call(Throwable throwable) {
                                           Log.e(TAG, "dataAvailable() Error: " + throwable);
                                       }
                                   });

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:14 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
dariuszseweryncommented, Sep 20, 2017

Finally I had time to dig into this issue. I have prepared a peripheral that sends out ~400 notifications per second and it worked as long as the consumer was quick:

device.establishConnection(false)
        .flatMap(connection -> connection.setupNotification(uuid))
        .flatMap(observable -> observable)
        .subscribe(
                bytes -> Log.i("Received", "."),
                throwable -> Log.e("Error", "Whoops!", throwable)
        );

Then I have made the consumer slower by adding a Thread.sleep(10) and I quickly got MissingBackpressureException. I have then started to play with .onBackpressureDrop() and adding it right before .subscribe() did not fixed the issue. I have checked the Javadoc of .onBackpressureDrop() and it says:

     * If the downstream request count hits 0 then the Observable will refrain from calling {@code onNext} until
     * the observer invokes {@code request(n)} again to increase the request count.

Then I have checked the Javadoc of .subscribe():

     *  <dd>The operator consumes the source {@code Observable} in an unbounded manner (i.e., no
     *  backpressure is applied to it).</dd>

This means that applying .onBackpressureDrop() just before .subscribe() does nothing as the .subscribe() is not applying backpressure to the upstream. .onBackpressure*() should be applied before an operator that applies backpressure to the upstream i.e. .observeOn(Scheduler) which Javadoc says:

     *  <dd>This operator honors backpressure from downstream and expects it from the source {@code Observable}. Violating this
     *  expectation will lead to {@code MissingBackpressureException}. This is the most common operator where the exception
     *  pops up; look for sources up the chain that don't support backpressure,
     *  such as {@code interval}, {@code timer}, {code PublishSubject} or {@code BehaviorSubject} and apply any
     *  of the {@code onBackpressureXXX} operators <strong>before</strong> applying {@code observeOn} itself.</dd>

i.e. this will work:

device.establishConnection(false)
        .flatMap(connection -> connection.setupNotification(uuid))
        .flatMap(observable -> observable)
        .onBackpressureDrop()
        .observeOn(Schedulers.computation())
        .subscribe(
                bytes -> {
                    Log.i("Received", ".");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                },
                throwable -> Log.e("Error", "Whoops!", throwable)
        );

but this will not:

device.establishConnection(false)
        .flatMap(connection -> connection.setupNotification(uuid))
        .flatMap(observable -> observable)
        .observeOn(Schedulers.computation())
        .onBackpressureDrop()
        .subscribe(
                bytes -> {
                    Log.i("Received", ".");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                },
                throwable -> Log.e("Error", "Whoops!", throwable)
        );

Summary: the behaviour of the library is correct. The aim of RxAndroidBle is to provide all BLE events to the user. Applying backpressure mechanisms inside the library would make it harder for the user to understand why they would not get all the notifications the device has sent if they consume them too slow.

0reactions
dariuszseweryncommented, Sep 13, 2017

@TeemuStenhammar Sorry for such a delay (I was on holiday)—could you add on what phone did the problem surfaced? How quick and of what size the notifications are?

Read more comments on GitHub >

github_iconTop Results From Across the Web

MissingBackpressureException even .onBackpressureDrop ...
Hey. I'm using RxAndroidBle for connection / writing data etc stuffs. And with long stream operation like subscribe to resource ( 1-3min) I ......
Read more >
MissingBackpressureException even .onBackpressureDrop ...
I have problem with MissingBackpressureException. I added few .onBackpressureDrop() just for the test but still getting exception.
Read more >
MissingBackpressureException (RxJava Javadoc 1.3.8)
Represents an exception that indicates that a Subscriber or operator attempted to apply reactive pull backpressure to an Observable that does not implement ......
Read more >
Dealing with Backpressure with RxJava - Baeldung
Our compute() function is simply printing the argument. ... Observer and thus they may still lead to MissingBackpressureException.
Read more >
RxJava — Flowables — What, when and how to use it?
Observables are those entities which we observe for any event. ... be reasonably backpressured and cause unexpected > MissingBackpressureException (i.e., ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found