|
- package executor
-
- import (
- "context"
- "github.com/pkg/errors"
- "github.com/seata/seata-go/pkg/common/log"
- "github.com/seata/seata-go/pkg/protocol/transaction"
- "github.com/seata/seata-go/pkg/protocol/transaction/manager"
- "sync"
- )
-
- type TransactionalExecutor interface {
- Execute(ctx context.Context, param interface{}) (interface{}, error)
- GetTransactionInfo() transaction.TransactionInfo
- }
-
- var (
- transactionTemplate *TransactionTemplate
- onceTransactionTemplate = &sync.Once{}
- )
-
- func GetTransactionTemplate() *TransactionTemplate {
- if transactionTemplate == nil {
- onceTransactionTemplate.Do(func() {
- transactionTemplate = &TransactionTemplate{}
- })
- }
- return transactionTemplate
- }
-
- type TransactionTemplate struct {
- }
-
- func (t *TransactionTemplate) Execute(ctx context.Context, business TransactionalExecutor, param interface{}) (interface{}, error) {
- if !transaction.IsSeataContext(ctx) {
- err := errors.New("context should be inited as seata context!")
- log.Error(err)
- return nil, err
- }
-
- if transaction.GetTransactionRole(ctx) == nil {
- transaction.SetTransactionRole(ctx, transaction.LAUNCHER)
- }
-
- var tx *manager.GlobalTransaction
- if transaction.HasXID(ctx) {
- tx = &manager.GlobalTransaction{
- Xid: transaction.GetXID(ctx),
- Status: transaction.Begin,
- Role: transaction.PARTICIPANT,
- }
- }
-
- // todo: Handle the transaction propagation.
-
- if tx == nil {
- tx = &manager.GlobalTransaction{
- Xid: transaction.GetXID(ctx),
- Status: transaction.UnKnown,
- Role: transaction.LAUNCHER,
- }
- }
-
- // todo: set current tx config to holder
-
- // begin global transaction
- err := t.BeginTransaction(ctx, tx, business.GetTransactionInfo().TimeOut, business.GetTransactionInfo().Name)
- if err != nil {
- log.Infof("transactionTemplate: begin transaction failed, error %v", err)
- return nil, err
- }
-
- // do your business
- res, err := business.Execute(ctx, param)
- if err != nil {
- log.Infof("transactionTemplate: execute business failed, error %v", err)
- return nil, manager.GetGlobalTransactionManager().Rollback(ctx, tx)
- }
-
- // commit global transaction
- err = t.CommitTransaction(ctx, tx)
- if err != nil {
- log.Infof("transactionTemplate: commit transaction failed, error %v", err)
- // rollback transaction
- return nil, manager.GetGlobalTransactionManager().Rollback(ctx, tx)
- }
- return res, err
- }
-
- func (TransactionTemplate) BeginTransaction(ctx context.Context, tx *manager.GlobalTransaction, timeout int32, name string) error {
- return manager.GetGlobalTransactionManager().Begin(ctx, tx, timeout, name)
- }
-
- func (TransactionTemplate) CommitTransaction(ctx context.Context, tx *manager.GlobalTransaction) error {
- return manager.GetGlobalTransactionManager().Commit(ctx, tx)
- }
|