When to initiate a new scope in Kotlin

Viewed 158

I have a blocking rest call in my code, and I would like to run it in a different context than the GlobalScope one (which is the best practice all over) but I do not understand if I also need to create a new scope for that operation as well.

On the one hand, it is said to run also on a different scope than the Global one, and with that, that effectively, scope and context are almost the same things.

I am running in a Spring WebFlux (netty) application and consuming rest calls. Consider the following code samples:

This one seems to be the "best practice one" (where this blogpost https://medium.com/@elizarov/coroutine-context-and-scope-c8b255d59055#:~:text=The%20difference%20between%20a%20context,is%20in%20their%20intended%20purpose.&text=It%20makes%20the%20scope%20in,it%20in%20the%20function%20signature. specifically says not to use CoroutineScope(Dispatchers.IO).launch

    val blockingScope = CoroutineScope(Dispatchers.IO)
    suspend fun one() = withContext(blockingScope.coroutineContext) {
        val queryParams = arrayOf(
             BasicNameValuePair("name", "key"),
        )
        blockingClient.get("...", JsonNode::class.java, queryParams)
    }

As well, do I need to take care of the blockingScope.cancel() here?

But what prevents me from using this all the same (or how will it affect the application)

    suspend fun one() = withContext(Dispatchers.IO) {
        val queryParams = arrayOf(
             BasicNameValuePair("name", "key"),
        )
        blockingClient.get("...", JsonNode::class.java, queryParams)
    }
1 Answers

what prevents me from using this all the same (or how will it affect the application)?

The two snippets you posted should be pretty much the same in terms of functionality. In the first one, you're creating a scope with Dispatchers.IO as its context and then calling the withContext builder function with the CoroutineContext you just passed to your newly created scope. In the second one, you just pass it directly.

Note however, that if you use the CoroutineScope you created in the first snippet to launch other coroutines, then cancellation or failure of any child coroutines of your scope will lead to cancellation of all other childern (further reference at the kotlinx.coroutines documentation).

As well, do I need to take care of the blockingScope.cancel() here?

If you mean by taking care of blockingScope.cancel() you mean needing to call .cancel() here on your scope, then no, you don't. You call this function on a CoroutineScope to cancel all its child coroutines. So unless that's what you want to do, you shouldn't call this function :)

Remark

As pointed out in the comments to your question, the warning regarding

CoroutineScope(coroutineContext).launch{...}

is because one's accessing the current coroutineContext here to launch another coroutine - so depending on what's the current context, the new coroutine could be launched in one context or another - you wouldn't know just by looking at the function code.

Related