https://kotlinlang.org logo
Title
w

waltermcq

04/19/2020, 1:34 AM
Question on ktor + exposed + coroutines
I'm trying to insert a new user into my database using the exposed DSL, with transactions that are wrapped with coroutines e.g. the dqQuery {} method frequently found for this purpose
Here's basically what the insert function is:
override suspend fun newUser(id: String, name: String): UserAgg {
        return dbQuery {
            val userRow = UserTable.insert {
                it[this.id] = id
                it[this.name] = name
            }.resultedValues!!.first()

          getUserById(UserId(userRow[UserTable.id]))!!
        }
    }
Heres's dbQuery()
suspend fun <T> dbQuery(
    block: () -> T): T =
    withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
        transaction { block() }
    }
The issue is in the insert newUser function, when I call getUserById to get the new id (specifically, a uuid) from the database, intellij tells me that getUserById must be called within a coroutine body
I can't wrap it in a dbQuery() call, I get the same issue (as its apparently not a coroutine body)
what is the best way to call getUserById() given the need for a coroutine body?
t

tjohnn

04/19/2020, 6:50 AM
You have to call it in a ktor route{}.
Or if you want to call it from another function , maybe repository function, mark that function as suspending and call that function from inside a route{}
m

Magno Junior

04/19/2020, 7:40 AM
maybe:
suspend fun <T> dbQuery(
    block: suspend () -> T): T =
    withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
        transaction { block() }
    }
but I am not sure all these functions has to be suspend 🤔
w

waltermcq

04/19/2020, 12:30 PM
@tjohnn Can you clarify why I would be using a ktor route specifically for a DB call? I'm not understanding the connection between the ktor route and a coroutine...
@Magno Junior my understanding is that this is a common pattern to use coroutines when using exposed - they need to be suspending functions
t

tjohnn

04/19/2020, 12:48 PM
I think you got it wrong. dbQuery is suspending so it has to be called in another suspending function or within a coroutine scope. Ktor routes are in a coroutine scope that helps them to run tasks concurrently.
And oh I see you need to mark block() as suspending
☝️ 1
w

waltermcq

04/19/2020, 3:24 PM
okay - what's the proper way to do that?
if I markup the above
block: () -> T): T =
to
block: suspend () -> T): T =
then the block() inside the transaction{} now requires a coroutine body
s

Sourabh Rawat

04/22/2020, 6:34 AM
did you try
runBlocking
?