Home > Blockchain >  What scope to use for launching a task in Kotlin from a controller?
What scope to use for launching a task in Kotlin from a controller?

Time:07-05

My Kotlin App is using Spring to expose an API that should execute a long task in the background. We need to return

@PutMapping("/refresh")
fun refresh() = {
    GlobalScope.launch(IO) { refreshDataFromCache() }
    return ResponseEntity.accepted().body("""{"result": "accepted"}""")
}

IntelliJ complains that using the GlobalScope is an anti-pattern. However, I cannot just add suspend to the controller function or it won't work. Neither I can use runBlocking or the method will need to wait until finishing producing a REST timeout

What should I add as the scope of this function to use structured concurrency?

CodePudding user response:

To leverage structured concurrency, as described here in the Parallel decomposition section, you can use coroutineScope function:

@PutMapping("/refresh")
suspend fun refresh() = coroutineScope {
    async { refreshDataFromCache() } // this will run in parallel
    ResponseEntity.accepted().body("""{"result": "accepted"}""")
}

refresh() should be marked as suspend to use coroutineScope.

CodePudding user response:

You probably want to inject some scope other than GlobalScope into your resource. If your framework already provides some sort of "application scope" that will be cancelled when your application shuts down, that seems appropriate.

Failing that -- a coroutine scope is just a wrapper around a Job (well, and other coroutine context items). So you can create a new Job during app startup, and simply CoroutineScope(job) to make your application coroutine scope. Then just do job.cancel() during app shutdown and that will ensure any coroutines launched in that scope will be cancelled.

  • Related