eclipse-vertx / eclipse-vertx/vertx-sql-client
Support rollback to savepoint after failure
- Dominant language
- Java
- Stars
- 912
- Forks
- 212
- Avg merge
- 17h 30m
- Merged PRs (30d)
- 3
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
```kotlin
@OptIn(DelicateCoroutinesApi::class)
fun launchCoroutineOnEventLoopAsVertxFuture(block: suspend () -> T) : Future {
val vertx = Vertx.currentContext()
val promise = Promise.promise()
GlobalScope.launch(vertx.dispatcher()) {
try {
promise.complete(block())
} catch (ex: Exception) {
promise.fail(ex)
}
}
return promise.future()
}
```
```kotlin
suspend fun withSavepoint(sqlConnection: SqlConnection, block: suspend () -> OkOrError): OkOrError {
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()
}
}
```
```kotlin
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`.
```sql
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()`.
Contributor guide
Assessment
This issue has not been assessed yet.