dtm/dtmsvr/cron.go
2021-05-27 23:15:55 +08:00

102 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package dtmsvr
import (
"fmt"
"math"
"math/rand"
"strings"
"time"
"github.com/sirupsen/logrus"
"github.com/yedf/dtm/common"
)
func CronPreparedOnce(expire time.Duration) {
db := dbGet()
ss := []TransGlobal{}
db.Must().Model(&TransGlobal{}).Where("update_time < date_sub(now(), interval ? second)", int(expire/time.Second)).Where("status = ?", "prepared").Find(&ss)
writeTransLog("", "saga fetch prepared", fmt.Sprint(len(ss)), "", "")
if len(ss) == 0 {
return
}
for _, sm := range ss {
writeTransLog(sm.Gid, "saga touch prepared", "", "", "")
db.Must().Model(&sm).Update("id", sm.ID)
resp, err := common.RestyClient.R().SetQueryParam("gid", sm.Gid).Get(sm.QueryPrepared)
e2p(err)
body := resp.String()
if strings.Contains(body, "FAIL") {
preparedExpire := time.Now().Add(time.Duration(-config.PreparedExpire) * time.Second)
logrus.Printf("create time: %s prepared expire: %s ", sm.CreateTime.Local(), preparedExpire.Local())
status := common.If(sm.CreateTime.Before(preparedExpire), "canceled", "prepared").(string)
writeTransLog(sm.Gid, "saga canceled", status, "", "")
db.Must().Model(&sm).Where("status = ?", "prepared").Update("status", status)
} else if strings.Contains(body, "SUCCESS") {
sm.Status = "committed"
sm.SaveNew(db)
sm.Process(db)
}
}
}
func CronPrepared() {
for {
defer handlePanic()
CronTransOnce(time.Duration(config.JobCronInterval)*time.Second, "prepared")
sleepCronTime()
}
}
func CronTransOnce(expire time.Duration, status string) bool {
trans := lockOneTrans(expire, status)
if trans == nil {
return false
}
trans.touch(dbGet())
branches := []TransBranch{}
db := dbGet()
db.Must().Where("gid=?", trans.Gid).Order("id asc").Find(&branches)
trans.getProcessor().ProcessOnce(db, branches)
if TransProcessedTestChan != nil {
TransProcessedTestChan <- trans.Gid
}
return true
}
func CronCommitted() {
for {
defer handlePanic()
processed := CronTransOnce(time.Duration(config.JobCronInterval)*time.Second, "commitetd")
if !processed {
sleepCronTime()
}
}
}
func lockOneTrans(expire time.Duration, status string) *TransGlobal {
trans := TransGlobal{}
owner := common.GenGid()
db := dbGet()
dbr := db.Must().Model(&trans).
Where("update_time < date_sub(now(), interval ? second) and status=?", int(expire/time.Second), status).
Limit(1).Update("owner", owner)
if dbr.RowsAffected == 0 {
return nil
}
dbr = db.Must().Where("owner=?", owner).Find(&trans)
return &trans
}
func handlePanic() {
if err := recover(); err != nil {
logrus.Printf("----panic %s handlered", err.(error).Error())
time.Sleep(3 * time.Second) // 出错后睡眠3s避免无限循环
}
}
func sleepCronTime() {
delta := math.Min(3, float64(config.JobCronInterval))
interval := time.Duration(rand.Float64() * delta * float64(time.Second))
time.Sleep(interval)
}