Romain
03/11/2019, 2:15 PMkevin.cianfarini
03/11/2019, 3:00 PMgiso
03/11/2019, 4:14 PMsbyrne
03/11/2019, 8:30 PMobobo
03/11/2019, 11:12 PMrunBlocking
block. I have a test in which I mock an external service integration throwing an exception. Via runBlocking
I call the suspending function, which in turn creates a new CoroutineScope using CoroutineScope(coroutineContext + <http://Dispatchers.IO|Dispatchers.IO>)
and creates many deferred calls using async
to the mocked external service, then uses awaitAll()
to get their results. Surrounding this code is a try/catch block, which handles the exception. I've stepped in and all of this is working fine.
The problem is when the suspending function returns, the surrounding block declares it exited exceptionally and throws an exception from the runBlocking call. Since I'm handling the exception, what's the right way to prevent the context from picking up the exception?Dmytro Danylyk
03/12/2019, 5:02 AMasync
, coroutineScope
and exception handling. When coroutineScope
is moved into separate function, I am able to catch exception inside coroutine. When coroutineScope
is declared inside coroutine, I am not able to catch exception.
This code works fine:
suspend fun doWork(): Deferred<String> = coroutineScope {
async(<http://Dispatchers.IO|Dispatchers.IO>) {
throw IllegalArgumentException()
}
}
// works fine
fun loadData() = scope.launch {
try {
doWork().await()
} catch (e: Exception) {
// exception is caught here
}
}
This doesn’t.
// crash FATAL EXCEPTION: DefaultDispatcher-worker-3 @coroutine#1
fun loadData() = scope.launch {
try {
val deferred = coroutineScope {
scope.async(<http://Dispatchers.IO|Dispatchers.IO>) {
throw IllegalArgumentException()
}
}
deferred.await()
} catch (e: Exception) {
// exception is NOT caught here
}
}
Martin Devillers
03/12/2019, 2:29 PMclose
method on SendChannel
? IMO it’s a bit confusing, because it brings up the idea of a Closeable
, which is very different (especially since there are plenty of channels which don’t need to be closed because they send indefinitely). The documentation leads me to suggest something like sendLast
, which I think would convey the intent better.hmole
03/13/2019, 7:01 AMsample
operator from RX on a Channel
? I need to discard items from the channel if they come at the higher rate than I specify.Aaron Stacy
03/13/2019, 1:45 PMsuspend fun request(url: URL): MyDataClass
, but I want to cache the HTTP results so I don’t make requests twice. Anyone know a good example of how to do that? @elizarov’s excellent post https://medium.com/@elizarov/deadlocks-in-non-hierarchical-csp-e5910d137cc has a nice example, but the only way I can think to wrap the channels in a suspend function is using `Deferred`’s. Is that the way to do it? It feels clunky.ahulyk
03/13/2019, 2:31 PMclass Presenter() : CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onDestroy() {
job.cancel()
}
fun loadData() {
launch {
try {
//loadData().async()
} catch (e: Exception) {
//handle exception
}
}
}
}
class Presenter() : CoroutineScope {
private val job = SupervisorJob()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onDestroy() {
job.cancel()
}
fun loadData() {
launch {
try {
//loadData().async()
} catch (e: Exception) {
//handle exception
}
}
}
}
ghedeon
03/13/2019, 8:31 PMfun CoroutineScope.foo()
basically kills the usage of Mockito in my project, right? It has some support for suspended functions, but not extensions. So, mockk
is the only answer or there are workarounds? That's quite a change for a big codebase...ansman
03/13/2019, 9:10 PMrunBlocking
? I’m bridging a blocking API that gives me a CancelationSignal
that can notify when canceledoday
03/14/2019, 1:48 PMAaron Stacy
03/14/2019, 4:01 PMHttpURLConnection
, reading an InputStream
) to a coroutine, it seems like I'd want to do something to suspend the coroutine while waiting on the network or disk. Is there a good example of this?jw
03/14/2019, 4:08 PMasync(IO) { .. }
louiscad
03/14/2019, 6:13 PMasync
is only for parallelization. I avoid recommending it unless you need it because I saw a lot of misuse regarding it that broke structured concurrency and throwables handling.jw
03/14/2019, 6:40 PMOleh Ponomarenko
03/15/2019, 11:08 AMMartin Devillers
03/15/2019, 1:27 PMobject InactiveScope
the standard library, which would be a CoroutineScope
instance with an job always in a cancelled state?
I think this would be useful in cases when we have a scope var which isn’t initialized at object creation, so we could use this object as a placeholder rather than using a null value. I’m thinking about scopes tied to Android activity states, i.e. activityCreatedScope
, activityStartedScope
, activityResumedScope
. Currently the solutions are to use lateinit
or nullable var
.davidasync
03/15/2019, 2:38 PMspierce7
03/15/2019, 7:28 PMSUPERCILEX
03/15/2019, 9:59 PMFatal Exception: java.net.SocketTimeoutException: timeout
at okio.Okio$4.newTimeoutException(Okio.java:232)
at okio.AsyncTimeout.exit(AsyncTimeout.java:275)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:243)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:354)
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:226)
at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:215)
at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at support.bymason.magicwand.core.data.PlatformRequestsKt$client$1.intercept(PlatformRequests.kt:18)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:2254)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
SUPERCILEX
03/15/2019, 10:03 PMJemshit Iskenderov
03/16/2019, 6:30 AMCoroutineScope.cancel()
and CoroutineScope.job.cancel()
.
Here is the CoroutineScope:
val scope = object : CoroutineScope {
val parentJob = Job()
override val coroutineContext: CoroutineContext
get() = parentJob + <http://Dispatchers.IO|Dispatchers.IO>
}
Observation 1: when Job of CoroutineScope is cancelled, both seemed not active:
scope.launch {
withContext(Dispatchers.Default) {
println("result")
}
scope.parentJob.cancel()
println("isActive:$isActive, job.isActive:${scope.parentJob.isActive}")
// PRINTS isActive:false, job.isActive:false
}
Observation 2: when CoroutineScope is cancelled, only CoroutineScope.isActive seems false. Job.isActive is true
scope.launch {
withContext(Dispatchers.Default) {
println("result")
}
cancel()
println("isActive:$isActive, job.isActive:${scope.parentJob.isActive}")
// PRINTS isActive:false, job.isActive:true
}
Observation 3 (CoroutineScope for Android Fragment):
protected lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
launch {
val result = withContext(Dispatchers.Default) {
// ...
}
this@Fragment.job.cancel()
// Log.d("$isActive ${this@Fragment.job.isActive}")
// PRINTS true, false
}
Question: when looking at source code, CoroutineScope.cancel
and CoroutineScope.isActive
calls methods of its Job. But in above code, CoroutineScope.cancel
does not return Job.isActive
or vice versa. Why this behavior? Is withContext
changing something?Hexa
03/16/2019, 9:07 AMif(carId.isNullOrEmpty())
statement here as it looks duplicated code to me.
deferredCarIdResult.await()
can return an empty string like this "" so I return CarNotFound("not found") but when the coroutines timeout I also return CarNotFound("not found")
val carId = runBlocking {
withTimeoutOrNull(10000L) {
deferredCarIdResult.await()
}
} ?: return CarNotFound("not found")
if(carId.isNullOrEmpty()){
return CarNotFound("not found")
}
Jay
03/16/2019, 12:43 PMdavidasync
03/16/2019, 12:46 PMjava NIO
already have asynchronous nature for example Jetty Http Client, asynchttpclient, apache async http client, and etc
is it necessary to wrap it with coroutines to do parallel http call ?davidasync
03/18/2019, 8:05 AMjava NIO
but using coroutines (or another lightweight thread) instead of native thread ?Ellen Shapiro
03/18/2019, 4:48 PMrunBlocking
on K/N because I could never successfully get it to import. But @russhwolf pointed out that it is definitely there. I looked in my local kotlinx-coroutines-core-1.1.1
and lo and behold, there it is. What am I missing about getting it to import in a common
framework?qwert_ukg
03/19/2019, 10:05 AMqwert_ukg
03/19/2019, 10:05 AMgildor
03/19/2019, 10:07 AMqwert_ukg
03/19/2019, 10:10 AMsendAndSaveResult(uuid, message)
take a lot of timegildor
03/19/2019, 10:18 AMqwert_ukg
03/19/2019, 10:18 AM