From 7eecaa1224d7c211ff1c42c40b814336d92f924e Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Thu, 10 Dec 2020 22:07:21 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=8C=BA=E5=9F=9F]=E5=8F=AF=E4=BB=A5=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=8C=BA=E5=9F=9F-=E4=BB=B7=E6=A0=BC=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=B9=8B=E9=97=B4=E7=9A=84=E4=BB=B7=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/tt/main.go | 2 +- internal/db/models/node_price_item_dao.go | 120 ++++++++++++++++ .../db/models/node_price_item_dao_test.go | 5 + internal/db/models/node_price_item_model.go | 28 ++++ .../db/models/node_price_item_model_ext.go | 1 + internal/db/models/node_region_dao.go | 34 +++++ internal/db/models/node_region_model.go | 2 + internal/db/models/server_stat_dao.go | 28 ++++ internal/db/models/server_stat_dao_test.go | 5 + internal/db/models/server_stat_model.go | 26 ++++ internal/db/models/server_stat_model_ext.go | 1 + internal/nodes/api_node.go | 1 + .../rpc/services/service_node_price_item.go | 130 ++++++++++++++++++ internal/rpc/services/service_node_region.go | 34 +++-- 14 files changed, 407 insertions(+), 10 deletions(-) create mode 100644 internal/db/models/node_price_item_dao.go create mode 100644 internal/db/models/node_price_item_dao_test.go create mode 100644 internal/db/models/node_price_item_model.go create mode 100644 internal/db/models/node_price_item_model_ext.go create mode 100644 internal/db/models/server_stat_dao.go create mode 100644 internal/db/models/server_stat_dao_test.go create mode 100644 internal/db/models/server_stat_model.go create mode 100644 internal/db/models/server_stat_model_ext.go create mode 100644 internal/rpc/services/service_node_price_item.go diff --git a/cmd/tt/main.go b/cmd/tt/main.go index 5e1a5af6..2890ac56 100644 --- a/cmd/tt/main.go +++ b/cmd/tt/main.go @@ -19,7 +19,7 @@ func main() { lastCommand := "" for { - time.Sleep(400 * time.Millisecond) + time.Sleep(200 * time.Millisecond) fmt.Print("> ") line, _, err := r.ReadLine() diff --git a/internal/db/models/node_price_item_dao.go b/internal/db/models/node_price_item_dao.go new file mode 100644 index 00000000..4013d604 --- /dev/null +++ b/internal/db/models/node_price_item_dao.go @@ -0,0 +1,120 @@ +package models + +import ( + "errors" + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + NodePriceItemStateEnabled = 1 // 已启用 + NodePriceItemStateDisabled = 0 // 已禁用 +) + +type NodePriceItemDAO dbs.DAO + +func NewNodePriceItemDAO() *NodePriceItemDAO { + return dbs.NewDAO(&NodePriceItemDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeNodePriceItems", + Model: new(NodePriceItem), + PkName: "id", + }, + }).(*NodePriceItemDAO) +} + +var SharedNodePriceItemDAO *NodePriceItemDAO + +func init() { + dbs.OnReady(func() { + SharedNodePriceItemDAO = NewNodePriceItemDAO() + }) +} + +// 启用条目 +func (this *NodePriceItemDAO) EnableNodePriceItem(id int64) error { + _, err := this.Query(). + Pk(id). + Set("state", NodePriceItemStateEnabled). + Update() + return err +} + +// 禁用条目 +func (this *NodePriceItemDAO) DisableNodePriceItem(id int64) error { + _, err := this.Query(). + Pk(id). + Set("state", NodePriceItemStateDisabled). + Update() + return err +} + +// 查找启用中的条目 +func (this *NodePriceItemDAO) FindEnabledNodePriceItem(id int64) (*NodePriceItem, error) { + result, err := this.Query(). + Pk(id). + Attr("state", NodePriceItemStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*NodePriceItem), err +} + +// 根据主键查找名称 +func (this *NodePriceItemDAO) FindNodePriceItemName(id int64) (string, error) { + return this.Query(). + Pk(id). + Result("name"). + FindStringCol("") +} + +// 创建价格 +func (this *NodePriceItemDAO) CreateItem(name string, itemType string, bitsFrom, bitsTo int64) (int64, error) { + op := NewNodePriceItemOperator() + op.Name = name + op.Type = itemType + op.BitsFrom = bitsFrom + op.BitsTo = bitsTo + op.IsOn = true + op.State = NodePriceItemStateEnabled + return this.SaveInt64(op) +} + +// 修改价格 +func (this *NodePriceItemDAO) UpdateItem(itemId int64, name string, bitsFrom, bitsTo int64) error { + if itemId <= 0 { + return errors.New("invalid itemId") + } + op := NewNodePriceItemOperator() + op.Id = itemId + op.Name = name + op.BitsFrom = bitsFrom + op.BitsTo = bitsTo + return this.Save(op) +} + +// 列出某个区域的所有价格 +func (this *NodePriceItemDAO) FindAllEnabledRegionPrices(priceType string) (result []*NodePriceItem, err error) { + _, err = this.Query(). + Attr("type", priceType). + State(NodePriceItemStateEnabled). + Asc("bitsFrom"). + Slice(&result). + FindAll() + return +} + +// 列出某个区域的所有启用的价格 +func (this *NodePriceItemDAO) FindAllEnabledAndOnRegionPrices(priceType string) (result []*NodePriceItem, err error) { + _, err = this.Query(). + Attr("type", priceType). + State(NodePriceItemStateEnabled). + Attr("isOn", true). + Asc("bitsFrom"). + Slice(&result). + FindAll() + return +} diff --git a/internal/db/models/node_price_item_dao_test.go b/internal/db/models/node_price_item_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/node_price_item_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/node_price_item_model.go b/internal/db/models/node_price_item_model.go new file mode 100644 index 00000000..cc6da5a4 --- /dev/null +++ b/internal/db/models/node_price_item_model.go @@ -0,0 +1,28 @@ +package models + +// 区域计费设置 +type NodePriceItem struct { + Id uint32 `field:"id"` // ID + IsOn uint8 `field:"isOn"` // 是否启用 + Type string `field:"type"` // 类型:峰值|流量 + Name string `field:"name"` // 名称 + BitsFrom uint64 `field:"bitsFrom"` // 起始值 + BitsTo uint64 `field:"bitsTo"` // 结束值 + CreatedAt uint64 `field:"createdAt"` // 创建时间 + State uint8 `field:"state"` // 状态 +} + +type NodePriceItemOperator struct { + Id interface{} // ID + IsOn interface{} // 是否启用 + Type interface{} // 类型:峰值|流量 + Name interface{} // 名称 + BitsFrom interface{} // 起始值 + BitsTo interface{} // 结束值 + CreatedAt interface{} // 创建时间 + State interface{} // 状态 +} + +func NewNodePriceItemOperator() *NodePriceItemOperator { + return &NodePriceItemOperator{} +} diff --git a/internal/db/models/node_price_item_model_ext.go b/internal/db/models/node_price_item_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/node_price_item_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/node_region_dao.go b/internal/db/models/node_region_dao.go index 6801544c..f0aafb8c 100644 --- a/internal/db/models/node_region_dao.go +++ b/internal/db/models/node_region_dao.go @@ -1,7 +1,9 @@ package models import ( + "encoding/json" "github.com/TeaOSLab/EdgeAPI/internal/errors" + "github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils" _ "github.com/go-sql-driver/mysql" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/dbs" @@ -131,3 +133,35 @@ func (this *NodeRegionDAO) UpdateRegionOrders(regionIds []int64) error { } return nil } + +// 修改价格项价格 +func (this *NodeRegionDAO) UpdateRegionItemPrice(regionId int64, itemId int64, price float32) error { + one, err := this.Query(). + Pk(regionId). + Result("prices"). + Find() + if err != nil { + return err + } + if one == nil { + return nil + } + prices := one.(*NodeRegion).Prices + pricesMap := map[string]float32{} + if len(prices) > 0 && prices != "null" { + err = json.Unmarshal([]byte(prices), &pricesMap) + if err != nil { + return err + } + } + pricesMap[numberutils.FormatInt64(itemId)] = price + pricesJSON, err := json.Marshal(pricesMap) + if err != nil { + return err + } + _, err = this.Query(). + Pk(regionId). + Set("prices", pricesJSON). + Update() + return err +} diff --git a/internal/db/models/node_region_model.go b/internal/db/models/node_region_model.go index 99a20d82..772ab7c9 100644 --- a/internal/db/models/node_region_model.go +++ b/internal/db/models/node_region_model.go @@ -8,6 +8,7 @@ type NodeRegion struct { Name string `field:"name"` // 名称 Order uint32 `field:"order"` // 排序 CreatedAt uint64 `field:"createdAt"` // 创建时间 + Prices string `field:"prices"` // 价格 State uint8 `field:"state"` // 状态 } @@ -18,6 +19,7 @@ type NodeRegionOperator struct { Name interface{} // 名称 Order interface{} // 排序 CreatedAt interface{} // 创建时间 + Prices interface{} // 价格 State interface{} // 状态 } diff --git a/internal/db/models/server_stat_dao.go b/internal/db/models/server_stat_dao.go new file mode 100644 index 00000000..512b4811 --- /dev/null +++ b/internal/db/models/server_stat_dao.go @@ -0,0 +1,28 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +type ServerStatDAO dbs.DAO + +func NewServerStatDAO() *ServerStatDAO { + return dbs.NewDAO(&ServerStatDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeServerStats", + Model: new(ServerStat), + PkName: "id", + }, + }).(*ServerStatDAO) +} + +var SharedServerStatDAO *ServerStatDAO + +func init() { + dbs.OnReady(func() { + SharedServerStatDAO = NewServerStatDAO() + }) +} diff --git a/internal/db/models/server_stat_dao_test.go b/internal/db/models/server_stat_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/server_stat_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/server_stat_model.go b/internal/db/models/server_stat_model.go new file mode 100644 index 00000000..0ca979f7 --- /dev/null +++ b/internal/db/models/server_stat_model.go @@ -0,0 +1,26 @@ +package models + +// 计费流量统计 +type ServerStat struct { + Id uint64 `field:"id"` // ID + ServerId uint32 `field:"serverId"` // 服务ID + RegionId uint32 `field:"regionId"` // 区域ID + Bytes uint64 `field:"bytes"` // 流量 + Day string `field:"day"` // 日期YYYYMMDD + TimeFrom string `field:"timeFrom"` // 开始时间HHMMSS + TimeTo string `field:"timeTo"` // 结束时间 +} + +type ServerStatOperator struct { + Id interface{} // ID + ServerId interface{} // 服务ID + RegionId interface{} // 区域ID + Bytes interface{} // 流量 + Day interface{} // 日期YYYYMMDD + TimeFrom interface{} // 开始时间HHMMSS + TimeTo interface{} // 结束时间 +} + +func NewServerStatOperator() *ServerStatOperator { + return &ServerStatOperator{} +} diff --git a/internal/db/models/server_stat_model_ext.go b/internal/db/models/server_stat_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/server_stat_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/nodes/api_node.go b/internal/nodes/api_node.go index 699f25f1..94a46d1c 100644 --- a/internal/nodes/api_node.go +++ b/internal/nodes/api_node.go @@ -186,6 +186,7 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err pb.RegisterMessageServiceServer(rpcServer, &services.MessageService{}) pb.RegisterNodeGroupServiceServer(rpcServer, &services.NodeGroupService{}) pb.RegisterNodeRegionServiceServer(rpcServer, &services.NodeRegionService{}) + pb.RegisterNodePriceItemServiceServer(rpcServer, &services.NodePriceItemService{}) pb.RegisterServerGroupServiceServer(rpcServer, &services.ServerGroupService{}) pb.RegisterIPLibraryServiceServer(rpcServer, &services.IPLibraryService{}) pb.RegisterFileChunkServiceServer(rpcServer, &services.FileChunkService{}) diff --git a/internal/rpc/services/service_node_price_item.go b/internal/rpc/services/service_node_price_item.go new file mode 100644 index 00000000..c96757a3 --- /dev/null +++ b/internal/rpc/services/service_node_price_item.go @@ -0,0 +1,130 @@ +package services + +import ( + "context" + "github.com/TeaOSLab/EdgeAPI/internal/db/models" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +// 节点区域价格相关服务 +type NodePriceItemService struct { + BaseService +} + +// 创建区域价格 +func (this *NodePriceItemService) CreateNodePriceItem(ctx context.Context, req *pb.CreateNodePriceItemRequest) (*pb.CreateNodePriceItemResponse, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + itemId, err := models.SharedNodePriceItemDAO.CreateItem(req.Name, req.Type, req.BitsFrom, req.BitsTo) + if err != nil { + return nil, err + } + return &pb.CreateNodePriceItemResponse{NodePriceItemId: itemId}, nil +} + +// 修改区域价格 +func (this *NodePriceItemService) UpdateNodePriceItem(ctx context.Context, req *pb.UpdateNodePriceItemRequest) (*pb.RPCSuccess, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + err = models.SharedNodePriceItemDAO.UpdateItem(req.NodePriceItemId, req.Name, req.BitsFrom, req.BitsTo) + if err != nil { + return nil, err + } + return this.Success() +} + +// 删除区域价格 +func (this *NodePriceItemService) DeleteNodePriceItem(ctx context.Context, req *pb.DeleteNodePriceItemRequest) (*pb.RPCSuccess, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + err = models.SharedNodePriceItemDAO.DisableNodePriceItem(req.NodePriceItemId) + if err != nil { + return nil, err + } + return this.Success() +} + +// 查找所有区域价格 +func (this *NodePriceItemService) FindAllEnabledNodePriceItems(ctx context.Context, req *pb.FindAllEnabledNodePriceItemsRequest) (*pb.FindAllEnabledNodePriceItemsResponse, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + prices, err := models.SharedNodePriceItemDAO.FindAllEnabledRegionPrices(req.Type) + if err != nil { + return nil, err + } + result := []*pb.NodePriceItem{} + for _, price := range prices { + result = append(result, &pb.NodePriceItem{ + Id: int64(price.Id), + IsOn: price.IsOn == 1, + Name: price.Name, + Type: price.Type, + BitsFrom: int64(price.BitsFrom), + BitsTo: int64(price.BitsTo), + }) + } + + return &pb.FindAllEnabledNodePriceItemsResponse{NodePriceItems: result}, nil +} + +// 查找所有启用的区域价格 +func (this *NodePriceItemService) FindAllEnabledAndOnNodePriceItems(ctx context.Context, req *pb.FindAllEnabledAndOnNodePriceItemsRequest) (*pb.FindAllEnabledAndOnNodePriceItemsResponse, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + prices, err := models.SharedNodePriceItemDAO.FindAllEnabledAndOnRegionPrices(req.Type) + if err != nil { + return nil, err + } + result := []*pb.NodePriceItem{} + for _, price := range prices { + result = append(result, &pb.NodePriceItem{ + Id: int64(price.Id), + IsOn: price.IsOn == 1, + Name: price.Name, + Type: price.Type, + BitsFrom: int64(price.BitsFrom), + BitsTo: int64(price.BitsTo), + }) + } + + return &pb.FindAllEnabledAndOnNodePriceItemsResponse{NodePriceItems: result}, nil +} + +// 查找单个区域信息 +func (this *NodePriceItemService) FindEnabledNodePriceItem(ctx context.Context, req *pb.FindEnabledNodePriceItemRequest) (*pb.FindEnabledNodePriceItemResponse, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + price, err := models.SharedNodePriceItemDAO.FindEnabledNodePriceItem(req.NodePriceItemId) + if err != nil { + return nil, err + } + if price == nil { + return &pb.FindEnabledNodePriceItemResponse{NodePriceItem: nil}, nil + } + return &pb.FindEnabledNodePriceItemResponse{NodePriceItem: &pb.NodePriceItem{ + Id: int64(price.Id), + IsOn: price.IsOn == 1, + Name: price.Name, + Type: price.Type, + BitsFrom: int64(price.BitsFrom), + BitsTo: int64(price.BitsTo), + }}, nil +} diff --git a/internal/rpc/services/service_node_region.go b/internal/rpc/services/service_node_region.go index c493ffaa..506459b6 100644 --- a/internal/rpc/services/service_node_region.go +++ b/internal/rpc/services/service_node_region.go @@ -63,9 +63,10 @@ func (this *NodeRegionService) FindAllEnabledNodeRegions(ctx context.Context, re result := []*pb.NodeRegion{} for _, region := range regions { result = append(result, &pb.NodeRegion{ - Id: int64(region.Id), - IsOn: region.IsOn == 1, - Name: region.Name, + Id: int64(region.Id), + IsOn: region.IsOn == 1, + Name: region.Name, + PricesJSON: []byte(region.Prices), }) } return &pb.FindAllEnabledNodeRegionsResponse{NodeRegions: result}, nil @@ -84,9 +85,10 @@ func (this *NodeRegionService) FindAllEnabledAndOnNodeRegions(ctx context.Contex result := []*pb.NodeRegion{} for _, region := range regions { result = append(result, &pb.NodeRegion{ - Id: int64(region.Id), - IsOn: region.IsOn == 1, - Name: region.Name, + Id: int64(region.Id), + IsOn: region.IsOn == 1, + Name: region.Name, + PricesJSON: []byte(region.Prices), }) } return &pb.FindAllEnabledAndOnNodeRegionsResponse{NodeRegions: result}, nil @@ -119,8 +121,22 @@ func (this *NodeRegionService) FindEnabledNodeRegion(ctx context.Context, req *p return &pb.FindEnabledNodeRegionResponse{NodeRegion: nil}, nil } return &pb.FindEnabledNodeRegionResponse{NodeRegion: &pb.NodeRegion{ - Id: int64(region.Id), - IsOn: region.IsOn == 1, - Name: region.Name, + Id: int64(region.Id), + IsOn: region.IsOn == 1, + Name: region.Name, + PricesJSON: []byte(region.Prices), }}, nil } + +// 修改价格项价格 +func (this *NodeRegionService) UpdateNodeRegionPrice(ctx context.Context, req *pb.UpdateNodeRegionPriceRequest) (*pb.RPCSuccess, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + err = models.SharedNodeRegionDAO.UpdateRegionItemPrice(req.NodeRegionId, req.NodeItemId, req.Price) + if err != nil { + return nil, err + } + return this.Success() +}