1 Star 0 Fork 0

Souki/go-framework

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
db_version_mag_v2.go 5.67 KB
一键复制 编辑 原始数据 按行查看 历史
sage 提交于 2022-12-05 17:36 +08:00 . Modify
package handler
import (
"database/sql"
"embed"
"fmt"
"gitee.com/scottq/go-framework/src/utils"
"io/ioutil"
"log"
"strings"
)
type DbVersionInfo struct {
Version string
SqlContent string
Comment string
}
type IVersionMagV2 interface {
AppendVersionDir(sqlDir string) error
AppendVersion(v DbVersionInfo)
AppendSqlContent(version string, content string)
AppendEmbedFS(fs embed.FS) error
AllVersionInfo() []DbVersionInfo
Upgrade(version string) error
UpgradeOne(vInfo DbVersionInfo) error
Version() (string, error)
SetLabel(label string)
Label() string
SetVars(map[string]string)
ILogger
}
type VersionMagV2 struct {
versions []DbVersionInfo
db *sql.DB
label string
vars map[string]string
optLock IOptimisticLock
_logger logFunc
}
func NewDBVersionMagV2(db *sql.DB) (IVersionMagV2, error) {
lock, err := NewOptimisticLock(db, 60)
if err != nil {
return nil, err
}
mag := &VersionMagV2{
db: db,
optLock: lock,
versions: []DbVersionInfo{},
}
if err := mag.init(); err != nil {
return nil, err
}
return mag, nil
}
func (mag *VersionMagV2) init() error {
var err error
_, err = mag.db.Exec(CREATE_VERSION_TABLE_SQL)
if err != nil {
mag.logError(err)
return err
}
return nil
}
func (mag *VersionMagV2) AddLogger(logger logFunc) {
mag._logger = logger
}
func (mag *VersionMagV2) AppendVersion(v DbVersionInfo) {
mag.versions = append(mag.versions, v)
}
func (mag *VersionMagV2) AppendSqlContent(version string, content string) {
mag.versions = append(mag.versions, DbVersionInfo{
Version: version,
SqlContent: content,
})
}
func (mag *VersionMagV2) AppendEmbedFS(fss embed.FS) error {
return utils.ScanEmbedFsDo(fss, func(file string, path string) error {
bytes, err := fss.ReadFile(path)
if err != nil {
return err
}
execSql := string(bytes)
mag.AppendSqlContent(file, execSql)
return nil
})
}
func (mag *VersionMagV2) SetVars(vars map[string]string) {
mag.vars = vars
}
func (mag *VersionMagV2) AppendVersionDir(sqlDir string) error {
if sqlDir == "" {
mag.logInfo("path is empty")
return nil
}
if !utils.IsExistPath(sqlDir) {
mag.logInfo("path not exist: " + sqlDir)
return nil
}
files, err := ioutil.ReadDir(sqlDir)
if err != nil {
return err
}
//
for _, x := range files {
if x.IsDir() {
continue
}
sqlFile := x.Name()
sqlFileFull := sqlDir + "/" + sqlFile
upVersion := strings.ReplaceAll(sqlFile, ".sql", "")
upVersion = strings.TrimLeft(upVersion, "v")
//执行升级文件
bytes, err := ioutil.ReadFile(sqlFileFull)
if err != nil {
return err
}
execSql := string(bytes)
mag.AppendSqlContent(upVersion, execSql)
}
return nil
}
//升级版本
func (mag *VersionMagV2) Upgrade(version string) error {
if version == "" {
version = "v99.99.99"
}
mag.logInfo("version upgrade to " + version)
lockName := mag.lockName()
if !mag.optLock.Lock(lockName) {
mag.logInfo("upgrade job has locked: " + lockName)
return nil
}
defer mag.optLock.UnLock(lockName)
//
versions := mag.versions
for index, v := range versions {
upVersion := v.Version
if utils.CompareVersion(upVersion, version) > 0 {
continue
}
err := mag.UpgradeOne(versions[index])
if err != nil {
return err
}
}
return nil
}
func (mag *VersionMagV2) AllVersionInfo() []DbVersionInfo {
return mag.versions
}
func (mag *VersionMagV2) SetLabel(label string) {
mag.label = label
}
func (mag *VersionMagV2) Label() string {
return mag.label
}
func (mag *VersionMagV2) lockName() string {
return "sql_upgrade." + mag.label
}
func (mag *VersionMagV2) logInfo(info string) {
if mag._logger == nil {
log.Println(info)
return
}
mag._logger(info, nil)
}
func (mag *VersionMagV2) logError(err error) {
if mag._logger == nil {
log.Println(err.Error())
return
}
mag._logger("", err)
}
//升级一次版本
func (mag *VersionMagV2) UpgradeOne(vInfo DbVersionInfo) error {
var err error
version, err := mag.Version()
if err != nil {
return err
}
upVersion := vInfo.Version
//无需处理
if utils.CompareVersion(vInfo.Version, version) <= 0 {
mag.logInfo("no need upgrade: " + upVersion)
return nil
}
err = mag.upgrade(vInfo)
if err != nil {
return err
}
mag.logInfo(fmt.Sprintf("upgrade success %s => %s", version, upVersion))
return nil
}
func (mag *VersionMagV2) upgrade(vInfo DbVersionInfo) error {
var err error
sqlContent := vInfo.SqlContent
if sqlContent == "" {
return fmt.Errorf("exec upgrade [%s] content is empty", vInfo.Version)
}
if mag.vars != nil {
for k, v := range mag.vars {
sqlContent = strings.ReplaceAll(sqlContent, k, v)
}
}
_, err = mag.db.Exec(sqlContent)
if err != nil {
mag.logError(err)
return err
}
//保存version信息
err = mag.addVersionRecord(mag.label, vInfo.Version, vInfo.Comment)
if err != nil {
mag.logError(err)
return err
}
return nil
}
//获取当前版本信息
func (mag VersionMagV2) Version() (string, error) {
var err error
querySql := fmt.Sprintf("SELECT version FROM %s WHERE label=? ORDER BY id DESC LIMIT 1", VERSION_MAG_TABLE)
row := mag.db.QueryRow(querySql, mag.label)
var version string
err = row.Scan(&version)
switch err {
case nil:
case sql.ErrNoRows:
default:
mag.logError(err)
return "", err
}
if version == "" {
version = "0.0.0"
}
return version, nil
}
func (mag *VersionMagV2) addVersionRecord(label, version, sqlFile string) error {
//保存version信息
insertSql := fmt.Sprintf("INSERT INTO %s SET `label`=?,`version`=?,`upgrade_file`=?", VERSION_MAG_TABLE)
stmt, err := mag.db.Prepare(insertSql)
if err != nil {
mag.logError(err)
return err
}
_, err = stmt.Exec(label, version, sqlFile)
if err != nil {
mag.logError(err)
return err
}
return nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/scottq/go-framework.git
git@gitee.com:scottq/go-framework.git
scottq
go-framework
go-framework
v1.1.46

搜索帮助