Котлин сопрограммы - различные варианты использования области сопрограмм / контекста? - PullRequest
0 голосов
/ 15 марта 2019

Я новичок в Kotlin / Coroutines и заметил два разных способа использования CoroutineScope.

Вариант 1 заключается в следующем: в любой функции:

CoroutineScope(Dispatchers.Default).launch { 
    expensiveOperation() 
}

Вариант 2 заключается в реализации интерфейса CoroutineScope в вашем классе с переопределением CoroutineContext, а затем вы можете легко запускать сопрограммы с помощью launch или async:

@Service
class ServiceImpl() : CoroutineScope {

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Default + Job()

    fun someFunction() {
        launch {
            expensiveOperation()
        }
    }
}

В настоящее время я разрабатываю конечную точку бэкэнда, которая будет выполнять следующие действия:

  1. принять запрос
  2. сохранить контекст запроса в базе данных
  3. запустить неблокирующую сопрограмму в фоновом режиме для выполнения дорогостоящей / длительной операции над запросом и немедленно вернуть http 200. (по сути, как только мы сохраним контекст, мы можем вернуть ответ и позволить процессу запроса выполнить фон)

В чем разница между двумя вариантами использования и для этого сценария, который является предпочтительным методом для получения CoroutineScope?

Эта конечная точка может получать несколько запросов в секунду, и длительная операция займет одну или две минуты, поэтому, безусловно, одновременно будет обрабатываться несколько запросов, исходящих из различных запросов.

Кроме того, если это вариант 2, хочу ли я передать область / контекст функции, которая выполняет тяжелую обработку? Или это не нужно? Например:

class ServiceImpl (): CoroutineScope {

override val coroutineContext: CoroutineContext
    get() = Dispatchers.Default + Job()

fun someFunction() {
    launch {
        expensiveOperation(CoroutineScope(coroutineContext))
    }
}

private fun expensiveOperation(scope: CoroutineScope) 
    {
        // perform expensive operation
    }

}

Это приложение Spring Boot, и я использую версию 1.3 из Kotlin.

Пожалуйста, дайте мне знать, если у вас есть какие-либо мысли / предложения о том, как лучше структурировать этот класс обслуживания. Спасибо

1 Ответ

0 голосов
/ 16 марта 2019

Я бы порекомендовал вариант 2. Это даст вам возможность четко определить родителя Job для всех ваших сопрограмм.Это также дает возможность корректно завершить весь процесс.

Есть еще несколько контекстных ключей сопрограммы для включения - CoroutineName, CoroutineExceptionHandler и так далее.

Наконец, структурный параллелизм может работать лучше, если вы явно передадите CoroutineScope и связанное с ним задание.
https://medium.com/@elizarov/structured-concurrency-722d765aa952

Кроме того, посмотрите объяснение в этой форме Roman: https://medium.com/@elizarov/coroutine-context-and-scope-c8b255d59055

...