github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/sqlx/tx_task.go (about) 1 package sqlx 2 3 import ( 4 "fmt" 5 "runtime/debug" 6 7 "github.com/pkg/errors" 8 9 "github.com/machinefi/w3bstream/pkg/depends/kit/logr" 10 ) 11 12 type Task func(db DBExecutor) error 13 14 func (task Task) Run(db DBExecutor) (err error) { 15 defer func() { 16 if e := recover(); e != nil { 17 err = fmt.Errorf("panic: %s; calltrace:%s", fmt.Sprint(e), string(debug.Stack())) 18 } 19 }() 20 return task(db) 21 } 22 23 func NewTasks(db DBExecutor) *Tasks { 24 return &Tasks{ 25 db: db, 26 } 27 } 28 29 type Tasks struct { 30 db DBExecutor 31 tasks []Task 32 } 33 34 func (tasks Tasks) With(task ...Task) *Tasks { 35 tasks.tasks = append(tasks.tasks, task...) 36 return &tasks 37 } 38 39 func (tasks *Tasks) Do() (err error) { 40 if len(tasks.tasks) == 0 { 41 return nil 42 } 43 44 db := tasks.db 45 46 l := logr.FromContext(db.Context()) 47 48 if maybeTx, ok := db.(TxExecutor); ok { 49 inTxScope := false 50 51 if !maybeTx.IsTx() { 52 db, err = maybeTx.Begin() 53 if err != nil { 54 return err 55 } 56 maybeTx = db.(TxExecutor) 57 inTxScope = true 58 } 59 60 for _, task := range tasks.tasks { 61 if runErr := task.Run(db); runErr != nil { 62 if inTxScope { 63 // err will bubble up,just handle and rollback in outermost layer 64 l.Error(errors.Wrap(err, "SQL FAILED")) 65 if rollBackErr := maybeTx.Rollback(); rollBackErr != nil { 66 l.Warn(errors.Wrap(rollBackErr, "ROLLBACK FAILED")) 67 err = rollBackErr 68 return 69 } 70 } 71 return runErr 72 } 73 } 74 75 if inTxScope { 76 if commitErr := maybeTx.Commit(); commitErr != nil { 77 l.Warn(errors.Wrap(commitErr, "TRANSACTION COMMIT FAILED")) 78 return commitErr 79 } 80 } 81 82 } 83 return nil 84 }