Kris Wong
01/27/2020, 5:15 PMKris Wong
01/27/2020, 5:29 PMbasher
01/27/2020, 5:50 PMKris Wong
01/27/2020, 5:54 PMkpgalligan
01/27/2020, 6:02 PMkpgalligan
01/27/2020, 6:03 PMkpgalligan
01/27/2020, 6:03 PMkpgalligan
01/27/2020, 6:03 PMopen class BaseModel : KoinComponent {
internal val mainScope = MainScope(Dispatchers.Main)
internal val ktorScope = MainScope(Dispatchers.Main)
open fun onDestroy() {
mainScope.job.cancel()
ktorScope.job.cancel()
}
}
internal class MainScope(private val mainContext: CoroutineContext) : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = mainContext + job + exceptionHandler
internal val job = Job()
private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
showError(throwable)
}
//TODO: Some way of exposing this to the caller without trapping a reference and freezing it.
fun showError(t: Throwable) {
printThrowable(t)
}
}
Kris Wong
01/27/2020, 6:41 PMKris Wong
01/27/2020, 6:51 PMKris Wong
01/27/2020, 6:51 PMkpgalligan
01/27/2020, 6:52 PMKris Wong
01/27/2020, 6:58 PMCoroutineScope(Dispatchers.Main).async {
validationService.validateMessagesReceived(
config.validationUrl, config.validationAccount, sentSuccessfully
)
}.await()
Kris Wong
01/27/2020, 6:59 PMvalidateMessagesReceived
creates the client, sends the request, and consumes the responseKris Wong
01/27/2020, 6:59 PMKris Wong
01/27/2020, 7:00 PMKris Wong
01/27/2020, 7:02 PMKris Wong
01/27/2020, 7:05 PMrunBlocking
kpgalligan
01/27/2020, 7:07 PMktorScope.launch {
val breedResult = ktorApi.getJsonFromApi()
val breedList = breedResult.message.keys.toList()
insertBreedData(breedList)
settings.putLong(DB_TIMESTAMP_KEY, currentTimeMS)
}
kpgalligan
01/27/2020, 7:08 PMinsertBreedData
we launch aother coroutine, so the ktor scope doesn’t leave the main threadkpgalligan
01/27/2020, 7:08 PMprivate fun insertBreedData(breeds: List<String>) {
mainScope.launch {
dbHelper.insertBreeds(breeds)
}
}
kpgalligan
01/27/2020, 7:08 PMkpgalligan
01/27/2020, 7:10 PMCoroutineScope(Dispatchers.Main).async
etc is itself calling from a thread that isn’t main, then you are on some level crossing thread boundaries.Kris Wong
01/27/2020, 9:14 PMKris Wong
01/27/2020, 9:15 PMkpgalligan
01/27/2020, 9:15 PMKris Wong
01/27/2020, 9:16 PMkpgalligan
01/27/2020, 9:16 PMkpgalligan
01/27/2020, 9:17 PMKris Wong
01/27/2020, 9:17 PMoverride fun messageSent(messageId: String, success: Boolean) = runBlocking {
channel.send(messageId to success)
}
Kris Wong
01/27/2020, 9:17 PMdispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
accessor.messageSent("1", true)
accessor.messageSent("2", true)
accessor.messageSent("3", true)
Unit
}.freeze())
Arkadii Ivanov
01/27/2020, 9:19 PMKris Wong
01/27/2020, 9:19 PMkpgalligan
01/27/2020, 9:20 PMKris Wong
01/27/2020, 10:55 PMkpgalligan
01/28/2020, 12:48 PMKris Wong
01/28/2020, 1:42 PMKris Wong
01/28/2020, 1:42 PMrunBlocking
deadlock, but hindsight is always 20/20