https://kotlinlang.org logo
Docs
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
coroutines
  • c

    christophsturm

    04/29/2020, 3:55 PM
    is there some example code for
    org.jetbrains.kotlinx:kotlinx-coroutines-reactive
    ? or even coroutines code that uses the r2dbc spi api?
    m
    • 2
    • 2
  • e

    elizarov

    04/29/2020, 5:36 PM
    📣 The design for upcoming
    StateFlow
    is documented in a new issue. Your feedback is welcome: https://github.com/Kotlin/kotlinx.coroutines/issues/1973
    ❤️ 1
    🎉 18
    🙏🏼 20
    💯 11
    👍 11
    👍🏼 3
    c
    d
    +7
    • 10
    • 13
  • i

    igor.wojda

    04/29/2020, 7:24 PM
    I have implemented a sleep sort algorithm using coroutines (don’t ask me why🤣) and now Vasya asks me if this implementation is thread-safe? And now I really wonder if it is thread-save to access
    sortedList
    like this? https://twitter.com/igorwojda/status/1255416485293502465
    a
    o
    +3
    • 6
    • 17
  • s

    svenjacobs

    04/30/2020, 9:49 AM
    Hey everybody, I'm implementing the Model-View-Intent pattern using coroutines and
    Flow
    . In my concept everything is a
    Flow
    , beginning with UI events. Let's say I have a view interface like this
    interface MyView {
    
        val buttonClicks: Flow<Action.ButtonClick>
    
        val button2Clicks: Flow<Action.Button2Click>
    
        fun setMessage(message: String)
    }
    I have actions
    sealed class Action {
    
        object ButtonClick : Action()
    
        object Button2Click : Action()
    }
    and a state that holds UI state
    data class State(
        val message: String
    )
    The idea is that a
    Flow<Action
    is transformed into a
    Flow<State>
    based on the current Action and that state changes are then delegated to the view. The - for this example extremly simplified - flow process would look like this
    val flow =
        merge(
            view.buttonClicks,
            view.button2Clicks
        ).flatMapMerge { action ->
            when (action) {
                is Action.ButtonClick -> flow {
                    // Simulate Flow that constantly produces values
    
                    var increment = 0
    
                    while (true) {
                        delay(1000)
                        increment++
    
                        emit(State(message = "Message $increment"))
                    }
                }
    
                is Action.Button2Click -> flowOf(State(message = "Hello world"))
            }
        }.onEach { state ->
            view.setMessage(state.message)
        }
    
    // Flow is collected when view is ready
    GlobalScope.launch {
        flow.collect()
    }
    However I have a problem with this concept. Let's say
    Action.ButtonClick
    should subscribe to some API that constantly produces values which update the UI (simulated in the example above). Unfortunately when multiple button clicks occur, multiple (inner) flows are running in parallel, each unnecessarily updating the UI. Do you have an idea how I can solve this problem, somehow stopping the previous (inner) flow? Thanks for your help!
    u
    w
    +3
    • 6
    • 28
  • k

    kzotin

    04/30/2020, 12:18 PM
    Hi friends, Have posted an issue on some Android 5 devices, which blocks us from using not only
    coroutines
    , but also
    android-ktx
    libs https://github.com/Kotlin/kotlinx.coroutines/issues/1979 Wondering, if any of you have heard about it?
    w
    • 2
    • 2
  • p

    Paul Martin

    04/30/2020, 7:17 PM
    hi everyone. total n00b question here. all help gratefully received. 🙏 i've got this code, which is based on one of the examples from the kotlinlang.org docs:
    fun main() = runBlocking {
        launch {
            println("block 1: start")
            delay(2000)
            println("block 1: end")
        }
        launch {
            println("block 2: start")
            delay(1000)
            println("block 2: end")
        }
    
        Unit
    }
    as expected, the output is:
    block 1: start
    block 2: start
    block 2: end
    block 1: end
    so the two
    launch
    blocks are running concurrently. next i try and replace the
    delay
    calls with some functions of my own:
    fun functionThatTakesALongTime() {
        for (j in 1..5) {
            for (i in 1..1_000_000_000) {
                i * i * i
            }
        }
    }
    
    fun functionThatTakesAShortTime() {
        1 + 1
    }
    
    fun main() = runBlocking {
        launch {
            println("block 1: start")
            functionThatTakesALongTime()
            println("block 1: end")
        }
        launch {
            println("block 2: start")
            functionThatTakesAShortTime()
            println("block 2: end")
        }
    
        Unit
    }
    this time the output is this:
    block 1: start
    block 1: end
    block 2: start
    block 2: end
    in other words it ran the whole of the first
    launch
    block before starting on the second one. want i want is for them to run concurrently as in the first example. i guess there's something fundamental that i'm missing! what is it about
    delay
    which enables the
    launch
    blocks to run concurrently? thanks!
    o
    u
    s
    • 4
    • 16
  • c

    Colton Idle

    04/30/2020, 8:29 PM
    Trying to sanity check converting some coroutines retrofit code to something that runs in parallel but stills waits for both calls to be complete. This is my sequential coroutine code
    viewModelScope.launch {
    
    val nameResponse = retrofitService.getName()
    val phoneResponse = retrofitService.getPhone()
    print("${nameResponse.isSuccessful.toString()} ${phoneResponse.isSuccessful.toString()}")
    
    }
    Is making it parallel as easy as doing this?
    viewModelScope.launch {
    
    val nameResponse = async { retrofitService.getName() }
    val phoneResponse = async { retrofitService.getPhone() }
    print("${nameResponse.await().isSuccessful.toString()} ${phoneResponse.await().isSuccessful.toString()}")
    
    }
    If that is all I need. Am I missing something anything from your point of view. Besides error handling (which is a whole other topic)? Any other ways to do this?
    o
    e
    • 3
    • 27
  • u

    ubu

    05/01/2020, 9:30 AM
    Hi guys. There this problem with
    viewModelScope
    from Android Architecture Components’
    ViewModel
    that i’ve been thinking over lately. I run a lot of background operations inside some
    ViewModel
    , because I use its
    ViewModelScope
    . These operations are
    use-cases
    injected into constructor of this
    ViewModel
    . For a better separation of concerns I would like to extract some of these operations in some other class that I would then inject in this
    ViewModel
    , but in order to run these operations, I need that
    ViewModelScope
    . Is there a way to provide it to injected components without passing the scope every time in some function signature?
    e
    u
    • 3
    • 28
  • l

    Lukas Lechner

    05/01/2020, 11:13 AM
    Hi! I wrote an article about Kotlin Coroutines VS Callbacks VS RxJava => https://www.lukaslechner.com/comparing-kotlin-coroutines-with-callbacks-and-rxjava/ Maybe someone can learn something!
    👍 1
    ❤️ 1
    r
    • 2
    • 1
  • s

    Sean Keane

    05/01/2020, 4:11 PM
    Hi All, Im writing some test code and I seem to be having issues with Coroutines. I want to make a request to
    Login
    but it calls the function and kicks it off on a new Coroutine. This causes the test to continue and hit the verify BEFORE the request is made. Im working in Multiplatform and using Coroutine testing tools in Android as a target for the tests. This is my test:
    class KAuthenticationServiceTest {
    
        var loginRequest = service.auth.login.build("<mailto:fakeEmail@mail.com|fakeEmail@mail.com>", "fakePassword")
    
        var mockStorage = MockStorage()
        var mockCredentialsManager = MockCredentialsManager()
        var mockNetworkManager = MockNetworkManager()
        lateinit var authService: AuthService
    
        @BeforeTest
        fun setup() {
            authService = KAuthenticationService(
                storage = mockStorage,
                credentialsManager = mockCredentialsManager,
                networkManager = mockNetworkManager
            )
        }
    
        /**
         * Given:   A user requests to login
         * When:    The call is made to the login interactor
         * Then:    The request is executed successfully
         */
        @Test
        fun callIsMadeToLoginInteractorToExecuteRequest() = runTest {
            authService.login(loginRequest, {}, {})
            assertTrue {
                mockNetworkManager.requestValue == loginRequest
            }
        }
    }
    The run test function in Android is the following:
    val mainThreadSurrogate = newSingleThreadContext("UI thread")
    
    actual fun <T> runTest(block: suspend () -> T) {
        Dispatchers.setMain(mainThreadSurrogate)
        runBlockingTest {  block() }
    }
    Im a bit lost as to how I can get the runBlocking to run the authService.login on the same thread so it blocks until executed and then continues to the assert? Has anyone got any suggestions?
    l
    • 2
    • 11
  • s

    SrSouza

    05/01/2020, 9:50 PM
    Hi folks, I'm using
    newSingleThreadExecutor
    as a Dispatcher but I have a problem with it, when I use
    delay(x)
    , other functions that use the same dispatcher does not execute until the delay finish. Why this is happening if
    delay
    does not block the Thread.
    o
    e
    e
    • 4
    • 8
  • m

    Mark

    05/03/2020, 9:53 AM
    Are there any best practices for using/calling coroutines from an Android ContentProvider? I’m thinking in terms of CoroutineScopes and contentprovider lifecycle, etc.
    l
    w
    • 3
    • 5
  • k

    kev1n11

    05/03/2020, 9:22 PM
    Hi all, Looking for some testing suggestion with coroutines, in particular
    CoroutineScope
    . We are POCing the following into our Spring Boot server • as the server starts up, use
    SqsAsyncClient
    to read in messages, • these are sent into a buffered
    Channel
    , • also start a pool of worker coroutines to process these messages, the processing functions are all
    suspend fun
    The above are encapsulated in a
    SQSConsumer
    which implements
    CoroutineScope
    , and we cant seem to figure out a clean way to test that. The code looks something like
    class SQSConsumer(
        val sqs: SqsAsyncClient,
        val props: SQSProperties
    ) : CoroutineScope {
        private val supervisorJob = SupervisorJob()
        override val coroutineContext: CoroutineContext
            get() = <http://Dispatchers.IO|Dispatchers.IO> + supervisorJob
    
        // called from another class using @PostConstruct
        fun start() = launch {
            val launchQueueReceiveChannel = launchReceiver(
                props.queueUrl,
                props.waitTimeSeconds,
                props.maxNumberOfMessages
            )
            repeat(props.workers) {
                launchWorker(launchQueueReceiveChannel, props.queueUrl, props.timeout)
            }
        }
    }
    What are the common patterns for overriding
    Dispatcher
    in tests? If you have a better suggest to encapsulate the above (Spring Boot or not), we’d love to hear too.
    t
    d
    • 3
    • 2
  • v

    Viktor Vostrikov

    05/05/2020, 5:57 AM
    Hello, can I pass kotlin coroutine scope as function argument? I have created question about it: https://stackoverflow.com/questions/61606630/should-you-pass-coroutinescope-as-function-argument
    o
    • 2
    • 33
  • s

    Slackbot

    05/05/2020, 9:09 AM
    This message was deleted.
    m
    • 2
    • 1
  • c

    christophsturm

    05/05/2020, 2:32 PM
    why does idea mark StringBuffer.append(Charsequence) as a blocking call?
    o
    • 2
    • 4
  • s

    Soundlicious

    05/05/2020, 3:04 PM
    Hello, I'm trying to integrate a form validation on my app. Usually I was doing that with RxJava using PublishSubject and Compose to combine all the observed editText and check once the user click on a button. How could you do the same thing using coroutines?
    c
    • 2
    • 2
  • c

    Chilli

    05/05/2020, 4:32 PM
    Linking
    kotlinx-coroutines-core-native
    takes suspiciously long time
    z
    • 2
    • 1
  • z

    zak.taccardi

    05/05/2020, 4:51 PM
    I’m wrapping an
    actor
    of one type with another, but struggling with the
    SendChannel#selectClause
    . How can I implement the following?
    private val _onSend: SelectClause2<StateActorIntention<S, I>, SendChannel<StateActorIntention<S, I>>> = actor.onSend
     // how do I forward onSend to `_onSend` without using `@InternalCoroutinesApi`?
     override val onSend: SelectClause2<I, SendChannel<I>> get() = TODO("??")
    • 1
    • 1
  • a

    ar-g

    05/05/2020, 4:55 PM
    Hi everyone, I have a code with a mix of recursion and coroutines, I'm wondering how valid and idiomatic it is: • each step when the board is changed I want to emit it with
    flow
    and show on UI • when the
    coroutine
    is canceled
    partiallySolve
    function expected to stop working
    typealias OnSudokuBoardChanged = suspend (board: List<List<Int>>) -> Unit
    
    class SudokuSolver {
    
        fun solve(board: List<List<Int>>) = flow {
            partiallySolve(0, 0, board) {
                emit(it)
            }
        }
    
        private suspend fun partiallySolve(
            curI: Int,
            curJ: Int,
            board: MutableList<MutableList<Int>>,
            callback: OnSudokuBoardChanged
        ): Boolean {
            if (curI > board.lastIndex) {
                return true
            }
    
            val curNum = board[curI][curJ]
    
            val nextI = if (curJ == board.lastIndex) curI + 1 else curI
            val nextJ = if (curJ == board.lastIndex) 0 else curJ + 1
    
            if (curNum != 0) {
                return partiallySolve(nextI, nextJ, board, callback)
            }
    
            if (curNum == 0) {
                for (guess in 1..9) {
                    if (validate(guess, curI, curJ, board)) {
    
                        board[curI][curJ] = guess
    
                        callback.invoke(board)
    
                        if (partiallySolve(nextI, nextJ, board, callback)) {
                            return true
                        }
                    }
                }
            }
    
            board[curI][curJ] = 0
    
            return false
        }
    z
    u
    • 3
    • 2
  • m

    Mark

    05/06/2020, 2:27 AM
    Is there some way to hook into each suspend/yield point so a check can be performed to potentially cancel the current Job? My use case is implementing an Android ContentProvider’s blocking query() method, which takes a CancellationSignal as one (amongst others) argument. At the moment, I have to pass the CancellationSignal down through the code and perform checks at appropriate points, but it would be better if the check could be done via some kind of onSuspend callback.
    z
    • 2
    • 13
  • l

    Luis Munoz

    05/06/2020, 2:53 AM
    Is it better to write code as in methodA, methodB, or methodC, why and what is the difference if any?
    Untitled
    d
    s
    z
    • 4
    • 4
  • a

    ar-g

    05/06/2020, 1:37 PM
    Hey everyone, I want to make the second version of the code run in parallel do you have any ideas, how to achieve it?
    fun getAll(): Flow<...> { //works in parallel, doesn't respect structural concurrency
        GlobalScope.launch {
            //start request...
        }
        return db.flow()//starts emitting immediately...
    }
    
    suspend fun getAll(): Flow<...> { //works sequentially
        withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
            launch {
                //start request...
            }
        }
        return db.flow()//start emitting after request is finished...
    }
    d
    a
    • 3
    • 9
  • s

    SrSouza

    05/06/2020, 4:24 PM
    HI folks, I have a Channel and I want to filter some value when receive it and await the first time. I try to use
    receiveAsFlow().filter {}.collect()
    but I think that this is not the right aproach be cause do not work. How I can await the first appearance of a value in a Channel?
    j
    • 2
    • 5
  • j

    Joffrey

    05/06/2020, 4:51 PM
    Hi guys, how can I add debug information to a timeout exception? I’m writing tests with a global timeout, and I would like to know where the execution got stuck when the timeout happens. I have a couple places in my testing utilities which are the usual bad boys, so I tried the following:
    try {
       doTheThingThatUsuallyGetsStuck()
    } catch(e: TimeoutCancellationException) {
       fail("some debug information about why the test may have timed out")
    }
    The problem with this is that sometimes the code under test uses timeouts as well, so this catch block may actually fail the test even in some valid timeout situations. Is there a way for me to transparently add information about the timeout somehow? If I rethrow a
    CancellationException
    with a custom error message, then how can I catch it upstream and access the message?
    t
    • 2
    • 2
  • j

    Jeff Johnson

    05/06/2020, 5:43 PM
    Hi All, having some trouble with cancelling coroutines in an Android app and wondering if you all could help: I have a class that launches coroutines and allows them to be cancelled when the Activity/Fragment they are called from is destroyed. However it is not working like I expect. When I back out of the fragment while the operation is running, the coroutine cancel does not take, and I get an NPE when trying to access a 
    View
     that does not exist anymore.
    open class CoroutineLauncher : CoroutineScope {
    
        private val dispatcher: CoroutineDispatcher = Dispatchers.Main
        private val supervisorJob = SupervisorJob()
        override val coroutineContext: CoroutineContext
            get() = dispatcher + supervisorJob
    
        fun launch(action: suspend CoroutineScope.() -> Unit) = launch(block = action)
    
        fun cancelCoroutines() {
            supervisorJob.cancelChildren() //coroutineContext.cancelChildren() has same results
        }
    }
    here is the usage
    class MyFragment : Fragment {
    
      val launcher = CoroutineLauncher()
    
      fun onSomeEvent() {
    
        launcher.launch {
    
          val result = someSuspendFunction() // made suspend function by using withContext(<http://Dispatchers.IO|Dispatchers.IO>)
    
          if (!isActive) return
    
          // CAUSES CRASH
          myTextView.text = result.userText
    
        }
    
      }
    
      override fun onDestroyView() {
        super.onDestroyView()
        launcher.cancelCoroutines()
      }
    
    }
    I added log lines to ensure 
    onDestroyView
     and 
    cancelCoroutines
     are both being called before the crash. It is my understanding that
    withContext
    is cancellable and thus I shouldn’t even need to check for
    isActive
    . I feel like I’m missing something obvious, but I can’t figure out what it is
    j
    • 2
    • 5
  • z

    zak.taccardi

    05/06/2020, 5:55 PM
    Is this always thread safe because the code here is always executed in the same coroutine? Meaning, we don’t need to use an
    AtomicRef
    on
    numberOfTimesUserHasChanged
    because it’s guaranteed to be executed in the same coroutine? My concern is that
    currentUserIdFlow
    could switch threads/coroutines internally, but I think that would not be able to affect the coroutine in which
    numberOfTimesUserHasChanged
    is read and written from?
    Untitled
    f
    z
    +2
    • 5
    • 56
  • e

    Erik

    05/07/2020, 10:31 AM
    On Android with AndroidX Work, there's the
    CoroutineWorker
    that does work on a coroutine. This work can be cancelled by the system, it then throws a
    CancellationException
    . In my apps I want to log any exceptions that are thrown by the crucial part of my work, e.g.:
    runCatching { crucialWork() }.onFailure { log(it) }
    . However, I see a lot of
    JobCancellationException
    instances being logged with message
    "Job was cancelled"
    . I don't want to log regular cancellations without an exceptional cause. So, if I read the documentation of
    Job
    (https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html), am I right to conclude that I'm only interested in exceptions that are not of type
    CancellationException
    , or if I catch a
    CancellationException
    , then I'm only interested if its
    cause
    is not a
    CancellationException
    ? In other words: I'm interested in 'failed' coroutines, not in 'normally cancelled' coroutines. So, what exceptions do I log, what do I ignore?
    f
    z
    r
    • 4
    • 8
  • a

    ar-g

    05/07/2020, 1:03 PM
    Hey folks, I've got another question regarding exception handling with Flow. Current implementation throws
    Flow invariant is violated: Emission from another coroutine detected...
    It makes sense, the question is how to not violate it and ensure that: • Request and observing DB happens in parallel • Exception wrapped and propagated to UI • UI continues to observe DB
    fun getAll(): Flow<Wrap<...>> = flow { //request and observing db happens in parallel
        coroutineScope {
            launch(<http://Dispatchers.IO|Dispatchers.IO>) {
                try {
                    //start request...
                } catch (e){
                    emit(Wrap(e))//!!! this will throw IllegalStateException: Flow invariant is violated: Emission from another coroutine is detected.
                }
            }
            emitAll(db.flow()) //starts emitting immediately...
        }
    }
    d
    • 2
    • 2
  • c

    christophsturm

    05/07/2020, 5:52 PM
    whats the best way to convert this code to a suspend method instead of returning a future?
    fun createCaptureServer(port: Int): CompletableFuture<String> {
            val future = CompletableFuture<String>()
            val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
                future.complete(it.queryString)
            }.build()
            undertow.start()
            return future.thenApplyAsync {
                undertow.stop()
                it
            }
        }
    possibly using ktor instead of undertow.
    o
    l
    • 3
    • 20
