KMP-NativeCoroutines icon indicating copy to clipboard operation
KMP-NativeCoroutines copied to clipboard

Improve async implementation

Open rickclephas opened this issue 2 years ago • 4 comments

  • Throw CancellationErrors instead of KotlinCancellationExceptions
  • Apply back pressure to the Flow collection

Breaking changes

  • asyncFunction(for:), asyncResult(for:) and asyncSequence(for:) throw a CancellationError instead of a KotlinCancellationException
  • asyncStream(for:) has been renamed to asyncSequence(for:) and now returns an AsyncSequence
  • the signatures of NativeSuspend and NativeFlow have changed

rickclephas avatar Mar 05 '22 15:03 rickclephas

Hey, I am curios how did you solve Flow back pressure from Swift. I tried the same thing, with an internal CoroutineScope and Jobs, but it did not work with StateFlows. After reading https://github.com/JetBrains/kotlin/blob/master/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutines-codegen.md, I tried using Continuations and at least for my use cases, it works like a charm. Maybe you want to take a look: https://github.com/hfhbd/testing-coroutines/blob/a0ea3690d487d206f9c50a9d1b6c33fd007f7d9f/src/commonMain/kotlin/app/softwork/testingcoroutines/Flows.kt#L43

hfhbd avatar Apr 05 '22 22:04 hfhbd

I solved this by suspending the "onItem" call inside the collect. The onItem callback now contains a completion handler which the Swift code must invoke once it's done consuming the item. https://github.com/rickclephas/KMP-NativeCoroutines/blob/2fe54869bbf8df6f00608403ac092e392ebebb6d/kmp-nativecoroutines-core/src/nativeCoroutinesMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt#L37-L41

This provides back pressure in the sense that the Swift code won't be buffering the items. Depending on the Flow this means that values either aren't generated or they are dropped (e.g. with a StateFlow).

What issues were you having with a StateFlow?

rickclephas avatar Apr 06 '22 06:04 rickclephas

Sorry for the late answer. I experiment with my simple implementation and my issue with StateFlow is wrong. It works as expected. I just have a problem with updating the state flow value from SwiftUI State property but because SwiftUI has its own state, you won't notice this problem in the ui but only when collecting the not updated state flows, which does not have the new input from the ui and does not send a new state (as expected...)

So there are absolut no issues with state flow collecting!

hfhbd avatar Apr 14 '22 09:04 hfhbd

JFYI: Maybe you/other have the same problem. I created the view model, which holds the StateFlow multiple times in my SwiftUI, because I wasn't aware of its handling, which results into wrong state flow values. This answer was the key: https://stackoverflow.com/a/71010187

hfhbd avatar Apr 19 '22 17:04 hfhbd