Skip to content

Instantly share code, notes, and snippets.

@thomashorta
Created September 21, 2022 02:18
Show Gist options
  • Save thomashorta/f74dfd1312234fbb1bb85e3cb64689ce to your computer and use it in GitHub Desktop.
Save thomashorta/f74dfd1312234fbb1bb85e3cb64689ce to your computer and use it in GitHub Desktop.
runCatching alternative for suspend functions for proper structured concurrency.
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.TimeoutCancellationException
/**
* Very similar to [runCatching] but it's better suited for use inside suspend functions, as it
* properly propagates [CancellationException], which are required for correct structured
* concurrency in Coroutines.
*
* Calls the specified function [block] with `this` value as its receiver and returns its
* encapsulated result if invocation was successful, catching any [Throwable] exception that was
* thrown from the [block] function execution and encapsulating it as a failure, also properly
* handling (and rethrowing) [CancellationException] for correct Coroutines usage.
*
* @see runCatching
*/
// suppressed warning because it looks like a false positive, as reported in
// https://youtrack.jetbrains.com/issue/KT-44481
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
suspend inline fun <T, R> T.runSuspendCatching(block: suspend T.() -> R): Result<R> {
return try {
Result.success(block())
} catch (e: TimeoutCancellationException) {
// timeout cancellations are most likely real failures, map to a failure
Result.failure(e)
} catch (e: CancellationException) {
// other cancellations need to be rethrown for correct coroutines structured concurrency
throw e
} catch (e: Throwable) {
// any other throwable will be caught and mapped to a failure
Result.failure(e)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment