Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit parallel requests with Retrofit 2.0?

My goal is to limit the number of parallel executing request by throwing an exception.

For example, I want only one executing request:

someApi.getUser(
    result -> print("ok: " + result), exception -> print("error: " + exception)
); // this request will be executed in 5 seconds

someApi.getServerInfo(
    result -> print("ok: " + result), exception -> print("error: " + exception)
); // there I want to catch exception like ExecutorIsBusy

How can I implement it with Retrofit 2.0?

like image 239
Alexandr Avatar asked Oct 19 '22 09:10

Alexandr


2 Answers

I am not sure that throwing an Exception is the best way to do it, but I don't know your use case so I will not discuss this point :)

Anyway, the comment of @Daniel actually points to a pretty good direction. If you're using retrofit with OkHttp, it's the OkHttpClient that will handle the "concurrent requests" stuff. Reading the docs, you could see that OkHttp uses a Dispatcher to handle parallel asynchronous requests (Dispatcher docs).

So two interesting points are :

  1. Method setMaxRequests(int maxRequests) : defines the maximum concurrent requests
  2. Method executed(RealCall call) : actually executes a requests

I think you could do this to achieve your goal :

  1. Create a custom Dispatcher class
  2. Overrides the executed(RealCall call) method throwing an exception if the number of currents request is superior to maxRequests
  3. Use the custom Dispatcher in the OkHttpClient you're using with retrofit
like image 130
mithrop Avatar answered Oct 21 '22 05:10

mithrop


Using RxJava & taking the approach in the above comments, here is an example:

Assume that these operations are attached to buttons.

public void runObservable1(View view) {
    if (!taskRunning){
        try{
            taskRunning = true;
            subsonicService.runTask1()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .compose(this.<Result>bindUntilEvent(ActivityEvent.DESTROY))
                    .subscribe(new Subscriber<Result>() {
                        @Override
                        public void onCompleted() {
                            taskRunning = false;
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onNext(Result result) {
                            //your logic here
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        Toast.makeText(this, "Task is running you must wait", Toast.LENGTH_SHORT).show();
    }


}

public void runObservable2(View view) {

    if (!taskRunning){
        try{
            taskRunning = true;
            subsonicService.runTask2()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .compose(this.<Result>bindUntilEvent(ActivityEvent.DESTROY))
                    .subscribe(new Subscriber<Result>() {
                        @Override
                        public void onCompleted() {
                            taskRunning = false;
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onNext(Result result) {
                            //Logic here
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        Toast.makeText(this, "Task is running you must wait", Toast.LENGTH_SHORT).show();
    }
}

I am also not an expert at RxJava so there may be an operator that makes this easier.

like image 41
Daniel Avatar answered Oct 21 '22 04:10

Daniel