question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to do conditional async execution?

See original GitHub issue
interface TestPreconditionVoter {
    fun vote(context: Map<String, Any>): Vote
}

and voters = List<TestPreconditionVoter>() Based on a given boolean flag, I’d like to do the following:

  1. if true, execute vote parallelly.
  2. Otherwise. execute them sequentially.

Optionally, I’d like to replace the Map<String, Any> with something from the CoroutineContext that can be used as a temporary bag of data to pass from one voter to another. Note that in the first case, such data structure would have to be thread safe.

What’d be an idiomatic way to do this? Currently I’ve the following WIP code but I suspect there is a better way.

runBlocking {
    withTimeout(vote.timeoutMillis, TimeUnit.MILLISECONDS) {
        if (vote.castingStrategy == PARALLEL) {
            voters
                .map { async { it.vote(context) } }
                .groupBy({ it.await() }, { it.await() })
                .mapValues { it.value.size }
        } else {
            voters
                .map { it.vote(context) }
                .groupingBy { it }?.eachCount()
        }
    }
}

Kotlin 1.2.31, Coroutine 0.22.5

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
qwwdfsadcommented, Mar 28, 2018

@asarkar

Could you be little more specific please?

Sure. Paragraph about suspending functions:

Suspending functions can take parameters and return values in the same manner as regular functions, but they can only be called from coroutines and other suspending functions, as well as function literals inlined into those.

groupingBy is not suspending function and is not inlined into caller (which is runBlocking block with type suspend CoroutineScope.() -> T), thus calling suspend function from groupingBy is prohibited. E.g. map method is defined as public inline fun <T, R> Iterable<T>.map and is inlined into block, so any suspend function can be called from map

1reaction
fvascocommented, Mar 27, 2018

The code in your opening post apparently works.

Some considerations:

  1. vote is not a suspending functions, so it completes always (regardless withTimeout)
  2. async block is in a context different than withTimeout’s context, so it completes always (regardless withTimeout)
  3. the async concurrency level is the DefaultExecutor concurrency level and it never invokes any suspendig function, so the parallelism is limited (the case is not the same in the guide).

That code is much or less the same of:

if (vote.castingStrategy == PARALLEL) {
            ForkJoinExecutor.submit(...).wait()
        } else {
            voters.map { it.vote(context) }.groupingBy { it }?.eachCount()
        }
if ( timeExpired ) throw CancellationException()

If the above statements are right then I suppose you should review your code, and the proposed refinement is not a great enhancement.

My friendly suggestion is to avoid coroutines for this use case, do it using multithread (or understand better how coroutine works).

Sorry for frankness, please do not read any arrogance in this lines, it isn’t absolutely my goal.

Good luck, Vasco

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - What should an async method do if a Task is conditionally ...
1. Tell us why you inserted that code. It's not necessary and it's evidence that you must misunderstand something. · 2. It's not...
Read more >
Conditional await, anyone? - ESDiscuss.org
If the author knows the function they're calling is async, they can use await normally. If they know it's not async, they can...
Read more >
Conditional async? : r/typescript - Reddit
The basic idea is that the overhead of redundantly adding functions to the microtask queue to be executed at the end of the...
Read more >
Use Promise.all to Stop Async/Await from Blocking Execution ...
Use Promise.all to Stop Async/Await from Blocking Execution in JS. When writing asynchronous code, async/await is a powerful tool — but it comes...
Read more >
async function - JavaScript - MDN Web Docs - Mozilla
Async functions can contain zero or more await expressions. Await expressions make promise-returning functions behave as though they're ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found