This is an automated email from the ASF dual-hosted git repository.
flypiggy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-seata-go-samples.git
The following commit(s) were added to refs/heads/main by this push:
new b55570b improve: refactor and resolve the integrate test error (#87)
b55570b is described below
commit b55570b1d4c234f4a3e9b57f44269fb2e2592f73
Author: TewGuo <[email protected]>
AuthorDate: Sat Jan 31 16:59:35 2026 +0800
improve: refactor and resolve the integrate test error (#87)
Co-authored-by: guotun <[email protected]>
---
integrate_test/at/insert_on_update/main.go | 132 +++++++++++++---------------
integrate_test/at/select_for_update/main.go | 129 ++++++++++++++++-----------
2 files changed, 137 insertions(+), 124 deletions(-)
diff --git a/integrate_test/at/insert_on_update/main.go
b/integrate_test/at/insert_on_update/main.go
index 2a326c8..8aada7b 100644
--- a/integrate_test/at/insert_on_update/main.go
+++ b/integrate_test/at/insert_on_update/main.go
@@ -21,121 +21,109 @@ import (
"context"
"database/sql"
"fmt"
- "log"
"time"
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/clause"
"seata.apache.org/seata-go/pkg/client"
sql2 "seata.apache.org/seata-go/pkg/datasource/sql"
"seata.apache.org/seata-go/pkg/tm"
)
-type OrderTblModel struct {
- Id int64 `gorm:"column:id" json:"id"`
- UserId string `gorm:"column:user_id" json:"user_id"`
- CommodityCode string `gorm:"commodity_code" json:"commodity_code"`
- Count int64 `gorm:"count" json:"count"`
- Money int64 `gorm:"money" json:"money"`
- Descs string `gorm:"descs" json:"descs"`
-}
+var db *sql.DB
func main() {
- initConfig()
+ client.InitPath("./conf/seatago.yml")
+ initDB()
+
+ ctx := context.Background()
- // test: insert on update
- err := tm.WithGlobalTx(context.Background(), &tm.GtxConfig{
+ // execute insert on update within global transaction
+ err := tm.WithGlobalTx(ctx, &tm.GtxConfig{
Name: "ATSampleLocalGlobalTx_InsertOnUpdate",
Timeout: time.Second * 30,
}, insertOnUpdateData)
-
if err != nil {
- log.Fatalf("failed to init transaction: %v", err)
- return
+ panic(fmt.Sprintf("transaction failed: %v", err))
}
- ctx := context.Background()
-
- // check
- if err := checkData(ctx); err != nil {
- fmt.Println(err)
- panic("failed")
+ // verify data was updated correctly
+ if err := verifyData(ctx); err != nil {
+ panic(fmt.Sprintf("data verification failed: %v", err))
}
- // wait clean undo log
+ // wait for undo log cleanup
time.Sleep(time.Second * 10)
- if checkUndoLogData(ctx) != nil {
- panic("failed")
+
+ // verify undo log is cleaned
+ if err := verifyUndoLogCleaned(ctx); err != nil {
+ panic(fmt.Sprintf("undo log verification failed: %v", err))
}
-}
-func initConfig() {
- client.InitPath("./conf/seatago.yml")
- initDB()
+ fmt.Println("insert_on_update test passed")
}
-var gormDB *gorm.DB
+// insertOnUpdateData tests INSERT ... ON DUPLICATE KEY UPDATE
+// The initial data has id=1, so this will trigger an UPDATE
+func insertOnUpdateData(ctx context.Context) error {
+ sql := "INSERT INTO order_tbl (id, user_id, commodity_code, count,
money, descs) " +
+ "VALUES (?, ?, ?, ?, ?, ?) " +
+ "ON DUPLICATE KEY UPDATE count = ?, descs = ?"
-func initDB() {
- sqlDB, err := sql.Open(sql2.SeataATMySQLDriver,
"root:12345678@tcp(127.0.0.1:3306)/seata_client?multiStatements=true&interpolateParams=true")
+ result, err := db.ExecContext(ctx, sql,
+ 1, "NO-100001", "C100000", 200, 10, "insert desc",
+ 200, "updated by insert_on_update")
if err != nil {
- panic("init service error")
+ return fmt.Errorf("insert on update failed: %w", err)
}
- gormDB, err = gorm.Open(mysql.New(mysql.Config{
- Conn: sqlDB,
- }), &gorm.Config{})
+ rows, err := result.RowsAffected()
if err != nil {
- panic("open DB error")
+ return fmt.Errorf("get rows affected failed: %w", err)
}
-}
+ fmt.Printf("insert on update affected rows: %d\n", rows)
-func getData() OrderTblModel {
- return OrderTblModel{
- Id: 1,
- UserId: "NO-100001",
- CommodityCode: "C100000",
- Count: 101,
- Money: 10,
- Descs: "insert desc",
- }
-}
-
-// insertOnUpdateData insert on update one data
-func insertOnUpdateData(ctx context.Context) error {
- data := getData()
-
- return
gormDB.WithContext(ctx).Table("order_tbl").Clauses(clause.OnConflict{
- Columns: []clause.Column{{Name: "id"}},
- DoUpdates: clause.Assignments(map[string]interface{}{
- "count": data.Count,
- }),
- }).Create(&data).Error
+ return nil
}
-func checkData(ctx context.Context) error {
- query := getData()
+func verifyData(ctx context.Context) error {
var count int64
- err :=
gormDB.WithContext(ctx).Table("order_tbl").Where(query).Count(&count).Error
+ var descs string
+
+ err := db.QueryRowContext(ctx,
+ "SELECT count, descs FROM order_tbl WHERE id = ?",
1).Scan(&count, &descs)
if err != nil {
- return err
+ return fmt.Errorf("query failed: %w", err)
+ }
+
+ if count != 200 {
+ return fmt.Errorf("expected count=200, got %d", count)
}
- fmt.Println("count:", count)
- if count != 1 {
- return fmt.Errorf("check data failed")
+ if descs != "updated by insert_on_update" {
+ return fmt.Errorf("expected descs='updated by
insert_on_update', got '%s'", descs)
}
+
+ fmt.Printf("data verified: count=%d, descs=%s\n", count, descs)
return nil
}
-func checkUndoLogData(ctx context.Context) error {
+func verifyUndoLogCleaned(ctx context.Context) error {
var count int64
- err := gormDB.WithContext(ctx).Table("undo_log").Count(&count).Error
+ err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM
undo_log").Scan(&count)
if err != nil {
- return err
+ return fmt.Errorf("query undo_log failed: %w", err)
}
+
if count != 0 {
- return fmt.Errorf("check undolog failed")
+ return fmt.Errorf("undo_log not cleaned, count=%d", count)
}
+
+ fmt.Println("undo_log cleaned successfully")
return nil
}
+
+func initDB() {
+ var err error
+ db, err = sql.Open(sql2.SeataATMySQLDriver,
"root:12345678@tcp(127.0.0.1:3306)/seata_client?multiStatements=true&interpolateParams=true")
+ if err != nil {
+ panic("init db error: " + err.Error())
+ }
+}
diff --git a/integrate_test/at/select_for_update/main.go
b/integrate_test/at/select_for_update/main.go
index 0ef2caa..3c0b096 100644
--- a/integrate_test/at/select_for_update/main.go
+++ b/integrate_test/at/select_for_update/main.go
@@ -21,94 +21,119 @@ import (
"context"
"database/sql"
"fmt"
- "log"
"time"
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/clause"
"seata.apache.org/seata-go/pkg/client"
sql2 "seata.apache.org/seata-go/pkg/datasource/sql"
"seata.apache.org/seata-go/pkg/tm"
)
-type OrderTblModel struct {
- Id int64 `gorm:"column:id" json:"id"`
- UserId string `gorm:"column:user_id" json:"user_id"`
- CommodityCode string `gorm:"commodity_code" json:"commodity_code"`
- Count int64 `gorm:"count" json:"count"`
- Money int64 `gorm:"money" json:"money"`
- Descs string `gorm:"descs" json:"descs"`
-}
+var db *sql.DB
+var expectedCount int64
func main() {
- initConfig()
+ client.InitPath("./conf/seatago.yml")
+ initDB()
+
+ ctx := context.Background()
- // test: select for update
- err := tm.WithGlobalTx(context.Background(), &tm.GtxConfig{
+ // execute select for update + update within global transaction
+ err := tm.WithGlobalTx(ctx, &tm.GtxConfig{
Name: "ATSampleLocalGlobalTx_SelectForUpdate",
Timeout: time.Second * 30,
- }, selectForUpdateData)
-
+ }, selectForUpdateAndModify)
if err != nil {
- log.Fatalf("failed to init transaction: %v", err)
- return
+ panic(fmt.Sprintf("transaction failed: %v", err))
}
- ctx := context.Background()
+ // verify data was updated correctly
+ if err := verifyData(ctx); err != nil {
+ panic(fmt.Sprintf("data verification failed: %v", err))
+ }
- // wait clean undo log
+ // wait for undo log cleanup
time.Sleep(time.Second * 10)
- if checkUndoLogData(ctx) != nil {
- panic("failed")
+
+ // verify undo log is cleaned
+ if err := verifyUndoLogCleaned(ctx); err != nil {
+ panic(fmt.Sprintf("undo log verification failed: %v", err))
}
-}
-func initConfig() {
- client.InitPath("./conf/seatago.yml")
- initDB()
+ fmt.Println("select_for_update test passed")
}
-var gormDB *gorm.DB
-
-func initDB() {
- sqlDB, err := sql.Open(sql2.SeataATMySQLDriver,
"root:12345678@tcp(127.0.0.1:3306)/seata_client?multiStatements=true&interpolateParams=true")
+// selectForUpdateAndModify tests SELECT ... FOR UPDATE followed by UPDATE
+// This is the typical use case: lock the row first, then modify it
+func selectForUpdateAndModify(ctx context.Context) error {
+ // step 1: select for update to lock the row
+ var id int64
+ var count int64
+ err := db.QueryRowContext(ctx,
+ "SELECT id, count FROM order_tbl WHERE id = ? FOR UPDATE",
1).Scan(&id, &count)
+ if err != nil {
+ return fmt.Errorf("select for update failed: %w", err)
+ }
+ fmt.Printf("locked row: id=%d, count=%d\n", id, count)
+
+ // step 2: update the locked row
+ newCount := count + 50
+ expectedCount = newCount // save for verification
+ result, err := db.ExecContext(ctx,
+ "UPDATE order_tbl SET count = ?, descs = ? WHERE id = ?",
+ newCount, "updated by select_for_update", id)
if err != nil {
- panic("init service error")
+ return fmt.Errorf("update failed: %w", err)
}
- gormDB, err = gorm.Open(mysql.New(mysql.Config{
- Conn: sqlDB,
- }), &gorm.Config{})
+ rows, err := result.RowsAffected()
if err != nil {
- panic("open DB error")
+ return fmt.Errorf("get rows affected failed: %w", err)
}
+ fmt.Printf("update affected rows: %d\n", rows)
+
+ return nil
}
-func getData() OrderTblModel {
- return OrderTblModel{
- UserId: "NO-100003",
- CommodityCode: "C100001",
- Count: 101,
- Money: 11,
- Descs: "insert desc",
+func verifyData(ctx context.Context) error {
+ var count int64
+ var descs string
+
+ err := db.QueryRowContext(ctx,
+ "SELECT count, descs FROM order_tbl WHERE id = ?",
1).Scan(&count, &descs)
+ if err != nil {
+ return fmt.Errorf("query failed: %w", err)
+ }
+
+ if count != expectedCount {
+ return fmt.Errorf("expected count=%d, got %d", expectedCount,
count)
+ }
+ if descs != "updated by select_for_update" {
+ return fmt.Errorf("expected descs='updated by
select_for_update', got '%s'", descs)
}
-}
-// selectForUpdateData select for update
-func selectForUpdateData(ctx context.Context) error {
- var data OrderTblModel
- return
gormDB.WithContext(ctx).Table("order_tbl").Where(&OrderTblModel{Id:
333}).Clauses(clause.Locking{Strength: "UPDATE"}).Find(&data).Error
+ fmt.Printf("data verified: count=%d, descs=%s\n", count, descs)
+ return nil
}
-func checkUndoLogData(ctx context.Context) error {
+func verifyUndoLogCleaned(ctx context.Context) error {
var count int64
- err := gormDB.WithContext(ctx).Table("undo_log").Count(&count).Error
+ err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM
undo_log").Scan(&count)
if err != nil {
- return err
+ return fmt.Errorf("query undo_log failed: %w", err)
}
+
if count != 0 {
- return fmt.Errorf("check undolog failed")
+ return fmt.Errorf("undo_log not cleaned, count=%d", count)
}
+
+ fmt.Println("undo_log cleaned successfully")
return nil
}
+
+func initDB() {
+ var err error
+ db, err = sql.Open(sql2.SeataATMySQLDriver,
"root:12345678@tcp(127.0.0.1:3306)/seata_client?multiStatements=true&interpolateParams=true")
+ if err != nil {
+ panic("init db error: " + err.Error())
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]