Question on ktor + exposed + coroutines
# ktor
w
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:
Copy code
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()
Copy code
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
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
maybe:
Copy code
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
@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
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
okay - what's the proper way to do that?
if I markup the above
Copy code
block: () -> T): T =
to
Copy code
block: suspend () -> T): T =
then the block() inside the transaction{} now requires a coroutine body
s
did you try
runBlocking
?