修复套餐创建事务回滚失败问题;修复 http dump 未根据环境配置打印问题;简化通道分配时计时输出
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
## todo
|
## todo
|
||||||
|
|
||||||
- channel 接口
|
|
||||||
- 待验证
|
|
||||||
- 长效业务接入
|
- 长效业务接入
|
||||||
- 微信支付
|
- 微信支付
|
||||||
- 页面 账户总览
|
- 页面 账户总览
|
||||||
@@ -10,6 +8,7 @@
|
|||||||
- 代理数据表的 secret 字段 aes 加密存储
|
- 代理数据表的 secret 字段 aes 加密存储
|
||||||
|
|
||||||
- globals 合并到 services 或者反之
|
- globals 合并到 services 或者反之
|
||||||
|
- 自定义的服务错误没有必要,可以统一在 handler 层使用包装的 fiber.Error
|
||||||
|
|
||||||
### 下阶段
|
### 下阶段
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ func Init() {
|
|||||||
env.DbHost, env.DbUserName, env.DbPassword, env.DbName, env.DbPort,
|
env.DbHost, env.DbUserName, env.DbPassword, env.DbName, env.DbPort,
|
||||||
)
|
)
|
||||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||||
|
TranslateError: true,
|
||||||
NamingStrategy: schema.NamingStrategy{
|
NamingStrategy: schema.NamingStrategy{
|
||||||
SingularTable: true,
|
SingularTable: true,
|
||||||
},
|
},
|
||||||
|
|||||||
24
web/error.go
24
web/error.go
@@ -2,6 +2,7 @@ package web
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"gorm.io/gorm"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"platform/web/core"
|
"platform/web/core"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -11,20 +12,29 @@ import (
|
|||||||
|
|
||||||
func ErrorHandler(c *fiber.Ctx, err error) error {
|
func ErrorHandler(c *fiber.Ctx, err error) error {
|
||||||
|
|
||||||
var code int
|
var code = fiber.StatusInternalServerError
|
||||||
var message string
|
var message = "服务器异常"
|
||||||
|
|
||||||
var fiberErr *fiber.Error
|
var fiberErr *fiber.Error
|
||||||
var serviceErr *core.ServiceErr
|
var serviceErr *core.ServiceErr
|
||||||
if errors.As(err, &fiberErr) {
|
|
||||||
|
switch {
|
||||||
|
|
||||||
|
// fiber 错误
|
||||||
|
case errors.As(err, &fiberErr):
|
||||||
code = fiberErr.Code
|
code = fiberErr.Code
|
||||||
message = fiberErr.Message
|
message = fiberErr.Message
|
||||||
} else if errors.As(err, &serviceErr) {
|
|
||||||
|
// 服务错误
|
||||||
|
case errors.As(err, &serviceErr):
|
||||||
code = serviceErr.Code()
|
code = serviceErr.Code()
|
||||||
message = serviceErr.Error()
|
message = serviceErr.Error()
|
||||||
} else {
|
|
||||||
code = fiber.StatusInternalServerError
|
// gorm 错误,忽略
|
||||||
message = "服务器异常"
|
case errors.Is(err, gorm.ErrForeignKeyViolated):
|
||||||
|
|
||||||
|
// 所有未手动声明的错误类型
|
||||||
|
default:
|
||||||
slog.Debug("未处理的异常", slog.String("type", reflect.TypeOf(err).Name()), slog.String("error", err.Error()))
|
slog.Debug("未处理的异常", slog.String("type", reflect.TypeOf(err).Name()), slog.String("error", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -319,11 +319,13 @@ func (c *cloud) token(refresh bool) (string, error) {
|
|||||||
_ = Body.Close()
|
_ = Body.Close()
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
dump, err := httputil.DumpResponse(resp, true)
|
if env.DebugHttpDump {
|
||||||
if err != nil {
|
dump, err := httputil.DumpResponse(resp, true)
|
||||||
return "", err
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
fmt.Println(string(dump))
|
||||||
}
|
}
|
||||||
fmt.Println(string(dump))
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return "", errors.New("failed to get token")
|
return "", errors.New("failed to get token")
|
||||||
|
|||||||
@@ -239,19 +239,19 @@ func (s *channelService) CreateChannel(
|
|||||||
err = q.Q.Transaction(func(q *q.Query) (err error) {
|
err = q.Q.Transaction(func(q *q.Query) (err error) {
|
||||||
|
|
||||||
// 查找套餐
|
// 查找套餐
|
||||||
resource, err := findResource(q, rid, resourceId, authCtx, count)
|
resource, err := findResource(q, resourceId, authCtx, count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找网关
|
// 查找网关
|
||||||
proxies, err := findProxies(q, rid)
|
proxies, err := findProxies(q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找已使用的节点
|
// 查找已使用的节点
|
||||||
channels, err := findChannels(q, rid, proxies)
|
channels, err := findChannels(q, proxies)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -259,7 +259,7 @@ func (s *channelService) CreateChannel(
|
|||||||
// 查找白名单
|
// 查找白名单
|
||||||
var whitelist *[]string
|
var whitelist *[]string
|
||||||
if authType == ChannelAuthTypeIp {
|
if authType == ChannelAuthTypeIp {
|
||||||
whitelist, err = findWhitelist(q, rid, authCtx.Payload.Id)
|
whitelist, err = findWhitelist(q, authCtx.Payload.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -299,10 +299,7 @@ func (s *channelService) CreateChannel(
|
|||||||
return newChannels, nil
|
return newChannels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findResource(q *q.Query, rid string, resourceId int32, authCtx *auth.Context, count int) (*ResourceInfo, error) {
|
func findResource(q *q.Query, resourceId int32, authCtx *auth.Context, count int) (*ResourceInfo, error) {
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
// 查找套餐
|
|
||||||
var resource = new(ResourceInfo)
|
var resource = new(ResourceInfo)
|
||||||
data := q.Resource.As("data")
|
data := q.Resource.As("data")
|
||||||
pss := q.ResourcePss.As("pss")
|
pss := q.ResourcePss.As("pss")
|
||||||
@@ -348,13 +345,10 @@ func findResource(q *q.Query, rid string, resourceId int32, authCtx *auth.Contex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("查找套餐", "rid", rid, "step", time.Since(step))
|
|
||||||
return resource, nil
|
return resource, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findProxies(q *q.Query, rid string) (proxies []*m.Proxy, err error) {
|
func findProxies(q *q.Query) (proxies []*m.Proxy, err error) {
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
proxies, err = q.Proxy.
|
proxies, err = q.Proxy.
|
||||||
Where(q.Proxy.Type.Eq(1)).
|
Where(q.Proxy.Type.Eq(1)).
|
||||||
Find()
|
Find()
|
||||||
@@ -362,18 +356,15 @@ func findProxies(q *q.Query, rid string) (proxies []*m.Proxy, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("查找网关", "rid", rid, "step", time.Since(step))
|
|
||||||
return proxies, nil
|
return proxies, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findChannels(q *q.Query, rid string, proxies []*m.Proxy) (channels []*m.Channel, err error) {
|
func findChannels(q *q.Query, proxies []*m.Proxy) (channels []*m.Channel, err error) {
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
var proxyIds = make([]int32, len(proxies))
|
var proxyIds = make([]int32, len(proxies))
|
||||||
for i, proxy := range proxies {
|
for i, proxy := range proxies {
|
||||||
proxyIds[i] = proxy.ID
|
proxyIds[i] = proxy.ID
|
||||||
}
|
}
|
||||||
channels, err = q.Channel.Debug().
|
channels, err = q.Channel.
|
||||||
Select(
|
Select(
|
||||||
q.Channel.ProxyID,
|
q.Channel.ProxyID,
|
||||||
q.Channel.ProxyPort).
|
q.Channel.ProxyPort).
|
||||||
@@ -388,14 +379,10 @@ func findChannels(q *q.Query, rid string, proxies []*m.Proxy) (channels []*m.Cha
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("查找已使用节点", "rid", rid, "step", time.Since(step))
|
|
||||||
return channels, nil
|
return channels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findWhitelist(q *q.Query, rid string, userId int32) (*[]string, error) {
|
func findWhitelist(q *q.Query, userId int32) (*[]string, error) {
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
// 按需查找用户白名单
|
|
||||||
var whitelist []string
|
var whitelist []string
|
||||||
err := q.Whitelist.
|
err := q.Whitelist.
|
||||||
Where(q.Whitelist.UserID.Eq(userId)).
|
Where(q.Whitelist.UserID.Eq(userId)).
|
||||||
@@ -408,7 +395,6 @@ func findWhitelist(q *q.Query, rid string, userId int32) (*[]string, error) {
|
|||||||
return nil, ChannelServiceErr("用户没有白名单")
|
return nil, ChannelServiceErr("用户没有白名单")
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("查找用户白名单", "rid", rid, "step", time.Since(step))
|
|
||||||
return &whitelist, nil
|
return &whitelist, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,13 +576,11 @@ func calcChannels(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("申请节点", "rid", step, "total", time.Since(step))
|
slog.Debug("申请节点", "total", time.Since(step))
|
||||||
return newChannels, nil
|
return newChannels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateResource(rid string, resource *ResourceInfo, count int, now time.Time) (err error) {
|
func updateResource(rid string, resource *ResourceInfo, count int, now time.Time) (err error) {
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
toUpdate := m.ResourcePss{
|
toUpdate := m.ResourcePss{
|
||||||
Used: resource.Used + int32(count),
|
Used: resource.Used + int32(count),
|
||||||
DailyLast: core.LocalDateTime(now),
|
DailyLast: core.LocalDateTime(now),
|
||||||
@@ -619,14 +603,10 @@ func updateResource(rid string, resource *ResourceInfo, count int, now time.Time
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("更新套餐使用记录", "rid", rid, "step", time.Since(step))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveChannels(channels []*m.Channel) (err error) {
|
func saveChannels(channels []*m.Channel) (err error) {
|
||||||
// 保存到数据库
|
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
err = q.Channel.
|
err = q.Channel.
|
||||||
Omit(
|
Omit(
|
||||||
q.Channel.NodeID,
|
q.Channel.NodeID,
|
||||||
@@ -638,19 +618,15 @@ func saveChannels(channels []*m.Channel) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("保存到数据库", "step", time.Since(step))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cacheChannels(ctx context.Context, rid string, channels []*m.Channel) (err error) {
|
func cacheChannels(ctx context.Context, rid string, channels []*m.Channel) (err error) {
|
||||||
var step = time.Now()
|
|
||||||
|
|
||||||
err = cache(ctx, channels)
|
err = cache(ctx, channels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("缓存通道数据", "rid", rid, "step", time.Since(step))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ func (s *resourceService) CompleteResource(ctx context.Context, tradeNo string,
|
|||||||
err = q.Q.Transaction(func(q *q.Query) error {
|
err = q.Q.Transaction(func(q *q.Query) error {
|
||||||
|
|
||||||
// 保存套餐
|
// 保存套餐
|
||||||
resource, err := createResource(&cache.CreateResourceData, cache.Uid)
|
resource, err := createResource(q, &cache.CreateResourceData, cache.Uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ func (s *resourceService) CreateResource(data *CreateResourceData, uid int32) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存套餐
|
// 保存套餐
|
||||||
resource, err := createResource(data, uid)
|
resource, err := createResource(q, data, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ type CreateResourceCache struct {
|
|||||||
BillId int32 `json:"bill_id"`
|
BillId int32 `json:"bill_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createResource(data *CreateResourceData, uid int32) (*m.Resource, error) {
|
func createResource(q *q.Query, data *CreateResourceData, uid int32) (*m.Resource, error) {
|
||||||
|
|
||||||
// 创建套餐
|
// 创建套餐
|
||||||
resource := m.Resource{
|
resource := m.Resource{
|
||||||
|
|||||||
@@ -110,9 +110,10 @@ func useRequestId() fiber.Handler {
|
|||||||
|
|
||||||
func useLogger() fiber.Handler {
|
func useLogger() fiber.Handler {
|
||||||
return logger.New(logger.Config{
|
return logger.New(logger.Config{
|
||||||
Format: "🚀 ${time} | ${locals:authtype} ${locals:authid} | ${method} ${path} | ${status} | ${latency} | ${error}\n",
|
DisableColors: true,
|
||||||
TimeFormat: "2006-01-02 15:04:05",
|
Format: "🚀 ${time} | ${locals:authtype} ${locals:authid} | ${method} ${path} | ${status} | ${latency} | ${error}\n",
|
||||||
TimeZone: "Asia/Shanghai",
|
TimeFormat: "2006-01-02 15:04:05",
|
||||||
|
TimeZone: "Asia/Shanghai",
|
||||||
Done: func(c *fiber.Ctx, logBytes []byte) {
|
Done: func(c *fiber.Ctx, logBytes []byte) {
|
||||||
var logStr = strings.TrimPrefix(string(logBytes), "🚀")
|
var logStr = strings.TrimPrefix(string(logBytes), "🚀")
|
||||||
var logVars = strings.Split(logStr, "|")
|
var logVars = strings.Split(logStr, "|")
|
||||||
|
|||||||
Reference in New Issue
Block a user