Files
waf-platform/EdgeAPI/internal/db/models/plan_dao_plus.go

490 lines
11 KiB
Go

//go:build plus
package models
import (
"bytes"
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
)
const (
PlanStateEnabled = 1 // 已启用
PlanStateDisabled = 0 // 已禁用
)
type PlanDAO dbs.DAO
func NewPlanDAO() *PlanDAO {
return dbs.NewDAO(&PlanDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgePlans",
Model: new(Plan),
PkName: "id",
},
}).(*PlanDAO)
}
var SharedPlanDAO *PlanDAO
func init() {
dbs.OnReady(func() {
SharedPlanDAO = NewPlanDAO()
})
}
// EnablePlan 启用条目
func (this *PlanDAO) EnablePlan(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Set("state", PlanStateEnabled).
Update()
return err
}
// DisablePlan 禁用条目
func (this *PlanDAO) DisablePlan(tx *dbs.Tx, planId int64) error {
clusterId, err := this.FindPlanClusterId(tx, planId)
if err != nil {
return err
}
_, err = this.Query(tx).
Pk(planId).
Set("state", PlanStateDisabled).
Update()
if err != nil {
return err
}
err = SharedServerDAO.ResetServersTrafficLimitStatusWithPlanId(tx, planId)
if err != nil {
return err
}
return this.NotifyUpdate(tx, planId, clusterId)
}
// FindEnabledPlan 查找启用中的条目
func (this *PlanDAO) FindEnabledPlan(tx *dbs.Tx, planId int64, cacheMap *utils.CacheMap) (*Plan, error) {
var cacheKey = this.Table + ":FindEnabledPlan:" + types.String(planId)
if cacheMap != nil {
cache, _ := cacheMap.Get(cacheKey)
if cache != nil {
return cache.(*Plan), nil
}
}
result, err := this.Query(tx).
Pk(planId).
Attr("state", PlanStateEnabled).
Find()
if result == nil {
return nil, err
}
if cacheMap != nil {
cacheMap.Put(cacheKey, result)
}
return result.(*Plan), err
}
// FindBasicPlan 查找套餐基本信息
func (this *PlanDAO) FindBasicPlan(tx *dbs.Tx, planId int64) (*Plan, error) {
one, err := this.Query(tx).
Pk(planId).
State(PlanStateEnabled).
Result("id", "name", "isOn").
Find()
if err != nil || one == nil {
return nil, err
}
return one.(*Plan), nil
}
// FindPlanName 根据主键查找名称
func (this *PlanDAO) FindPlanName(tx *dbs.Tx, id int64) (string, error) {
return this.Query(tx).
Pk(id).
Result("name").
FindStringCol("")
}
// CreatePlan 创建套餐
func (this *PlanDAO) CreatePlan(tx *dbs.Tx,
name string,
description string,
clusterId int64,
trafficLimitJSON []byte,
bandwidthLimitPerNode []byte,
hasFullFeatures bool,
featuresJSON []byte,
priceType serverconfigs.PlanPriceType,
trafficPriceJSON []byte,
bandwidthPriceJSON []byte,
monthlyPrice float32,
seasonallyPrice float32,
yearlyPrice float32,
totalServers int32,
totalServerNames int32,
totalServerNamesPerServer int32,
dailyRequests int64,
monthlyRequests int64,
dailyWebsocketConnections int64,
monthlyWebsocketConnections int64,
maxUploadSizeJSON []byte) (int64, error) {
var op = NewPlanOperator()
op.Name = name
op.Description = description
op.ClusterId = clusterId
if len(trafficLimitJSON) > 0 {
op.TrafficLimit = trafficLimitJSON
}
if len(bandwidthLimitPerNode) > 0 {
op.BandwidthLimitPerNode = bandwidthLimitPerNode
}
op.HasFullFeatures = hasFullFeatures
if len(featuresJSON) > 0 {
op.Features = featuresJSON
}
op.PriceType = priceType
if len(trafficPriceJSON) > 0 {
op.TrafficPrice = trafficPriceJSON
}
if len(bandwidthPriceJSON) > 0 {
op.BandwidthPrice = bandwidthPriceJSON
}
if monthlyPrice >= 0 {
op.MonthlyPrice = monthlyPrice
}
if seasonallyPrice >= 0 {
op.SeasonallyPrice = seasonallyPrice
}
if yearlyPrice >= 0 {
op.YearlyPrice = yearlyPrice
}
op.TotalServers = totalServers
op.TotalServerNamesPerServer = totalServerNamesPerServer
op.TotalServerNames = totalServerNames
op.DailyRequests = dailyRequests
op.MonthlyRequests = monthlyRequests
op.DailyWebsocketConnections = dailyWebsocketConnections
op.MonthlyWebsocketConnections = monthlyWebsocketConnections
if maxUploadSizeJSON != nil {
op.MaxUploadSize = maxUploadSizeJSON
}
op.IsOn = true
op.State = PlanStateEnabled
return this.SaveInt64(tx, op)
}
// UpdatePlan 修改套餐
func (this *PlanDAO) UpdatePlan(tx *dbs.Tx,
planId int64,
name string,
description string,
isOn bool,
clusterId int64,
trafficLimitJSON []byte,
bandwidthLimitPerNode []byte,
hasFullFeatures bool,
featuresJSON []byte,
priceType serverconfigs.PlanPriceType,
trafficPriceJSON []byte,
bandwidthPriceJSON []byte,
monthlyPrice float32,
seasonallyPrice float32,
yearlyPrice float32,
totalServers int32,
totalServerNames int32,
totalServerNamesPerServer int32,
dailyRequests int64,
monthlyRequests int64,
dailyWebsocketConnections int64,
monthlyWebsocketConnections int64,
maxUploadSizeJSON []byte) error {
if planId <= 0 {
return errors.New("invalid planId")
}
// 检查集群有无变化
oldClusterId, err := this.Query(tx).
Pk(planId).
Result("clusterId").
FindInt64Col(0)
if err != nil {
return err
}
// 检查限制是否变化
oldPlanOne, err := this.Query(tx).
Pk(planId).
Find()
if err != nil || oldPlanOne == nil {
return err
}
var oldPlan = oldPlanOne.(*Plan)
var op = NewPlanOperator()
op.Id = planId
op.Name = name
op.Description = description
op.IsOn = isOn
op.ClusterId = clusterId
if len(trafficLimitJSON) > 0 {
op.TrafficLimit = trafficLimitJSON
}
if len(bandwidthLimitPerNode) > 0 {
op.BandwidthLimitPerNode = bandwidthLimitPerNode
}
op.HasFullFeatures = hasFullFeatures
if len(featuresJSON) > 0 {
op.Features = featuresJSON
}
op.PriceType = priceType
if len(trafficPriceJSON) > 0 {
op.TrafficPrice = trafficPriceJSON
}
if len(bandwidthPriceJSON) > 0 {
op.BandwidthPrice = bandwidthPriceJSON
}
if monthlyPrice >= 0 {
op.MonthlyPrice = monthlyPrice
} else {
op.MonthlyPrice = 0
}
if seasonallyPrice >= 0 {
op.SeasonallyPrice = seasonallyPrice
} else {
op.SeasonallyPrice = 0
}
if yearlyPrice >= 0 {
op.YearlyPrice = yearlyPrice
} else {
op.YearlyPrice = 0
}
op.TotalServers = totalServers
op.TotalServerNamesPerServer = totalServerNamesPerServer
op.TotalServerNames = totalServerNames
op.DailyRequests = dailyRequests
op.MonthlyRequests = monthlyRequests
op.DailyWebsocketConnections = dailyWebsocketConnections
op.MonthlyWebsocketConnections = monthlyWebsocketConnections
if maxUploadSizeJSON != nil {
op.MaxUploadSize = maxUploadSizeJSON
}
err = this.Save(tx, op)
if err != nil {
return err
}
if oldClusterId != clusterId {
// 修改服务所属集群
err = SharedServerDAO.UpdateServersClusterIdWithPlanId(tx, planId, clusterId)
if err != nil {
return err
}
err = this.NotifyUpdate(tx, planId, oldClusterId)
if err != nil {
return err
}
}
err = this.NotifyUpdate(tx, planId, clusterId)
if err != nil {
return err
}
// 检查流量、请求数等限制变化
var planLimitChanged = false
// 检查流量限制
if !bytes.Equal(oldPlan.TrafficLimit, trafficLimitJSON) {
var newTrafficLimitConfig = &serverconfigs.TrafficLimitConfig{}
if IsNull(oldPlan.TrafficLimit) || IsNull(trafficLimitJSON) {
planLimitChanged = true
} else {
var oldTrafficLimitConfig = &serverconfigs.TrafficLimitConfig{}
err = json.Unmarshal(oldPlan.TrafficLimit, oldTrafficLimitConfig)
if err != nil {
return err
}
err = json.Unmarshal(trafficLimitJSON, newTrafficLimitConfig)
if err != nil {
return err
}
if !oldTrafficLimitConfig.Equals(newTrafficLimitConfig) {
planLimitChanged = true
}
}
}
// 检查请求数限制
if !planLimitChanged && (int64(oldPlan.DailyRequests) != dailyRequests ||
int64(oldPlan.MonthlyRequests) != monthlyRequests ||
int64(oldPlan.DailyWebsocketConnections) != dailyWebsocketConnections ||
int64(oldPlan.MonthlyWebsocketConnections) != monthlyWebsocketConnections) {
planLimitChanged = true
}
if planLimitChanged {
// 重置限流状态
err = SharedServerDAO.ResetServersTrafficLimitStatusWithPlanId(tx, planId)
if err != nil {
return err
}
// 重新计算限流状态
err = SharedUserPlanStatDAO.ResetUserPlanStatsWithPlanId(tx, planId)
if err != nil {
return err
}
err = SharedUserPlanStatDAO.ProcessUserPlanStats(tx)
if err != nil {
return err
}
}
return nil
}
// CountAllEnabledPlans 计算套餐的数量
func (this *PlanDAO) CountAllEnabledPlans(tx *dbs.Tx) (int64, error) {
return this.Query(tx).
State(PlanStateEnabled).
Count()
}
// ListEnabledPlans 列出单页套餐
func (this *PlanDAO) ListEnabledPlans(tx *dbs.Tx, offset int64, size int64) (result []*Plan, err error) {
_, err = this.Query(tx).
State(PlanStateEnabled).
Offset(offset).
Limit(size).
Slice(&result).
Desc("order").
AscPk().
FindAll()
return
}
// FindAllEnabledPlans 查找所有可用套餐,包含未启用的套餐
func (this *PlanDAO) FindAllEnabledPlans(tx *dbs.Tx) (result []*Plan, err error) {
_, err = this.Query(tx).
State(PlanStateEnabled).
Slice(&result).
FindAll()
return
}
// FindAllAvailablePlans 查找所有可用套餐
// 不包含未启用的套餐
func (this *PlanDAO) FindAllAvailablePlans(tx *dbs.Tx) (result []*Plan, err error) {
_, err = this.Query(tx).
State(PlanStateEnabled).
Attr("isOn", true).
Desc("order").
AscPk().
Slice(&result).
FindAll()
return
}
// FindAllAvailableBasicPlans 查找所有可用套餐,并只返回基本信息
func (this *PlanDAO) FindAllAvailableBasicPlans(tx *dbs.Tx) (result []*Plan, err error) {
_, err = this.Query(tx).
State(PlanStateEnabled).
Attr("isOn", true).
Result("id", "name", "bandwidthLimitPerNode", "trafficLimit", "maxUploadSize").
Slice(&result).
FindAll()
return
}
// SortPlans 增加排序
func (this *PlanDAO) SortPlans(tx *dbs.Tx, planIds []int64) error {
if len(planIds) == 0 {
return nil
}
var order = len(planIds)
for _, planId := range planIds {
err := this.Query(tx).
Pk(planId).
Set("order", order).
UpdateQuickly()
if err != nil {
return err
}
order--
}
return nil
}
// FindEnabledPlanTrafficLimit 获取套餐的流量限制
func (this *PlanDAO) FindEnabledPlanTrafficLimit(tx *dbs.Tx, planId int64, cacheMap *utils.CacheMap) (*serverconfigs.TrafficLimitConfig, error) {
var cacheKey = this.Table + ":FindEnabledPlanTrafficLimit:" + types.String(planId)
if cacheMap != nil {
cache, _ := cacheMap.Get(cacheKey)
if cache != nil {
return cache.(*serverconfigs.TrafficLimitConfig), nil
}
}
trafficLimit, err := this.Query(tx).
Pk(planId).
State(PlanStateEnabled).
Result("trafficLimit").
FindStringCol("")
if err != nil {
return nil, err
}
if len(trafficLimit) == 0 {
return nil, nil
}
var config = &serverconfigs.TrafficLimitConfig{}
err = json.Unmarshal([]byte(trafficLimit), config)
if err != nil {
return nil, err
}
if cacheMap != nil {
cacheMap.Put(cacheKey, config)
}
return config, nil
}
// FindPlanClusterId 查找套餐所属集群
func (this *PlanDAO) FindPlanClusterId(tx *dbs.Tx, planId int64) (clusterId int64, err error) {
return this.Query(tx).
Pk(planId).
Result("clusterId").
FindInt64Col(0)
}
// NotifyUpdate 通知变更
func (this *PlanDAO) NotifyUpdate(tx *dbs.Tx, planId int64, clusterId int64) error {
if clusterId <= 0 {
return nil
}
err := SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypePlanChanged)
if err != nil {
return err
}
return nil
}