viralshah
04/11/2020, 3:58 PMfun CoroutineScope.foo() = launch{//some stuff}
vs
fun foo() = CoroutineScope { launch{//some stuff}}
vs
fun foo(){ coroutineScope { launch { // some stuff } } }
? ThanksFranco
04/12/2020, 9:05 AMsuspendCancellableCoroutine
completes so I can unsubscribe from the callback that might return more values later on.
My use case is that I'm trying to get the user from Firebase using the onAuthStateChanged()
listener as they suggest here. However, I don't want to keep listening for this after getting it at the start of the app and if I don't unsubscribe from it then I get the error IllegalStateException: Already resumed, but proposed with update
.
This is an example of my code:
suspend fun getUser(): User = suspendCancellableCoroutine { continuation ->
val unsubscribe = firebaseAuth.onAuthStateChanged(
nextOrObserver = { user -> continuation.resume(user) },
error = { error -> continuation.resumeWithException(...) }
)
}
CLOVIS
04/12/2020, 2:37 PMCompletableDeferred
as a mirror of another one? As in, I have two or more `CompletableDeferred`that I know are waiting for the same value, so I'd like to ‘merge' them so that completing the ‘master' automatically completes the ‘slaves'.
So far I've come up with:
fun <T> CoroutineScope.merge(
master: CompletableDeferred<T>,
slave: CompletableDeferred<T>
) = launch {
master.await().also { result ->
slave.complete(result)
}
}
However this creates a new coroutine, and I'm wondering if there's a better way to achieve a similar goal.Kirill Prybylsky
04/13/2020, 10:32 AMfun scan() = callbackFlow<Device> {
deviceChannel = channel
hardwareChecker.scanDevices()
}
nicholasnet
04/13/2020, 3:27 PMsuspend fun processRequest(request: Request): Result = coroutineScope {
val jobId = UUID.randomUUID().toString()
val deferredMessage = async {
redisOperations.listenToChannel(jobId).awaitFirst()
}
val deferredProducer = async(start = CoroutineStart.LAZY) {
adtMessageProducer.send(adtRequest, jobId)
}
deferredProducer.await()
deferredMessage.await().message
}
viralshah
04/14/2020, 5:06 AM@Test
fun `should fetch JsonObject when call executes successfully`() = runBlockingTest {
coEvery { webClient.get().uri(any<URI>()).awaitExchange().awaitBody<String>() } returns "{}"
val result = service.fetchData(paramsMap, transactionId)
assertThat(result).isNotNull
assertThat(result).isInstanceOf(JsonObject::class.java)
}
Hi Guys, my test is hanging for some reason, could you help me figure out why?Martin Nordholts
04/14/2020, 10:54 AMCoroutineExceptionHandler
never handle CancellationException
? That seems to be the case (see example program in thread) but I can’t find a clear authoritative statement on that this is the case.
For example, docs for interface CoroutineExceptionHandler states
when no handler is installed […] CancellationException […] is ignoredrather than “CancellationException is always ignored with CoroutineExceptionHandler”
Ahmed Ibrahim
04/14/2020, 6:12 PMuserRepository.streamUser().filterLoggedIn().firstOrNull()
The repository returns a Logged Out user, but I'm only interested in logged in users, I would expect that since this flow becomes an empty flow, then firstOrNull
should return null, right or am I missing something?Syex
04/15/2020, 7:12 AMCoroutineScope
as an input in order to launch
some new coroutines. If any of these coroutines throw an exception it should delegate them to the initially given CoroutineScope
. However, I figured out, if this scope has a SupervisorJob()
all exceptions of my launched coroutines are just silently swallowed, which is probably working as intended.
Is there any way I still can crash the application? I tried to create my own scope via CoroutineScope(initialScope.coroutineContext + Job())
, but it still keeps the behavior of the supervisor job.Christian Sousa
04/15/2020, 4:06 PM@Test
fun fetchAvailableStuff() {
runBlockingTest {
val job = launch(Dispatchers.Main) {
api.fetchAvailableStuff { success ->
println("----------- TEST -----------")
println(success)
}
}
job.join()
}
}
But it gives me:
java.lang.IllegalStateException: This job has not completed yet
I already tried some of the solutions that are in this channel but with no luckJakub Walusiak
04/15/2020, 4:11 PMJob
from my scope later (e.g by marking it in some way)?elizarov
04/15/2020, 4:51 PMkotlinx.coroutines
library in the next major release. It concerns "atomic cancellation" behavior of Channel
send
and receive
functions. It might affect your code if you've ever used channels to transfer resources (references that need to be closed, like open files, sockets, etc) between coroutines via channels and if you were relying on those guarantees to ensure that the corresponding resource get closed by either sender or receiver and thus never leaks. If this is the case, then, please, study the details of the proposed change and voice your concern if the change is going to negatively affect the code you maintain: https://github.com/Kotlin/kotlinx.coroutines/issues/1813Erik
04/15/2020, 5:15 PMwithContext
docs:
The resulting context for the block is derived by merging the currentFrom thewith the specifiedcoroutineContext
usingcontext
(seecoroutineContext + context
).CoroutineContext.plus
CoroutineContext.plus
docs:
Returns a context containing elements from this context and elements from otherFrom these docs I conclude that any. The elements from this context with the same key as in the other one are dropped.context
CoroutineExceptionHandler
in the context
in withContext(context)
call replaces the one from the parent scope of withContext
. So why does @Manuel Vivo write in his excellent article (https://medium.com/androiddevelopers/coroutines-patterns-for-work-that-shouldnt-be-cancelled-e26c40f142ad):
CoroutineExceptionHandlers don’t work as you’d expect when the context is used in withContext since the exception will be re-thrown.So how come that a thrown exception is handled by the parent exception handler (which might rethrow it) , instead of handled by the overridden exception handler?
gotoOla
04/15/2020, 8:55 PMAlex Gotev
04/15/2020, 9:41 PMGiorgos Neokleous
04/16/2020, 1:57 PMMaciek
04/16/2020, 4:33 PMLukas Lechner
04/17/2020, 12:14 PMDennis Schröder
04/17/2020, 3:20 PM@RestController
class PageController(
private val pageService: PageService,
) {
private val context = <http://Dispatchers.IO|Dispatchers.IO>
@GetMapping(PAGES_BY_SLUG)
suspend fun getPage(
@PathVariable slug: String,
): PageResponse =
withContext(context) { pageService.getPage(slug) }
}
}
My motivation is to keep the webflux threadpool clean from everything that does not relate to the request till it reaches the controller.
But does really have an positiv affect on performance? Or does the context switch here is even bad because it comes with an cost?zak.taccardi
04/17/2020, 6:25 PMdelay(..)
reports IDLE or not in an Espresso test dynamically at runtime. What would be the right way to handle this?.
For example, if a delay(..)
launched on Dispatchers.Default
is currently suspended, I would like to be able to control at any point through the test whether the dispatcher should report idle or notMaciek
04/18/2020, 10:53 AMwaltermcq
04/19/2020, 12:25 PMGopal S Akshintala
04/19/2020, 3:14 PMinternal class MyRecursiveTask(private val names: List<String?>) : RecursiveTask<String>() {
override fun compute(): String = if (names.size > MIN_LIST_SIZE) {
val mid = names.size / 2
val myRecursiveTask1 = MyRecursiveTask(names.subList(0, mid))
val myRecursiveTask2 = MyRecursiveTask(names.subList(mid, names.size))
myRecursiveTask1.fork()
myRecursiveTask2.fork()
val results = ArrayList<String>()
results.add(myRecursiveTask1.join())
results.add(myRecursiveTask2.join())
concat(results) // This just concats strings
} else {
concat(names) // This just concats strings
}
companion object {
private const val serialVersionUID = -5978274303314688527L
private const val MIN_LIST_SIZE = 2 // In real-world, DO NOT have it below 10,000
}
}
iex
04/19/2020, 9:12 PMoverride fun foo(): List<String> =
runBlocking {
fooSuspended()
}
suspend fun fooSuspended(): List<String> =
coroutineScope {
val res: List<Deferred<String?>> = (1..100).map { n ->
async {
doWork()
}
}
res.mapNotNull { it.await() }
}
fun doWork(): String? {
Thread.sleep(500)
return "hi"
}
iex
04/19/2020, 10:28 PMNick
04/19/2020, 10:32 PMMarc Knaup
04/20/2020, 11:30 AMpakoito
04/20/2020, 12:04 PMMarc Knaup
04/20/2020, 2:00 PMJob
to launch
as it breaks parent/child-relationship 😅
We’ve got to take the Job
returned by launch
instead.wadva
04/20/2020, 2:15 PM