mirror of https://github.com/ouqiang/gocron
feat($upgrade): 支持从旧版本升级, #13
parent
db1ef3b317
commit
350dc0881e
|
@ -26,9 +26,7 @@ _testmain.go
|
|||
.idea
|
||||
log/*
|
||||
data/*
|
||||
conf/install.lock
|
||||
conf/app.ini
|
||||
conf/ansible_hosts.ini
|
||||
conf/*
|
||||
profile/*
|
||||
public/resource/javascript/vue.js
|
||||
gocron
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
* -s ip:port 监听地址
|
||||
|
||||
## To Do List
|
||||
- [ ] 版本升级
|
||||
- [x] 版本升级
|
||||
- [ ] 任务分组
|
||||
- [ ] 多用户
|
||||
- [ ] 权限控制
|
||||
|
|
22
cmd/web.go
22
cmd/web.go
|
@ -47,7 +47,7 @@ func runWeb(ctx *cli.Context) {
|
|||
// 设置运行环境
|
||||
setEnvironment(ctx)
|
||||
// 初始化应用
|
||||
app.InitEnv()
|
||||
app.InitEnv(ctx.App.Version)
|
||||
// 初始化模块 DB、定时任务等
|
||||
initModule()
|
||||
// 捕捉信号,配置热更新等
|
||||
|
@ -74,8 +74,12 @@ func initModule() {
|
|||
}
|
||||
app.Setting = config
|
||||
|
||||
// 初始化DB
|
||||
models.Db = models.CreateDb()
|
||||
|
||||
// 版本升级
|
||||
upgradeIfNeed()
|
||||
|
||||
// 初始化定时任务
|
||||
serviceTask := new(service.Task)
|
||||
serviceTask.Initialize()
|
||||
|
@ -167,4 +171,20 @@ func shutdown() {
|
|||
|
||||
// 释放gRPC连接池
|
||||
grpcpool.Pool.ReleaseAll()
|
||||
}
|
||||
|
||||
// 判断应用是否需要升级, 当版本号文件版本小于app.VersionId时升级
|
||||
func upgradeIfNeed() {
|
||||
currentVersionId := app.GetCurrentVersionId()
|
||||
if currentVersionId >= app.VersionId {
|
||||
return
|
||||
}
|
||||
|
||||
migration := new(models.Migration)
|
||||
logger.Infof("版本升级开始, 当前版本号%d", currentVersionId)
|
||||
|
||||
migration.Upgrade(currentVersionId)
|
||||
app.UpdateVersionFile()
|
||||
|
||||
logger.Infof("已升级到最新版本%d", app.VersionId)
|
||||
}
|
|
@ -4,11 +4,11 @@ import (
|
|||
"errors"
|
||||
)
|
||||
|
||||
// 创建数据库表
|
||||
|
||||
type Migration struct{}
|
||||
|
||||
func (migration *Migration) Exec(dbName string) error {
|
||||
// 首次安装, 创建数据库表
|
||||
func (migration *Migration) Install(dbName string) error {
|
||||
if !isDatabaseExist(dbName) {
|
||||
return errors.New("数据库不存在")
|
||||
}
|
||||
|
@ -36,9 +36,29 @@ func (migration *Migration) Exec(dbName string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// 创建数据库
|
||||
// 判断数据库是否存在
|
||||
func isDatabaseExist(name string) bool {
|
||||
_, err := Db.Exec("use ?", name)
|
||||
|
||||
return err != nil
|
||||
}
|
||||
|
||||
// 迭代升级数据库, 新建表、新增字段等
|
||||
func (migration *Migration) Upgrade(oldVersionId int) {
|
||||
versionIds := []int{}
|
||||
upgradeFuncs := []func(){}
|
||||
|
||||
startIndex := 0
|
||||
for i, value := range versionIds {
|
||||
if oldVersionId == value {
|
||||
startIndex = i + 1
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
length := len(versionIds)
|
||||
for startIndex < length {
|
||||
upgradeFuncs[startIndex]()
|
||||
startIndex++
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ import (
|
|||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"gopkg.in/ini.v1"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -16,10 +19,12 @@ var (
|
|||
AppConfig string // 应用配置文件
|
||||
Installed bool // 应用是否安装过
|
||||
Setting *ini.Section // 应用配置
|
||||
VersionId int // 版本号
|
||||
VersionFile string // 版本号文件
|
||||
)
|
||||
|
||||
|
||||
func InitEnv() {
|
||||
func InitEnv(versionString string) {
|
||||
logger.InitLogger()
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
@ -30,11 +35,13 @@ func InitEnv() {
|
|||
LogDir = AppDir + "/log"
|
||||
DataDir = AppDir + "/data"
|
||||
AppConfig = ConfDir + "/app.ini"
|
||||
VersionFile = ConfDir + "/.version"
|
||||
checkDirExists(ConfDir, LogDir, DataDir)
|
||||
Installed = IsInstalled()
|
||||
VersionId = ToNumberVersion(versionString)
|
||||
}
|
||||
|
||||
// 判断应用是否安装过
|
||||
// 判断应用是否已安装
|
||||
func IsInstalled() bool {
|
||||
_, err := os.Stat(ConfDir + "/install.lock")
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -54,6 +61,54 @@ func CreateInstallLock() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// 更新应用版本号文件
|
||||
func UpdateVersionFile() {
|
||||
err := ioutil.WriteFile(VersionFile,
|
||||
[]byte(strconv.Itoa(VersionId)),
|
||||
0644,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取应用当前版本号, 从版本号文件中读取
|
||||
func GetCurrentVersionId() int {
|
||||
if !utils.FileExist(VersionFile) {
|
||||
// 默认版本号110, 从v1.1版本开始支持升级
|
||||
return 110;
|
||||
}
|
||||
|
||||
bytes, err := ioutil.ReadFile(VersionFile)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
versionId, err := strconv.Atoi(string(bytes))
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
return versionId
|
||||
}
|
||||
|
||||
// 把字符串版本号a.b.c转换为整数版本号abc
|
||||
func ToNumberVersion(versionString string) int {
|
||||
versionString = strings.TrimSpace(versionString)
|
||||
v := strings.Replace(versionString, ".", "", -1)
|
||||
if len(v) < 3 {
|
||||
v += "0"
|
||||
}
|
||||
|
||||
versionId, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
return versionId
|
||||
}
|
||||
|
||||
// 检测目录是否存在
|
||||
func checkDirExists(path ...string) {
|
||||
for _, value := range path {
|
||||
|
|
|
@ -75,7 +75,7 @@ func Store(ctx *macaron.Context, form InstallForm) string {
|
|||
models.Db = models.CreateDb()
|
||||
// 创建数据库表
|
||||
migration := new(models.Migration)
|
||||
err = migration.Exec(form.DbName)
|
||||
err = migration.Install(form.DbName)
|
||||
if err != nil {
|
||||
return json.CommonFailure(fmt.Sprintf("创建数据库表失败-%s", err.Error()), err)
|
||||
}
|
||||
|
@ -92,6 +92,9 @@ func Store(ctx *macaron.Context, form InstallForm) string {
|
|||
return json.CommonFailure("创建文件安装锁失败", err)
|
||||
}
|
||||
|
||||
// 更新版本号文件
|
||||
app.UpdateVersionFile()
|
||||
|
||||
app.Installed = true
|
||||
// 初始化定时任务
|
||||
serviceTask := new(service.Task)
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"strings"
|
||||
"text/template"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
// 定时任务调度管理器
|
||||
|
@ -364,7 +365,7 @@ func appendResultToCommand(command string, taskResult TaskResult) string {
|
|||
}
|
||||
data := map[string]interface{} {
|
||||
"Code": code,
|
||||
"Message": taskResult.Result,
|
||||
"Message": base64.StdEncoding.EncodeToString([]byte(taskResult.Result)),
|
||||
}
|
||||
var buf *bytes.Buffer = new(bytes.Buffer)
|
||||
tmpl, err := template.New("command").Parse(command)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="ui striped table">
|
||||
<table class="ui celled table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="ui pink table task-list">
|
||||
<table class="ui celled table task-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>任务ID</th>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="ui pink table">
|
||||
<table class="ui celled table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>任务ID</th>
|
||||
|
|
Loading…
Reference in New Issue