2025-11-17 18:38:10 +08:00
|
|
|
package tasks
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"fmt"
|
2025-11-24 18:44:06 +08:00
|
|
|
"log/slog"
|
|
|
|
|
"platform/pkg/env"
|
|
|
|
|
"platform/pkg/u"
|
2025-11-17 18:38:10 +08:00
|
|
|
"platform/web/events"
|
2025-11-24 18:44:06 +08:00
|
|
|
e "platform/web/events"
|
|
|
|
|
g "platform/web/globals"
|
|
|
|
|
m "platform/web/models"
|
2025-12-01 12:43:29 +08:00
|
|
|
q "platform/web/queries"
|
2025-11-17 18:38:10 +08:00
|
|
|
s "platform/web/services"
|
2025-11-24 18:44:06 +08:00
|
|
|
"strings"
|
2025-11-17 18:38:10 +08:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/hibiken/asynq"
|
2025-12-01 12:43:29 +08:00
|
|
|
"gorm.io/datatypes"
|
2025-11-17 18:38:10 +08:00
|
|
|
)
|
|
|
|
|
|
2025-11-28 19:00:34 +08:00
|
|
|
func HandleCompleteTrade(_ context.Context, task *asynq.Task) (err error) {
|
|
|
|
|
event := new(events.CompleteTradeData)
|
|
|
|
|
err = json.Unmarshal(task.Payload(), event)
|
2025-11-17 18:38:10 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("解析任务参数失败: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-28 19:00:34 +08:00
|
|
|
data := &s.ModifyTradeData{
|
|
|
|
|
TradeNo: event.TradeNo,
|
|
|
|
|
Method: event.Method,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = s.Trade.CompleteTrade(data)
|
2025-11-17 18:38:10 +08:00
|
|
|
if err != nil {
|
2025-11-28 19:00:34 +08:00
|
|
|
slog.Debug("完成交易失败[异步结束订单]", "err", err)
|
|
|
|
|
err = s.Trade.CancelTrade(data, time.Now())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("取消交易失败[异步结束订单]: %w", err)
|
|
|
|
|
}
|
2025-11-17 18:38:10 +08:00
|
|
|
}
|
2025-11-28 19:00:34 +08:00
|
|
|
|
2025-11-17 18:38:10 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func HandleRemoveChannel(_ context.Context, task *asynq.Task) (err error) {
|
2025-11-24 18:44:06 +08:00
|
|
|
data := new(e.RemoveChannelData)
|
|
|
|
|
err = json.Unmarshal(task.Payload(), data)
|
2025-11-17 18:38:10 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("解析任务参数失败: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-24 18:44:06 +08:00
|
|
|
err = s.Channel.RemoveChannels(data.Batch, data.IDs)
|
2025-11-17 18:38:10 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("删除通道失败: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2025-11-24 18:44:06 +08:00
|
|
|
|
2025-12-03 15:04:48 +08:00
|
|
|
func HandleFlushGateway(_ context.Context, task *asynq.Task) error {
|
2025-12-01 12:43:29 +08:00
|
|
|
start := time.Now()
|
2025-12-03 15:04:48 +08:00
|
|
|
defer func() {
|
|
|
|
|
duration := time.Since(start)
|
|
|
|
|
if duration > time.Second {
|
|
|
|
|
slog.Warn("更新代理后备配置耗时过长", "time", duration.String())
|
|
|
|
|
}
|
|
|
|
|
}()
|
2025-11-24 18:44:06 +08:00
|
|
|
|
|
|
|
|
// 获取所有网关:配置组
|
|
|
|
|
proxies, err := s.Proxy.AllProxies(m.ProxyTypeBaiYin, true)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("获取网关失败: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, proxy := range proxies {
|
|
|
|
|
|
|
|
|
|
// 获取当前后备配置
|
|
|
|
|
locals := map[string]int{}
|
|
|
|
|
for _, channel := range proxy.Channels {
|
|
|
|
|
isp := channel.FilterISP.String()
|
|
|
|
|
prov := u.Z(channel.FilterProv)
|
|
|
|
|
city := u.Z(channel.FilterCity)
|
|
|
|
|
locals[fmt.Sprintf("%s:%s:%s", isp, prov, city)]++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取之前的后备配置
|
|
|
|
|
remotes := map[string]int{}
|
|
|
|
|
if proxy.Meta != nil {
|
2025-12-03 15:04:48 +08:00
|
|
|
meta, ok := proxy.Meta.Data().([]any)
|
2025-11-24 18:44:06 +08:00
|
|
|
if !ok {
|
2025-12-03 15:04:48 +08:00
|
|
|
return fmt.Errorf("解析网关数据失败: %T", proxy.Meta.Data())
|
2025-11-24 18:44:06 +08:00
|
|
|
}
|
2025-12-03 15:04:48 +08:00
|
|
|
for _, rawM := range meta {
|
|
|
|
|
m, ok := rawM.(map[string]any)
|
|
|
|
|
if !ok {
|
|
|
|
|
return fmt.Errorf("解析网关数据失败: %T", rawM)
|
|
|
|
|
}
|
|
|
|
|
remotes[fmt.Sprintf("%s:%s:%s", m["isp"], m["province"], m["city"])] = int(m["count"].(float64))
|
2025-11-24 18:44:06 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否需要更新
|
|
|
|
|
pass := true
|
|
|
|
|
for k, local := range locals {
|
|
|
|
|
remote, ok := remotes[k]
|
|
|
|
|
if !ok {
|
|
|
|
|
pass = false
|
|
|
|
|
} else {
|
|
|
|
|
local, remote := float64(local), float64(remote)
|
|
|
|
|
if remote < local*1.5 || remote > local*3 {
|
|
|
|
|
pass = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if pass {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新后备配置
|
|
|
|
|
configs := make([]g.AutoConfig, 0)
|
|
|
|
|
for k, local := range locals {
|
|
|
|
|
arr := strings.Split(k, ":")
|
|
|
|
|
isp, prov, city := arr[0], arr[1], arr[2]
|
|
|
|
|
configs = append(configs, g.AutoConfig{
|
|
|
|
|
Isp: isp,
|
|
|
|
|
Province: prov,
|
|
|
|
|
City: city,
|
|
|
|
|
Count: local * 2,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if env.DebugExternalChange {
|
2025-12-01 12:43:29 +08:00
|
|
|
err := g.Cloud.CloudConnect(g.CloudConnectReq{
|
2025-11-24 18:44:06 +08:00
|
|
|
Uuid: proxy.Mac,
|
|
|
|
|
AutoConfig: configs,
|
|
|
|
|
})
|
2025-12-01 12:43:29 +08:00
|
|
|
if err != nil {
|
|
|
|
|
slog.Error("提交代理后备配置失败", "error", err)
|
|
|
|
|
}
|
2025-11-24 18:44:06 +08:00
|
|
|
} else {
|
|
|
|
|
bytes, _ := json.Marshal(configs)
|
2025-12-04 09:45:35 +08:00
|
|
|
slog.Debug("更新代理后备配置", "proxy", proxy.IP.String(), "config", string(bytes))
|
2025-11-24 18:44:06 +08:00
|
|
|
}
|
2025-12-01 12:43:29 +08:00
|
|
|
|
|
|
|
|
_, err := q.Proxy.
|
|
|
|
|
Where(q.Proxy.ID.Eq(proxy.ID)).
|
|
|
|
|
UpdateSimple(q.Proxy.Meta.Value(datatypes.NewJSONType(configs)))
|
|
|
|
|
if err != nil {
|
|
|
|
|
slog.Error("更新代理后备配置失败", "error", err)
|
|
|
|
|
}
|
2025-11-24 18:44:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|