Description
Questions
I have encountered some strange transaction behaviour. If I execute a query after the transaction starts, create a checkpoint, then this query terminates with an exception (in my case an index constraint error). Then I rollback the checkpoint, and after that when commit transaction the system hangs. At the same time rollback works. In Debug I saw that there is a flag failed in the transaction object. Is this how it should be or am I doing something wrong?
Version
4.4.6
Context
Language
Kotlin
Packages
- io.vertx:vertx-core
- io.vertx:vertx-lang-kotlin-coroutines
- io.vertx:vertx-lang-kotlin
- io.vertx:vertx-pg-client
Location
Vertx Verticle
Code
@OptIn(DelicateCoroutinesApi::class)
fun <T> launchCoroutineOnEventLoopAsVertxFuture(block: suspend () -> T) : Future<T> {
val vertx = Vertx.currentContext()
val promise = Promise.promise<T>()
GlobalScope.launch(vertx.dispatcher()) {
try {
promise.complete(block())
} catch (ex: Exception) {
promise.fail(ex)
}
}
return promise.future()
}
suspend fun <T, Error> withSavepoint(sqlConnection: SqlConnection, block: suspend () -> OkOrError<T, Error>): OkOrError<T, Error> {
sqlConnection
.query("SAVEPOINT AsyncSqlConnectionPgSavepointWithErrorHandling")
.execute()
.await()
try {
val result = block()
if(result.isError) {
sqlConnection
.query("ROLLBACK TO SAVEPOINT AsyncSqlConnectionPgSavepointWithErrorHandling")
.execute()
.await()
}
return result
}
catch (e: PgException) {
sqlConnection
.query("ROLLBACK TO SAVEPOINT AsyncSqlConnectionPgSavepointWithErrorHandling")
.execute()
.await()
throw e
}
finally {
sqlConnection
.query("RELEASE SAVEPOINT AsyncSqlConnectionPgSavepointWithErrorHandling")
.execute()
.await()
}
}
pgPool.withConnection { sqlConnection ->
launchCoroutineOnEventLoopAsVertxFuture {
val transaction = sqlConnection.begin().await()
try {
val result =
try {
withSavepoint(sqlConnection) {
functionWithDatabaseException()
}
} catch(e: PgException) {
....
Ok(...)
}
if(result.isOk) {
transaction.commit().await() // here problem
} else {
transaction.rollback().await()
}
return result
} catch (e: Exception) {
transaction.rollback().await()
throw e
}
}
}.await()
After stuck on the line transaction.commit().await()
. With a query in PostgreSQL, I can see that the last query from the application to the database is ROLLBACK
.
SELECT *
FROM pg_stat_activity
WHERE application_name = 'vertx-pg-client'
PS Everything works fine if I manually make BEGIN/COMMIT requests with SqlConnection instead sqlConnection.begin()
/transaction.commit()
.