Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

191
Views
How to implement timeout without interrupting a calculation in Kotlin coroutine?

Let's say a request started a long calculation, but ready to wait no longer than X seconds for the result. But instead of interrupting the calculation I would like it to continue in parallel until completion.

The first condition ("wait no longer than") is satisfied by withTimeoutOrNull function.
What is the standard (idiomatic Kotlin) way to continue the computation and execute some final action when the result is ready?

Example:

  fun longCalculation(key: Int): String { /* 2..10 seconds */}


  // ----------------------------
  cache = Cache<Int, String>()

  suspend fun getValue(key: Int) = coroutineScope {

      val value: String? = softTimeoutOrNull(
              timeout = 5.seconds(), 
              calculation = { longCalculation() },
              finalAction = { v -> cache.put(key, v) }
      )

      // return calculated value or null
  }
over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

This is a niche enough case that I don't think there's a consensus on an idiomatic way to do it.

Since you want the work to continue in the background even if the current coroutine is resuming, you need a separate CoroutineScope to launch that background work, rather than using the coroutineScope builder that launches the coroutine as a child coroutine of the current one. That outer scope will determine the lifetime of the coroutines that it launches (cancelling them if it is cancelled). Typically, if you're using coroutines, you already have a scope on hand that's associated with the lifecycle of the current class.

I think this would do what you're describing. The current coroutine can wrap a Deferred.await() call in withTimeoutOrNull to see if it can wait for the other coroutine (that's not a child coroutine since it was launched directly from an outer CoroutineScope) without interfering with it.

suspend fun getValue(key: Int): String? {
    val deferred = someScope.async {
        longCalculation(key)
           .also { cache.put(key, it) }
    }
    return withTimeoutOrNull(5000) { deferred.await() }
}

Here's a generalized version:

/**
 * Launches a coroutine in the specified [scope] to perform the given [calculation]
 * and [finalAction] with that calculation's result. Returns the result of the
 * calculation if it is available within [timeout].
 */
suspend fun <T> softTimeoutOrNull(
    scope: CoroutineScope,
    timeout: Duration,
    calculation: suspend () -> T,
    finalAction: suspend (T) -> Unit = { }
): T? {
    val deferred = scope.async {
        calculation().also { finalAction(it) }
    }
    return withTimeoutOrNull(timeout) { deferred.await() }
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!