feat: expose transaction failure stages and conservative outcomes
This commit is contained in:
55
examples/transactions/main.go
Normal file
55
examples/transactions/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Run with go run ./examples/transactions. Uses a deterministic demonstration
|
||||
// driver, no external database and no actual uploaded files.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.yuntuo.hk/k2safe/go-omni/database"
|
||||
)
|
||||
|
||||
func main() {
|
||||
failure := errors.New("demonstration failure")
|
||||
for _, name := range []string{"success", "beginFailure", "workFailure", "rollbackFailure", "commitRejected", "commitAcknowledgementLost"} {
|
||||
driver := &demoConnector{}
|
||||
var workErr error
|
||||
switch name {
|
||||
case "beginFailure":
|
||||
driver.beginErr = failure
|
||||
case "workFailure":
|
||||
workErr = failure
|
||||
case "rollbackFailure":
|
||||
workErr, driver.rollbackErr = failure, failure
|
||||
case "commitRejected":
|
||||
driver.commitErr = failure
|
||||
case "commitAcknowledgementLost":
|
||||
driver.commitErr, driver.persistBeforeError = failure, true
|
||||
}
|
||||
pool := &database.DB{DB: sql.OpenDB(driver)}
|
||||
err := pool.InTx(context.Background(), nil, func(tx *sql.Tx) error {
|
||||
if _, err := tx.ExecContext(context.Background(), "INSERT demonstration record"); err != nil {
|
||||
return err
|
||||
}
|
||||
return workErr
|
||||
})
|
||||
_ = pool.Close()
|
||||
if err == nil {
|
||||
fmt.Printf("%s: committed, stored=%t\n", name, driver.stored.Load())
|
||||
continue
|
||||
}
|
||||
var txErr *database.TxError
|
||||
if !errors.As(err, &txErr) || !errors.Is(err, failure) {
|
||||
panic("transaction phase or original cause lost")
|
||||
}
|
||||
// A project decides whether cleanup is appropriate for its own operation.
|
||||
// Unknown outcomes must not be treated as evidence that no record exists.
|
||||
cleanup := txErr.Outcome == database.TxOutcomeNotStarted || txErr.Outcome == database.TxOutcomeRolledBack
|
||||
if cleanup && driver.stored.Load() {
|
||||
panic("unsafe cleanup decision")
|
||||
}
|
||||
fmt.Printf("%s: stage=%s outcome=%s stored=%t cleanup=%t\n", name, txErr.Stage, txErr.Outcome, driver.stored.Load(), cleanup)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user