@ -4,6 +4,7 @@ import (
"fmt"
"github.com/yedf/dtm/dtmcli"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
@ -13,10 +14,11 @@ func svcSubmit(t *TransGlobal) (interface{}, error) {
err := t . saveNew ( db )
if err == errUniqueConflict {
dbt := transFromDb ( db , t . Gid )
dbt := transFromDb ( db . DB , t . Gid , false )
if dbt . Status == dtmcli . StatusPrepared {
updates := t . setNextCron ( cronReset )
db . Must ( ) . Model ( t ) . Where ( "gid=? and status=?" , t . Gid , dtmcli . StatusPrepared ) . Select ( append ( updates , "status" ) ) . Updates ( t )
dbr := db . Must ( ) . Model ( & TransGlobal { } ) . Where ( "gid=? and status=?" , t . Gid , dtmcli . StatusPrepared ) . Select ( append ( updates , "status" ) ) . Updates ( t )
checkAffected ( dbr )
} else if dbt . Status != dtmcli . StatusSubmitted {
return map [ string ] interface { } { "dtm_result" : dtmcli . ResultFailure , "message" : fmt . Sprintf ( "current status '%s', cannot sumbmit" , dbt . Status ) } , nil
}
@ -28,7 +30,7 @@ func svcPrepare(t *TransGlobal) (interface{}, error) {
t . Status = dtmcli . StatusPrepared
err := t . saveNew ( dbGet ( ) )
if err == errUniqueConflict {
dbt := transFromDb ( dbGet ( ) , t . Gid )
dbt := transFromDb ( dbGet ( ) . DB , t . Gid , false )
if dbt . Status != dtmcli . StatusPrepared {
return map [ string ] interface { } { "dtm_result" : dtmcli . ResultFailure , "message" : fmt . Sprintf ( "current status '%s', cannot prepare" , dbt . Status ) } , nil
}
@ -38,7 +40,7 @@ func svcPrepare(t *TransGlobal) (interface{}, error) {
func svcAbort ( t * TransGlobal ) ( interface { } , error ) {
db := dbGet ( )
dbt := transFromDb ( db , t . Gid )
dbt := transFromDb ( db . DB , t . Gid , false )
if t . TransType != "xa" && t . TransType != "tcc" || dbt . Status != dtmcli . StatusPrepared && dbt . Status != dtmcli . StatusAborting {
return map [ string ] interface { } { "dtm_result" : dtmcli . ResultFailure , "message" : fmt . Sprintf ( "trans type: '%s' current status '%s', cannot abort" , dbt . TransType , dbt . Status ) } , nil
}
@ -46,32 +48,37 @@ func svcAbort(t *TransGlobal) (interface{}, error) {
return dbt . Process ( db ) , nil
}
func svcRegisterBranch ( branch * TransBranch , data map [ string ] string ) ( interface { } , error ) {
db := dbGet ( )
dbt := transFromDb ( db , branch . Gid )
if dbt . Status != dtmcli . StatusPrepared {
return map [ string ] interface { } { "dtm_result" : dtmcli . ResultFailure , "message" : fmt . Sprintf ( "current status: %s cannot register branch" , dbt . Status ) } , nil
}
func svcRegisterBranch ( branch * TransBranch , data map [ string ] string ) ( ret interface { } , rerr error ) {
err := dbGet ( ) . Transaction ( func ( db * gorm . DB ) error {
dbt := transFromDb ( db , branch . Gid , true )
if dbt . Status != dtmcli . StatusPrepared {
ret = map [ string ] interface { } { "dtm_result" : dtmcli . ResultFailure , "message" : fmt . Sprintf ( "current status: %s cannot register branch" , dbt . Status ) }
return nil
}
branches := [ ] TransBranch { * branch , * branch }
if dbt . TransType == "tcc" {
for i , b := range [ ] string { dtmcli . BranchCancel , dtmcli . BranchConfirm } {
branches [ i ] . Op = b
branches [ i ] . URL = data [ b ]
branches := [ ] TransBranch { * branch , * branch }
if dbt . TransType == "tcc" {
for i , b := range [ ] string { dtmcli . BranchCancel , dtmcli . BranchConfirm } {
branches [ i ] . Op = b
branches [ i ] . URL = data [ b ]
}
} else if dbt . TransType == "xa" {
branches [ 0 ] . Op = dtmcli . BranchRollback
branches [ 0 ] . URL = data [ "url" ]
branches [ 1 ] . Op = dtmcli . BranchCommit
branches [ 1 ] . URL = data [ "url" ]
} else {
rerr = fmt . Errorf ( "unknow trans type: %s" , dbt . TransType )
return nil
}
} else if dbt . TransType == "xa" {
branches [ 0 ] . Op = dtmcli . BranchRollback
branches [ 0 ] . URL = data [ "url" ]
branches [ 1 ] . Op = dtmcli . BranchCommit
branches [ 1 ] . URL = data [ "url" ]
} else {
return nil , fmt . Errorf ( "unknow trans type: %s" , dbt . TransType )
}
db . Must ( ) . Clauses ( clause . OnConflict {
DoNothing : true ,
} ) . Create ( branches )
global := TransGlobal { Gid : branch . Gid }
global . touch ( dbGet ( ) , cronKeep )
return dtmcli . MapSuccess , nil
dbr := db . Clauses ( clause . OnConflict {
DoNothing : true ,
} ) . Create ( branches )
checkAffected ( dbr )
ret = dtmcli . MapSuccess
return nil
} )
e2p ( err )
return
}