簡體   English   中英

從控制器啟動 Kotlin 任務的范圍是什么?

[英]What scope to use for launching a task in Kotlin from a controller?

我的 Kotlin 應用程序正在使用 Spring 公開一個應該在后台執行長任務的 API。 我們需要返回

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

IntelliJ 抱怨說使用 GlobalScope 是一種反模式。 但是,我不能只將掛起添加到控制器功能,否則它將不起作用。 我不能使用runBlocking或者該方法需要等到完成產生 REST 超時

我應該添加什么作為此函數的范圍以使用結構化並發

您可能希望將 GlobalScope 以外的一些范圍注入到您的資源中。 如果您的框架已經提供了某種“應用程序范圍”,當您的應用程序關閉時將取消該“應用程序范圍”,那么這似乎是合適的。

做不到這一點 - 協程范圍只是 Job (以及其他協程上下文項)的包裝器。 所以你可以在app啟動的時候創建一個新的Job,簡單CoroutineScope(job)就可以讓你的應用成為協程范圍。 然后只需在應用程序關閉期間執行job.cancel() ,這將確保在該范圍內啟動的任何協程都將被取消。

編輯添加我的解決方案:

private val jobScope = CoroutineScope(IO)

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

@PreDestroy
fun stopTasks() {
    jobScope.cancel("Closing app")
}

要利用結構化並發,如並行分解部分中所述,您可以使用coroutineScope函數:

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

refresh()應標記為suspend以使用coroutineScope

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM