Search code examples
resthttpkotlinkotlinx.coroutines

Throttle or Limit Kotlin CoRoutine count


I am trying to hit an http service from my coroutine. I might have to hit the service a million times. I prefer to do it in parallel as those are independent of each other, at the same time I don't want to DOS that service. I want to throttle my coroutine (some kind of back pressure)

I know I can batch the requests to acceptable concurrent number of requests. But, that's too boilerplate I think. Is there any http library out there handles this in an idiomatic way


Solution

  • Option 1:

    OK HTTP with retrofit can limit number of requests:

    Dispatcher dispatcher = new Dispatcher();
    dispatcher.setMaxRequests(100);
    dispatcher.setMaxRequestsPerHost(10);
    OkHttpClient client = new OkHttpClient.Builder()
        .dispatcher(dispatcher)
        .build();
    

    You can see the example here: OkHttpClient limit number of connections?
    There is an adapter for coroutines: https://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter
    So both together will give you what you need.

    Option 2:

    Use Retrofit with AsyncHttpClient which also has an adapter: https://github.com/AsyncHttpClient/async-http-client/tree/master/extras/retrofit2

    Then limit the resources like this:

    AsyncHttpClient http = asyncHttpClient(config()
        .setMaxConnections(500)
        .setMaxConnectionsPerHost(200)
        .setPooledConnectionIdleTimeout(100)
        .setConnectionTtl(500)
    );
    

    That example is from the wiki: https://github.com/AsyncHttpClient/async-http-client/wiki/Connection-pooling

    Option 3:

    Use one of the above clients (or any other one) without retrofit. Then wrap the callback yourself or find a lib that already did that (exists for many callback types): https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#wrapping-callbacks