After a few discussions it seems that the consensu...
# coroutines
t
After a few discussions it seems that the consensus for limiting threads for certain purpose should be coroutine worker pool. In an attempt to improve my internals I'd like to migrate my bad situation that is a mix of synchronous code, callbacks and futures in a dedicated thread pool to coroutines. The application can communicate with different systems that each have their specific limitation needs. And the main application should be unaware of that. The goal is to move to fully suspend functions, but with each system being able to enfore some global limits on all the called functions.
Copy code
interface Host {

   suspend fun getMovies() : List<Movies>
   suspend fun setWatched(movie:Movie) : Boolean
   
   .....
}
Imagine a lot more functions. At any given moment there should be no more than X functions running. Ideally the limit should only apply to the actual server communication and the transformation of received data, should not be limited to allow faster command enqueing. The interface does implement close() that should also cancel all running coroutines for the host. My solution with blocking calls, would be to have a dedicated thread pool as dispatcher and use withcontext for the network call, but this is not efficient and no more works if some of the calls are non blocking and can switch to IO for example. I'd really appreciate some help on how to apprehend this needs, as it's major refactoring so needs to be done correctly 🙂
j
You may want to use a
newFixedThreadPoolContext
. Also have a look at https://github.com/Kotlin/kotlinx.coroutines/issues/261
Be also careful about the difference between "parallelism" and "concurrency". Many coroutines may be executed concurrently, even if they use the same single-threaded context.
t
Thanks I know all that, but actually this does not answer the questions at all 😉 newFixed is that bad solution that works towards blocking calls only.
z
I’m not sure exactly what you’re asking – if you’re looking for general advice on how to refactor a complex proprietary system, I’m not sure how to help you. If you’re just wondering how to implement a worker pool to meet the requirements you described, here’s a rough sketch: https://gist.github.com/zach-klippenstein/38bd9a6fc4a84ee3e2435956ada18504
t
Thanks of a lot for the full example, you opened my eyes. Yes I was asking for help about the worker pool (or a way to achieve the concurrency limits with coroutines, but after all the discussions worker pool are the solution for that need) and did not thought about putting it down to the actual http request because I have one case that does not fit but I could probably use another worker pool for that unless you have an idea. A few of the functions needs to use paging so will be a loop of requests + parsing until the pages are finished. Using worker at http level means that other queries could get in and delay a lot that job even if it was started first. I don’t think yet about how to handle the limits with 2 worker pool but will figure it out if you have no better idea 🙂
z
The HTTP call isn’t necessarily the right layer to use the worker pool with – it just worked well for the example. If your system has additional layers, they should be considered as well.
t
Well the real need for that system is to limit the number of http calls in the end, so I feel stupid to not have thought about that as the input / output are similar the pattern works great. For the specific needs well they are specific and should be addressed as a specific part over the need and not the other way around like I tried to do since the start. So once again thanks for making me think in the opposite direction 🙂
So did a POC and everything works 🙂 Just have a few questions about the context switches that I posted at https://kotlinlang.slack.com/archives/C1CFAFJSK/p1541508621405300, maybe there's something to change.