package storage

import (
	"github.com/astaxie/beego/orm"
)

type DbaTasker interface {
	Exec(db orm.Ormer) error
	Rollback(db orm.Ormer) error
}

type Task func(db orm.Ormer) error

func (t *Task) Exec(db orm.Ormer) error {
	return (*t)(db)
}

func (t *Task) Rollback(db orm.Ormer) error {
	return nil
}

func GenerateDbaTask(task Task) DbaTasker {
	return &task
}

func ExecTrans(tasks ...DbaTasker) error {
	mysqlORM := orm.NewOrm()
	successTask := make([]DbaTasker, 0)
	isCommit := false
	defer func() {
		// 捕获异常，并执行回滚操作
		if v := recover(); v != nil || !isCommit {
			for _, task := range successTask {
				task.Rollback(mysqlORM)
			}
			mysqlORM.Rollback()
			//向上层抛出异常
			if v != nil {
				panic(v)
			}
		}
	}()

	if err := mysqlORM.Begin(); err != nil {
		panic("db error")
	}

	for _, task := range tasks {
		if task != nil {
			if err := task.Exec(mysqlORM); err != nil {
				if err == EXIT_QUERY {
					return err
				}
				panic(err)
			}
		}
		successTask = append(successTask, task)
	}

	mysqlORM.Commit()
	isCommit = true
	return nil
}
