github.com/kunlun-qilian/sqlx/v3@v3.0.0/task.go (about)

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