阶段性提交

This commit is contained in:
GoEdgeLab
2020-09-16 09:09:21 +08:00
parent 4a55b483e9
commit 81720234d5
18 changed files with 566 additions and 13 deletions

View File

@@ -4,6 +4,7 @@ import (
"github.com/TeaOSLab/EdgeAPI/internal/apis"
"github.com/TeaOSLab/EdgeAPI/internal/apps"
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
_ "github.com/TeaOSLab/EdgeAPI/internal/tasks"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -61,6 +61,7 @@ func (this *APINode) listenRPC() error {
pb.RegisterOriginServerServiceServer(rpcServer, &services.OriginServerService{})
pb.RegisterHTTPWebServiceServer(rpcServer, &services.HTTPWebService{})
pb.RegisterReverseProxyServiceServer(rpcServer, &services.ReverseProxyService{})
pb.RegisterHTTPGzipServiceServer(rpcServer, &services.HTTPGzipService{})
err = rpcServer.Serve(listener)
if err != nil {
return errors.New("[API]start rpc failed: " + err.Error())

View File

@@ -0,0 +1,133 @@
package models
import (
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
)
const (
HTTPGzipStateEnabled = 1 // 已启用
HTTPGzipStateDisabled = 0 // 已禁用
)
type HTTPGzipDAO dbs.DAO
func NewHTTPGzipDAO() *HTTPGzipDAO {
return dbs.NewDAO(&HTTPGzipDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeHTTPGzips",
Model: new(HTTPGzip),
PkName: "id",
},
}).(*HTTPGzipDAO)
}
var SharedHTTPGzipDAO = NewHTTPGzipDAO()
// 启用条目
func (this *HTTPGzipDAO) EnableHTTPGzip(id int64) error {
_, err := this.Query().
Pk(id).
Set("state", HTTPGzipStateEnabled).
Update()
return err
}
// 禁用条目
func (this *HTTPGzipDAO) DisableHTTPGzip(id int64) error {
_, err := this.Query().
Pk(id).
Set("state", HTTPGzipStateDisabled).
Update()
return err
}
// 查找启用中的条目
func (this *HTTPGzipDAO) FindEnabledHTTPGzip(id int64) (*HTTPGzip, error) {
result, err := this.Query().
Pk(id).
Attr("state", HTTPGzipStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*HTTPGzip), err
}
// 组合配置
func (this *HTTPGzipDAO) ComposeGzipConfig(gzipId int64) (*serverconfigs.HTTPGzipConfig, error) {
gzip, err := this.FindEnabledHTTPGzip(gzipId)
if err != nil {
return nil, err
}
if gzip == nil {
return nil, nil
}
config := &serverconfigs.HTTPGzipConfig{}
config.Id = int64(gzip.Id)
config.IsOn = gzip.IsOn == 1
if len(gzip.MinLength) > 0 && gzip.MinLength != "null" {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(gzip.MinLength), minLengthConfig)
if err != nil {
return nil, err
}
config.MinLength = minLengthConfig
}
if len(gzip.MaxLength) > 0 && gzip.MaxLength != "null" {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(gzip.MaxLength), maxLengthConfig)
if err != nil {
return nil, err
}
config.MaxLength = maxLengthConfig
}
config.Level = types.Int8(gzip.Level)
return config, nil
}
// 创建Gzip
func (this *HTTPGzipDAO) CreateGzip(level int, minLengthJSON []byte, maxLengthJSON []byte) (int64, error) {
op := NewHTTPGzipOperator()
op.State = HTTPGzipStateEnabled
op.IsOn = true
op.Level = level
if len(minLengthJSON) > 0 {
op.MinLength = string(minLengthJSON)
}
if len(maxLengthJSON) > 0 {
op.MaxLength = string(maxLengthJSON)
}
_, err := this.Save(op)
if err != nil {
return 0, err
}
return types.Int64(op.Id), nil
}
// 修改Gzip
func (this *HTTPGzipDAO) UpdateGzip(gzipId int64, level int, minLengthJSON []byte, maxLengthJSON []byte) error {
if gzipId <= 0 {
return errors.New("invalid gzipId")
}
op := NewHTTPGzipOperator()
op.Id = gzipId
op.Level = level
if len(minLengthJSON) > 0 {
op.MinLength = string(minLengthJSON)
}
if len(maxLengthJSON) > 0 {
op.MaxLength = string(maxLengthJSON)
}
_, err := this.Save(op)
return err
}

View File

@@ -0,0 +1,5 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
)

View File

