How can I queue up and delay retrofit requests to avoid hitting an api rate limit?

Tyler Pfaff picture Tyler Pfaff · Dec 24, 2016 · Viewed 10.9k times · Source

I'm using an api that implements throttling. One of the limits is 1 request/second. ugh. I have the following scenario which hits the limit right away.

  • Check the status of the api with api/status

  • if the api is up, get a users subscriptions

  • load a page from the list of subscriptions

Is there anything I can plug into retrofit that can queue each network request to only run at least 1000ms after the last? I am using/learning rxjava, can debounce be of any use here?

Answer

parkgrrr picture parkgrrr · Mar 9, 2017

You can throttle your observable.

    Observable<String> text = ...
text.throttleLast(1, SECONDS)
    .flatMap(retrofitApiCall())
    .subscribe(result -> System.out.println("result: " + result));

Another solution is to set a dispatcher in your okhttp builder, and add an interceptor that sleeps for one second. This may not be the most elegant solution and kills some of the benefits of using async because it limits you to one thread at a time.

OkHttpClient.Builder builder = new OkHttpClient.Builder();


    Dispatcher dispatcher = new Dispatcher();
    dispatcher.setMaxRequests(1);

    Interceptor interceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            SystemClock.sleep(1000);
            return chain.proceed(chain.request());
        }
    };

    builder.addNetworkInterceptor(interceptor);
    builder.dispatcher(dispatcher);
    builder.build();