eclipse-vertx / eclipse-vertx/vertx-sql-client

Support rollback to savepoint after failure

Open
#1,369 5 comments 0 reactions 0 assignees View on GitHub
enhancement help wanted module:pg
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.