@@ -0,0 +1,30 @@
package models
// Gzip配置
type HTTPGzip struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint32 `field:"createdAt"` // 创建时间
}
type HTTPGzipOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
IsOn interface{} // 是否启用
Level interface{} // 压缩级别
MinLength interface{} // 可压缩最小值
MaxLength interface{} // 可压缩最大值
State interface{} // 状态
CreatedAt interface{} // 创建时间
}
func NewHTTPGzipOperator() *HTTPGzipOperator {
return &HTTPGzipOperator{}
}

View File

@@ -0,0 +1,26 @@
package models
import (
"encoding/json"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
// 解析最小长度
func (this *HTTPGzip) DecodeMinLength() (*shared.SizeCapacity, error) {
if len(this.MinLength) == 0 {
return nil, nil
}
capacity := &shared.SizeCapacity{}
err := json.Unmarshal([]byte(this.MinLength), capacity)
return capacity, err
}
// 解析最大长度
func (this *HTTPGzip) DecodeMaxLength() (*shared.SizeCapacity, error) {
if len(this.MaxLength) == 0 {
return nil, nil
}
capacity := &shared.SizeCapacity{}
err := json.Unmarshal([]byte(this.MaxLength), capacity)
return capacity, err
}

View File

@@ -60,7 +60,7 @@ func (this *HTTPWebDAO) FindEnabledHTTPWeb(id int64) (*HTTPWeb, error) {
}
// 组合配置
func (this *HTTPWebDAO) ComposeWebConfig(webId int64) (*serverconfigs.WebConfig, error) {
func (this *HTTPWebDAO) ComposeWebConfig(webId int64) (*serverconfigs.HTTPWebConfig, error) {
web, err := SharedHTTPWebDAO.FindEnabledHTTPWeb(webId)
if err != nil {
return nil, err
@@ -68,9 +68,24 @@ func (this *HTTPWebDAO) ComposeWebConfig(webId int64) (*serverconfigs.WebConfig,
if web == nil {
return nil, nil
}
config := &serverconfigs.WebConfig{}
config := &serverconfigs.HTTPWebConfig{}
config.Id = webId
config.IsOn = web.IsOn == 1
config.Root = web.Root
// gzip
if web.GzipId > 0 {
gzipConfig, err := SharedHTTPGzipDAO.ComposeGzipConfig(int64(web.GzipId))
if err != nil {
return nil, err
}
config.Gzip = gzipConfig
}
// TODO charset
// TODO 更多配置
return config, nil
}
@@ -95,8 +110,37 @@ func (this *HTTPWebDAO) UpdateWeb(webId int64, root string) error {
op.Id = webId
op.Root = root
_, err := this.Save(op)
if err != nil {
return err
}
// TODO 更新所有使用此Web配置的服务
return err
return this.NotifyUpdating(webId)
}
// 修改Gzip配置
func (this *HTTPWebDAO) UpdateWebGzip(webId int64, gzipId int64) error {
if webId <= 0 {
return errors.New("invalid webId")
}
op := NewHTTPWebOperator()
op.Id = webId
op.GzipId = gzipId
_, err := this.Save(op)
if err != nil {
return err
}
return this.NotifyUpdating(webId)
}
// 通知更新
func (this *HTTPWebDAO) NotifyUpdating(webId int64) error {
err := SharedServerDAO.UpdateServerIsUpdatingWithWebId(webId)
if err != nil {
return err
}
// TODO 更新所有使用此Web配置的Location所在服务
return nil
}

View File

@@ -10,6 +10,7 @@ type HTTPWeb struct {
State uint8 `field:"state"` // 状态
CreatedAt uint32 `field:"createdAt"` // 创建时间
Root string `field:"root"` // 资源根目录
GzipId uint32 `field:"gzipId"` // Gzip配置
}
type HTTPWebOperator struct {
@@ -21,6 +22,7 @@ type HTTPWebOperator struct {
State interface{} // 状态
CreatedAt interface{} // 创建时间
Root interface{} // 资源根目录
GzipId interface{} // Gzip配置
}
func NewHTTPWebOperator() *HTTPWebOperator {

View File

@@ -118,7 +118,7 @@ func (this *OriginServerDAO) ComposeOriginConfig(originId int64) (*serverconfigs
}
}
connTimeout := shared.TimeDuration{}
connTimeout := &shared.TimeDuration{}
if len(origin.ConnTimeout) > 0 && origin.ConnTimeout != "null" {
err = json.Unmarshal([]byte(origin.ConnTimeout), &connTimeout)
if err != nil {
@@ -126,7 +126,7 @@ func (this *OriginServerDAO) ComposeOriginConfig(originId int64) (*serverconfigs
}
}
readTimeout := shared.TimeDuration{}
readTimeout := &shared.TimeDuration{}
if len(origin.ReadTimeout) > 0 && origin.ReadTimeout != "null" {
err = json.Unmarshal([]byte(origin.ReadTimeout), &readTimeout)
if err != nil {
@@ -134,7 +134,7 @@ func (this *OriginServerDAO) ComposeOriginConfig(originId int64) (*serverconfigs
}
}
idleTimeout := shared.TimeDuration{}
idleTimeout := &shared.TimeDuration{}
if len(origin.IdleTimeout) > 0 && origin.IdleTimeout != "null" {
err = json.Unmarshal([]byte(origin.IdleTimeout), &idleTimeout)
if err != nil {

View File

@@ -2,4 +2,13 @@ package models
import (
_ "github.com/go-sql-driver/mysql"
"testing"
)
func TestOriginServerDAO_ComposeOriginConfig(t *testing.T) {
config, err := SharedOriginServerDAO.ComposeOriginConfig(1)
if err != nil {
t.Fatal(err)
}
t.Log(config)
}

View File

@@ -88,7 +88,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(reverseProxyId int64) (*s
return nil, err
}
for _, originConfig := range originConfigs {
newOriginConfig, err := SharedOriginServerDAO.ComposeOriginConfig(int64(originConfig.Id))
newOriginConfig, err := SharedOriginServerDAO.ComposeOriginConfig(originConfig.Id)
if err != nil {
return nil, err
}
@@ -99,7 +99,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(reverseProxyId int64) (*s
}
if len(reverseProxy.BackupOrigins) > 0 && reverseProxy.BackupOrigins != "null" {
originConfigs := []*OriginServer{}
originConfigs := []*serverconfigs.OriginServerConfig{}
err = json.Unmarshal([]byte(reverseProxy.BackupOrigins), &originConfigs)
if err != nil {
return nil, err
@@ -195,3 +195,12 @@ func (this *ReverseProxyDAO) UpdateReverseProxyBackupOrigins(reverseProxyId int6
return err
}
// 修改是否启用
func (this *ReverseProxyDAO) UpdateReverseProxyIsOn(reverseProxyId int64, isOn bool) error {
_, err := this.Query().
Pk(reverseProxyId).
Set("isOn", isOn).
Update()
return err
}

View File

@@ -283,6 +283,28 @@ func (this *ServerDAO) UpdateServerWeb(serverId int64, webId int64) error {
return this.RenewServerConfig(serverId)
}
// 初始化Web配置
func (this *ServerDAO) InitServerWeb(serverId int64) (int64, error) {
if serverId <= 0 {
return 0, errors.New("serverId should not be smaller than 0")
}
webId, err := SharedHTTPWebDAO.CreateWeb("")
if err != nil {
return 0, err
}
_, err = this.Query().
Pk(serverId).
Set("webId", webId).
Update()
if err != nil {
return 0, err
}
return webId, nil
}
// 修改ServerNames配置
func (this *ServerDAO) UpdateServerNames(serverId int64, config []byte) error {
if serverId <= 0 {
@@ -503,6 +525,40 @@ func (this *ServerDAO) FindReverseProxyConfig(serverId int64) (*serverconfigs.Re
return config, err
}
// 查找需要更新的Server
func (this *ServerDAO) FindUpdatingServerIds() (serverIds []int64, err error) {
ones, err := this.Query().
State(ServerStateEnabled).
Attr("isUpdating", true).
ResultPk().
FindAll()
if err != nil {
return nil, err
}
for _, one := range ones {
serverIds = append(serverIds, int64(one.(*Server).Id))
}
return
}
// 修改服务是否需要更新
func (this *ServerDAO) UpdateServerIsUpdating(serverId int64, isUpdating bool) error {
_, err := this.Query().
Pk(serverId).
Set("isUpdating", isUpdating).
Update()
return err
}
// 更新所有Web相关的处于更新状态
func (this *ServerDAO) UpdateServerIsUpdatingWithWebId(webId int64) error {
_, err := this.Query().
Attr("webId", webId).
Set("isUpdating", true).
Update()
return err
}
// 生成唯一ID
func (this *ServerDAO) genUniqueId() (string, error) {
for {

View File

@@ -26,6 +26,7 @@ type Server struct {
ExcludeNodes string `field:"excludeNodes"` // 节点排除条件
Version uint32 `field:"version"` // 版本号
CreatedAt uint32 `field:"createdAt"` // 创建时间
IsUpdating uint8 `field:"isUpdating"` // 是否正在更新
State uint8 `field:"state"` // 状态
}
@@ -54,6 +55,7 @@ type ServerOperator struct {
ExcludeNodes interface{} // 节点排除条件
Version interface{} // 版本号
CreatedAt interface{} // 创建时间
IsUpdating interface{} // 是否正在更新
State interface{} // 状态
}

View File

@@ -45,7 +45,9 @@ func (this *HTTPWebService) FindEnabledHTTPWeb(ctx context.Context, req *pb.Find
result := &pb.HTTPWeb{}
result.Id = int64(web.Id)
result.IsOn = web.IsOn == 1
result.Root = web.Root
result.GzipId = int64(web.GzipId)
return &pb.FindEnabledHTTPWebResponse{Web: result}, nil
}
@@ -64,3 +66,19 @@ func (this *HTTPWebService) UpdateHTTPWeb(ctx context.Context, req *pb.UpdateHTT
return &pb.UpdateHTTPWebResponse{}, nil
}
// 修改Gzip配置
func (this *HTTPWebService) UpdateHTTPWebGzip(ctx context.Context, req *pb.UpdateHTTPWebGzipRequest) (*pb.UpdateHTTPWebGzipResponse, error) {
// 校验请求
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
}
err = models.SharedHTTPWebDAO.UpdateWebGzip(req.WebId, req.GzipId)
if err != nil {
return nil, err
}
return &pb.UpdateHTTPWebGzipResponse{}, nil
}

View File

@@ -120,3 +120,19 @@ func (this *ReverseProxyService) UpdateReverseProxyBackupOrigins(ctx context.Con
return &pb.UpdateReverseProxyBackupOriginsResponse{}, nil
}
// 修改是否启用
func (this *ReverseProxyService) UpdateReverseProxyIsOn(ctx context.Context, req *pb.UpdateReverseProxyIsOnRequest) (*pb.UpdateReverseProxyIsOnResponse, error) {
// 校验请求
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
}
err = models.SharedReverseProxyDAO.UpdateReverseProxyIsOn(req.ReverseProxyId, req.IsOn)
if err != nil {
return nil, err
}
return &pb.UpdateReverseProxyIsOnResponse{}, nil
}

View File

@@ -426,6 +426,12 @@ func (this *ServerService) ListEnabledServers(ctx context.Context, req *pb.ListE
Config: []byte(server.Config),
Name: server.Name,
Description: server.Description,
HttpJSON: []byte(server.Http),
HttpsJSON: []byte(server.Https),
TcpJSON: []byte(server.Tcp),
TlsJSON: []byte(server.Tls),
UnixJSON: []byte(server.Unix),
UdpJSON: []byte(server.Udp),
IncludeNodes: []byte(server.IncludeNodes),
ExcludeNodes: []byte(server.ExcludeNodes),
CreatedAt: int64(server.CreatedAt),
@@ -497,6 +503,7 @@ func (this *ServerService) FindEnabledServer(ctx context.Context, req *pb.FindEn
Name: server.Name,
Description: server.Description,
Config: []byte(server.Config),
ServerNamesJON: []byte(server.ServerNames),
HttpJSON: []byte(server.Http),
HttpsJSON: []byte(server.Https),
TcpJSON: []byte(server.Tcp),
@@ -532,7 +539,7 @@ func (this *ServerService) FindEnabledServerType(ctx context.Context, req *pb.Fi
}
// 查找反向代理设置
func (this *ServerService) FindServerReverseProxy(ctx context.Context, req *pb.FindServerReverseProxyRequest) (*pb.FindServerReverseProxyResponse, error) {
func (this *ServerService) FindServerReverseProxyConfig(ctx context.Context, req *pb.FindServerReverseProxyConfigRequest) (*pb.FindServerReverseProxyConfigResponse, error) {
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
@@ -544,12 +551,27 @@ func (this *ServerService) FindServerReverseProxy(ctx context.Context, req *pb.F
}
if reverseProxy == nil {
return &pb.FindServerReverseProxyResponse{Config: nil}, nil
return &pb.FindServerReverseProxyConfigResponse{Config: nil}, nil
}
configData, err := json.Marshal(reverseProxy)
if err != nil {
return nil, err
}
return &pb.FindServerReverseProxyResponse{Config: configData}, nil
return &pb.FindServerReverseProxyConfigResponse{Config: configData}, nil
}
// 初始化Web设置
func (this *ServerService) InitServerWeb(ctx context.Context, req *pb.InitServerWebRequest) (*pb.InitServerWebResponse, error) {
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
}
webId, err := models.SharedServerDAO.InitServerWeb(req.ServerId)
if err != nil {
return nil, err
}
return &pb.InitServerWebResponse{WebId: webId}, nil
}

View File

@@ -0,0 +1,109 @@
package services
import (
"context"
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
type HTTPGzipService struct {
}
// 创建Gzip配置
func (this *HTTPGzipService) CreateHTTPGzip(ctx context.Context, req *pb.CreateHTTPGzipRequest) (*pb.CreateHTTPGzipResponse, error) {
// 校验请求
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
}
minLengthJSON := []byte{}
if req.MinLength != nil {
minLengthJSON, err = (&shared.SizeCapacity{
Count: req.MinLength.Count,
Unit: req.MinLength.Unit,
}).AsJSON()
if err != nil {
return nil, err
}
}
maxLengthJSON := []byte{}
if req.MaxLength != nil {
maxLengthJSON, err = (&shared.SizeCapacity{
Count: req.MaxLength.Count,
Unit: req.MaxLength.Unit,
}).AsJSON()
if err != nil {
return nil, err
}
}
gzipId, err := models.SharedHTTPGzipDAO.CreateGzip(int(req.Level), minLengthJSON, maxLengthJSON)
if err != nil {
return nil, err
}
return &pb.CreateHTTPGzipResponse{GzipId: gzipId}, nil
}
// 查找Gzip
func (this *HTTPGzipService) FindEnabledHTTPGzipConfig(ctx context.Context, req *pb.FindEnabledGzipConfigRequest) (*pb.FindEnabledGzipConfigResponse, error) {
// 校验请求
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
}
config, err := models.SharedHTTPGzipDAO.ComposeGzipConfig(req.GzipId)
if err != nil {
return nil, err
}
configData, err := json.Marshal(config)
if err != nil {
return nil, err
}
return &pb.FindEnabledGzipConfigResponse{Config: configData}, nil
}
// 修改Gzip配置
func (this *HTTPGzipService) UpdateHTTPGzip(ctx context.Context, req *pb.UpdateHTTPGzipRequest) (*pb.UpdateHTTPGzipResponse, error) {
// 校验请求
_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
if err != nil {
return nil, err
}
minLengthJSON := []byte{}
if req.MinLength != nil {
minLengthJSON, err = (&shared.SizeCapacity{
Count: req.MinLength.Count,
Unit: req.MinLength.Unit,
}).AsJSON()
if err != nil {
return nil, err
}
}
maxLengthJSON := []byte{}
if req.MaxLength != nil {
maxLengthJSON, err = (&shared.SizeCapacity{
Count: req.MaxLength.Count,
Unit: req.MaxLength.Unit,
}).AsJSON()
if err != nil {
return nil, err
}
}
err = models.SharedHTTPGzipDAO.UpdateGzip(req.GzipId, int(req.Level), minLengthJSON, maxLengthJSON)
if err != nil {
return nil, err
}
return &pb.UpdateHTTPGzipResponse{}, nil
}

View File

@@ -0,0 +1,70 @@
package tasks
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/iwind/TeaGo/logs"
"time"
)
// TODO 考虑多个API服务同时运行的冲突
func init() {
task := &ServerUpdateTask{}
go task.Run()
}
// 更新服务配置
type ServerUpdateTask struct {
}
func (this *ServerUpdateTask) Run() {
ticker := time.NewTicker(1 * time.Second)
for range ticker.C {
this.loop()
}
}
func (this *ServerUpdateTask) loop() {
serverIds, err := models.SharedServerDAO.FindUpdatingServerIds()
if err != nil {
logs.Println("[ServerUpdateTask]" + err.Error())
return
}
if len(serverIds) == 0 {
return
}
for _, serverId := range serverIds {
// 查找配置
config, err := models.SharedServerDAO.ComposeServerConfig(serverId)
if err != nil {
logs.Println("[ServerUpdateTask]" + err.Error())
continue
}
if config == nil {
err = models.SharedServerDAO.UpdateServerIsUpdating(serverId, false)
if err != nil {
logs.Println("[ServerUpdateTask]" + err.Error())
continue
}
}
configData, err := json.Marshal(config)
if err != nil {
logs.Println("[ServerUpdateTask]" + err.Error())
continue
}
// 修改配置
err = models.SharedServerDAO.UpdateServerConfig(serverId, configData)
if err != nil {
logs.Println("[ServerUpdateTask]" + err.Error())
continue
}
// 修改更新状态
err = models.SharedServerDAO.UpdateServerIsUpdating(serverId, false)
if err != nil {
logs.Println("[ServerUpdateTask]" + err.Error())
continue
}
}
}