Robert Jaros
03/09/2023, 2:35 PMTower Guidev2
03/09/2023, 4:32 PMVsevolod Tolstopyatov [JB]
03/09/2023, 4:50 PMChannel
, Mutex
and select
implementations
• JPMS support
• Merge of kotlinx-coroutines-core
and kotlinx-coroutines-jdk8
• Partial stabilization and notable improvements of kotlinx-coroutines-test
• More K/N support: all official targets, better dispatchers, <http://Dispatchers.IO|Dispatchers.IO>
And many more! Full changelog: https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.7.0-BetaDaniel
03/10/2023, 6:12 PMsuspend fun Logout(token: String) {
val userId = appService.currentUser!!.id ///// this will execute 1st
realm.write { ///// this will execute 2nd
var user = query<UserInfo>("_id = $0", userId).first().find()
if (user != null) {
user = findLatest(user)!!.also {
it.FCMToken.remove(token)
}
copyToRealm(user)
}
}
withContext(Dispatchers.Default) { ///// this will execute 3rd
realm.syncSession.uploadAllLocalChanges() ///// this will execute 4rd
appService.currentUser?.logOut() ///// this will execute 5th
}
}
Are they executed in a linear way?Kshitij Patil
03/14/2023, 5:16 AMSlackbot
03/14/2023, 11:19 AMnatario1
03/14/2023, 12:16 PMclass Processor {
private val condition1 = MutableStateFlow(false)
private val condition2 = MutableStateFlow(false)
private suspend fun process(): Processed { ... }
init {
someScope.launch {
combine(condition1, condition2) { a, b -> a || b }
.collectLatest { process() }
}
}
fun setCondition1() { condition1.value = true }
fun setCondition2() { condition2.value = true }
}
When the user changes one of the conditions, I would like to
• know if this change did not trigger a process()
(for example, throw if not)
• return something like a Deferred<Processed>
to be (optionally) awaited.
Does anyone have any idea on how to achieve this?jean
03/14/2023, 12:52 PMawaitClose
from my unit test ? I tried to cancel testScope
but that triggers a ClosedReceiveChannelException: Channel was closed
since turbine gets also canceled.
private fun someApiCallbackToFlow(api: API) = callbackFlow {
val callback = object : ApiCallback {
override fun next(data: Int) {
trySend("Success")
}
}
api.register(callback)
awaitClose {
println("callback unregistered")
api.unregister(callback)
}
}
@OptIn(ExperimentalTime::class)
@Test
fun test() = testScope.runTest {
val api = SomeApi()
val flow = someApiCallbackToFlow(api)
flow.test {
assertEquals(1, api.callbacks.size)
api.getData()
assertEquals("Success", awaitItem())
// how can I check there isn't any callback here?
}
}
KotlinLeaner
03/15/2023, 10:40 PMrunTest
. I have a simple viewModel
class LoadingViewModel(
private val ioDispatcher: CoroutineDispatcher,
) : ViewModel() {
var xyz by mutableStateOf(false)
fun checkXyz() {
viewModelScope.launch {
delay(1000L)
xyz = true
}
}
}
more code in 🧵Patrick Steiger
03/16/2023, 12:15 AMsupervisorScope
while still capturing all exceptions (aggregated) that are thrown in them.
Note that I do not want failure of a child to cancel other children (or the scope), hence supervisor scope, but I might want to “sum” (probably addSuppressed
) all exceptions and throw it later after scope is done
Right now I’m using withContext
with a custom CoroutineExceptionHandler
that puts all exceptions in a collection and later reduce the collection and throw, but it just feels boilerplate-y and wonder if I’m missing somethingSam Stone
03/16/2023, 8:05 PMPHondogo
03/17/2023, 9:27 PMTeimatini Marin
03/18/2023, 12:21 AMimport kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
fun main() = runBlocking {
produceFlowNumbers()
.collect { // First collect
squareFlow(it)
.collect { // Second collect inside First collect
println(it)
}
}
println("Done!") // we are done
}
fun produceFlowNumbers() : Flow<Int> = flow {
var x = 1
while (x < 5) emit(x++) // infinite stream of integers starting from 1
}
fun squareFlow(number: Int): Flow<Int> = flow {
emit(number*number)
}
I have the feeling that I'm missing something here.
Any suggestion experts?Nino
03/20/2023, 3:35 PMrunCatching
is in use in any of your Kotlin (or Android) projects ? I feel my team is abusing it and I'm trying to understand if there's any "pros" about using it in any coroutine-based codebase. My team just adopted this convention and I'm at loss of words.
(Examples in thread for anyone interested)Mark Vogel
03/20/2023, 5:33 PMprintln
calls that reference variables in which case the problem disappears while that statement is present.
The pasted test class will print the following when ran (and never complete):
Registering
Registered
Emitting
Emitting here
Subscribers
0
Done
Suspending
Note that is says there are zero subscribers and finished emitting even though it was registered.
However, when uncommenting lines 59 or 63, it still says there are zero subscribers, but the object is emitted to my registered collector and the program finishes.
I am relatively new to Flows and have avoided them mostly because of these kinds of things, but I would love to make them work since they are exactly what I need.
I feel like I must be doing something wrong.
I appreciate any help!loloof64
03/21/2023, 9:11 PMLuke
03/22/2023, 2:44 PMdelay
is accessible and does check the cancellation status so there must be a way right?Daniel
03/23/2023, 6:09 PMDaniel
03/23/2023, 6:18 PMmartypitt
03/24/2023, 8:43 AM1.7.0-Beta
, and it appears that kotlinx.coroutines.future.future
has been moved - does anyone know what it's replacement is?Johann Pardanaud
03/24/2023, 10:31 AMrouting {
get("/some-route") {
MDC.put("foo", "bar") // Will it leak in successive requests for the same route?
println(MDC.getCopyOfContextMap())
delay(1)
println(MDC.getCopyOfContextMap()) // Should I use `withContext(MDCContext()) {}` here?
}
}
Should I do something like this?
routing {
get("/some-route") {
// Use MDCContext before modifying the MDC to ensure the data is restored
withContext(MDCContext()) {
MDC.put("foo", "bar")
println(MDC.getCopyOfContextMap())
// Use MDCContext before suspending the coroutine to ensure
// the data is still available when resuming
withContext(MDCContext()) {
delay(1)
println(MDC.getCopyOfContextMap())
}
}
}
}
As you can see, I’m a bit lost and I’m not sure when I need to use MDCContext
😬Jaro
03/24/2023, 3:54 PMCompletableFuture
code in Java to Coroutines
in Kotlin, the interface that my Kotlin class implements has functions that are returning CompletableFuture
Here is example of functions that I want to rewrite
private final Map<String, FooWrapper> fooRequests = new ConcurrentHashMap<>();
public CompletableFuture<FooResponse> retrieveFoo(FooRequest request) {
return completedFuture(...)
.thenAccept(client::callFoo)
.thenCompose(ignore -> storeFooRequest(request))
.whenComplete((response, error) -> log(request, error));
}
private CompletableFuture<FooResponse> storeFooRequest(FooRequest request) {
var fooWrapper = new FooWrapper(request, new CompletableFuture<>());
fooRequests.put(request.getId(), fooWrapper);
return fooWrapper.getResponseFuture();
}
eventually there will be call to other functions that will call complete
on a CompletableFuture
stored in fooRequests
and allowing completion of retrieveFoo
here is my Kotlin code
private val fooRequests: ConcurrentHashMap<String, CompletableDeferred<FooResponse>> = ConcurrentHashMap()
override fun retrieveFoo(request: FooRequest): CompletableFuture<FooResponse> {
return GlobalScope.future {
retrieveQuoteAsync(request)
}
}
private suspend fun retrieveFooAsync(request: FooRequest): Deferred<FooResponse> {
return coroutineScope {
storeFooRequest(request)//.await()
}
}
private suspend fun storeFooRequest(request: FooRequest): Deferred<FooResponse> {
val deferred: CompletableDeferred<FooResponse> = CompletableDeferred()
fooRequests[request.id] = deferred
return deferred
}
I'm trying to replace CompletableFuture
with CompletableDeferred
but I do not know how to get the value without calling await()
, I do not want it to block
Any suggestion how to make it work in similar way to Java?Seth Madison
03/24/2023, 9:41 PMtransform
. I have a flow along the lines of`sharedFlow -> transformWhile -> map` , and I see the map
run even when the downstream collector has completed. Is this expected?
Example in the thread.Ismaïl
03/25/2023, 1:08 PMIsmaïl
03/25/2023, 4:06 PMArjan van Wieringen
03/26/2023, 6:59 AMIsmaïl
03/26/2023, 5:27 PMsuspendCoroutine
works, I tried to implement an example, here is the GitHub Gist link
Does this code make sense ? it works but I was wondering if it can be improved somehow
Thanks in advancejean
03/27/2023, 6:44 AMChannel
to be able to communicate data between coroutines?sanggggg
03/28/2023, 3:18 AMYoussef Shoaib [MOD]
03/28/2023, 3:57 PMThread
that's already running (for legacy reasons, it needs to be a Thread
for now). Inside a suspend
function, how can I call thread.join()
in a "better" manner? As in, so that the coroutine suspends until the thread finishes.Youssef Shoaib [MOD]
03/28/2023, 3:57 PMThread
that's already running (for legacy reasons, it needs to be a Thread
for now). Inside a suspend
function, how can I call thread.join()
in a "better" manner? As in, so that the coroutine suspends until the thread finishes.CLOVIS
03/28/2023, 4:08 PMwithContext(<http://Dispatchers.IO|Dispatchers.IO>) {
thread.join()
}
mkrussel
03/28/2023, 4:13 PMYoussef Shoaib [MOD]
03/28/2023, 4:15 PMthread.isAlive
is false, so wouldn't I be able to use that as a condition to wait for? I do have control over the thread code, but I'm trying to not be too invasivecoroutineScope { launch { while (thread.isAlive) delay(10) } }
simon.vergauwen
03/28/2023, 4:17 PMwithContext
.
A non-blocking option would be to somehow pass a CompletableDeferred
as the task running in the Thread
and await that.
I would personally prefer join
in favor of looping, you can potentially also use newSingleThreadContext instead of <http://Dispatchers.IO|Dispatchers.IO>
but be sure to close it.CLOVIS
03/28/2023, 4:19 PMrunInterruptible(<http://Dispatchers.IO|Dispatchers.IO>)
looks more appropriate. It's still blocking a thread.Youssef Shoaib [MOD]
03/28/2023, 4:23 PMCompletableDeferred
and completing it at the end of the thread's code, then awaiting it instead of calling join
CLOVIS
03/28/2023, 4:24 PMsimon.vergauwen
03/28/2023, 4:25 PMtry { } finally { }
block so it gets called regardless of exceptions 😉Youssef Shoaib [MOD]
03/28/2023, 4:28 PMCLOVIS
03/28/2023, 4:30 PM