```@Component class RiskAssertionFeedbackHandler( ...
# coroutines
n
Copy code
@Component
class RiskAssertionFeedbackHandler(


) {
    companion object {
        
    }

    fun sendFeedback (authZResponse: AuthZResponse){
        val customScopeLocal = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO> + MDCContext())
        customScopeLocal.launch {
            when {
                isOperationSupportedForAuthBlock(authZResponse, reason!!, operationMethodName!!) -> {
                    authBlockedFeedbackHandler.recordAuthBlocked(authZResponse, reason , operationMethodName)
                }
          
            }
        }
    }

    fun sendFeedback(operationMethodName: String, feedbackTransaction: FraudTransaction) {
        ThreadContextLocal.addAllAttributesToMDC()
        val customScope = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO> + MDCContext())
        customScope.launch {
            when (feedbackTransaction) {
                FraudTransaction.AUTH_BLOCKED -> authFailedFeedbackHandler.recordAuthFailed(operationMethodName)
                FraudTransaction.UAF_REG_PASS -> uafRegPassFeedbackHandler.recordUAFRegPass(operationMethodName)
                FraudTransaction.UAF_REG_FAILED -> uafRegFailedFeedbackHandler.recordUAFRegFailed(operationMethodName)
            }
        }
    }
Is this efficient way to launch coroutines ? I read that CoroutineScope is also same as GlobalLaunch and not good for production.
e
it is not a good way to do that, no
not enough context to determine what the right scope is, but in most cases I would say it should be injected instead of created by a class like this
👍 1
n
Can you pls give an example?
This coroutine is used to make a rest api call to downstream api
Also functions from this class are invoked in during api processing to make an async call
Because callers of this function are not suspended,need to find a way call suspended functions from non- suspended one
@ephemient can you pls help with above ?
Can someone help with this ?
r
Typical pattern I use with Spring is this:
Copy code
@Configuration
class MyConfiguration {

    @Qualifier("default")
    @Bean
    fun defaultDispatcher() = Dispatchers.Default
}

@Component
class MyComponent(
    @Qualifier("default") private val defaultDispatcher: CoroutineDispatcher,
) {
    private val backgroundScope = CoroutineScope(
        defaultDispatcher +
                SupervisorJob() +
                CoroutineExceptionHandler { coroutineContext, throwable ->
                    // logging
                }
    )
    
    fun launchBackgroundWork(): Job {
        return backgroundScope.launch { 
            // Background work
        }
    }

    fun launchOtherBackgroundWork(): Job {
        return backgroundScope.launch {
            // Background work
        }
    }
    
    @PreDestroy
    fun destroy() {
        backgroundScope.cancel()
    }
}
Inject the dispatchers so that it can be replaced for testing Create a scope per service component with appropriate exception handling/logging Use SupervisorJob so that one launched task failing doesn't cause the scope to terminate Use
@PreDestroy
to ensure the scope is bound to the bean's lifecycle (particularly useful if your Spring application does context reloads). I often return Job when launching background work so that the calling method can optionally choose to wait for completion with join, but this is optional
n
Thanks for responding
I need to pass mdc context with each request from which coroutine will be started
r
ah yeah so that's just:
Copy code
fun launchOtherBackgroundWork(): Job {
        return backgroundScope.launch(MDCContext()) {
            // Background work
        }
    }
n
Thank you so much!
r
👍
n
One follow up question on this, if one coroutine fails in background scope will it block execution of other coroutines ?
r
no, because of the added
SupervisorJob()