Powered by Linen
Title
c

christophsturm

05/07/2020, 5:52 PM
whats the best way to convert this code to a suspend method instead of returning a future?
fun createCaptureServer(port: Int): CompletableFuture<String> {
        val future = CompletableFuture<String>()
        val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
            future.complete(it.queryString)
        }.build()
        undertow.start()
        return future.thenApplyAsync {
            undertow.stop()
            it
        }
    }
possibly using ktor instead of undertow.
o

octylFractal

05/07/2020, 5:55 PM
if you're using ktor, it basically just becomes a normal function -- ktor's http methods are all suspend
wait, nvm
misread what was happening here
realistically I think it would be mostly the same, except you'd use a
CompletableDeferred
instead of
Future
l

Luis Munoz

05/07/2020, 5:58 PM
because it is a callbac I think this applies https://stackoverflow.com/questions/48552925/existing-3-function-callback-to-kotlin-coroutines/48562175#48562175
o

octylFractal

05/07/2020, 5:59 PM
yes, you could do it that way as well
though I would recommend
suspendCancellableCoroutine
c

christophsturm

05/07/2020, 6:03 PM
thanks guys!
and how do do the
thenApplyAsync
part? (stop the http server)
o

octylFractal

05/07/2020, 6:10 PM
use
try-finally
(assuming you go the
suspendCancellableCoroutine
route)
c

