Hi all! I'm writing some code using coroutines and...
# coroutines
j
Hi all! I'm writing some code using coroutines and wanted to make sure I wasn't using an antipattern:
Copy code
class TSCompiler {
    private val dispatcher = Executors.newFixedThreadPool(24).asCoroutineDispatcher()

    public suspend fun compile(program: Any) = coroutineScope {
        launch(dispatcher) {
            // do something that takes awhile!
        }
    }
}
Would it be better in this case to just use the Executor directly, rather than using it as a coroutine Dispatcher?
g
What is your use case for this fixed dispatcher? You of course can use executor, because you don’t use much from coroutines. but you could use more, for example
program
can be suspendable itself and support cancellation, but it requires another approach for such executor
In general, you don’t need coroutine scope and launch in this case, just use
withContext(dispatcher)
also, I would just use IO dispatcher if code of
program
is blocking or
Default
if it’s CPU consuming
j
Awesome, thank you! This code is called as part of a Ktor request handler - it spawns another process and waits for it to finish, collects its output, and sends it back.
g
if you wait for execution result you probably want return something from
compile
function, not just Job
I would have a function, where you pass program and getting result, this is good use case of coroutines which would be hard to do in a non-blocking way with executors
j
Gotcha. I'll try this instead. Thank you for your advice!
g
Something like that
Copy code
public suspend fun compile(program: Any): CompiationResult {
    return withContext(YOUR_DISPATCHER) {
          doBlockingCompilation(program)
    }
}
so this allow you to use this function in non-bloking coroutine code:
Copy code
post("/compile") {
    val program = call.request.body()
    val compiled = compile(program) // Non blocking compilation
    call.respond(compiled.logs) // we can use result when it's ready
}