christophsturm

05/07/2020, 6:15 PM
why is
suspendCancellableCoroutine
better? when would it cancel?
o

octylFractal

05/07/2020, 6:16 PM
if you cancel the Job that the suspend function is a part of, then it properly cancels and throws an exception
otherwise it will just ignore cancellation
going to be honest, though, I don't see how to do this easily with
suspendCancellableCoroutine
-- I think that using the future model for actually retrieving the data is better
suspend fun createCaptureServer(port: Int): String {
  val deferred = CompleteableDeferred<String>()
  val server = <create server, with handler that completes the deferred>
  server.start()
  try {
    return deferred.await()
  } finally {
    server.close()
  }
}
is my take
c

christophsturm

05/07/2020, 6:20 PM
suspend fun createCaptureServer(port: Int): String {
        val result =  suspendCoroutine<String>{cont->
            val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
                cont.resume(it.queryString)
            }.build()
            undertow.start()
        }
        undertow.close()
        return result
    }
this is what i came up with, but it does not work that way because undertow is inside the callback, so i would have to make it nullable and a var. which is not so great
so your solution is probably better
i ended up without finally, but thats probably just a matter of taste:
val deferred = CompletableDeferred<String>()
        val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
            deferred.complete(it.queryString)
        }.build()
        undertow.start()

        val result = deferred.await()
        undertow.stop()
        return result
    }
thanks for your help!
o

octylFractal

05/07/2020, 6:26 PM
i'd be concerned about leaking the server in the case of an exception
but maybe you're okay with that
View count: 8