完善通道删除与定时失效功能

This commit is contained in:
2025-03-31 09:09:05 +08:00
parent ec4f499edd
commit 47bb49ce70
18 changed files with 832 additions and 619 deletions

View File

@@ -5,8 +5,9 @@ import (
"platform/pkg/env"
"platform/pkg/logs"
"platform/pkg/orm"
"platform/web/models"
m "platform/web/models"
q "platform/web/queries"
"time"
"golang.org/x/crypto/bcrypt"
)
@@ -16,59 +17,96 @@ func main() {
logs.Init()
orm.Init()
q.User.
Select(
q.User.Phone).
Create(&models.User{
Phone: "12312341234"})
err := q.Q.Transaction(func(tx *q.Query) error {
q.User.
Select(q.User.Phone).
Save(&m.User{
Phone: "12312341234",
})
var user, _ = q.User.First()
q.Proxy.
Select(
q.Proxy.Version,
q.Proxy.Name,
q.Proxy.Host,
q.Proxy.Type).
Create(&models.Proxy{
Version: 1,
Name: "7a17e8b4-cdc3-4500-bf16-4a665991a7f6",
Host: "110.40.82.248",
Type: 1})
q.Resource.
Select(q.Resource.UserID, q.Resource.Active).
Create(&m.Resource{
UserID: user.ID,
Active: true,
})
var resource, _ = q.Resource.First()
q.Node.
Select(
q.Node.Version,
q.Node.Name,
q.Node.Host,
q.Node.Isp,
q.Node.Prov,
q.Node.City,
q.Node.Status).
Create(&models.Node{
Version: 1,
Name: "test-node",
Host: "123",
Isp: "test-isp",
Prov: "test-prov",
City: "test-city",
Status: 1})
q.ResourcePss.
Select(
q.ResourcePss.ResourceID,
q.ResourcePss.Live,
q.ResourcePss.Type,
q.ResourcePss.Expire,
q.ResourcePss.DailyLimit,
).
Create(&m.ResourcePss{
ResourceID: resource.ID,
Live: 180,
Type: 1,
Expire: time.Now().Add(24 * time.Hour * 1000),
DailyLimit: 300000,
})
var secret, _ = bcrypt.GenerateFromPassword([]byte("test"), bcrypt.DefaultCost)
q.Client.
Select(
q.Client.ClientID,
q.Client.ClientSecret,
q.Client.GrantClient,
q.Client.GrantRefresh,
q.Client.Spec,
q.Client.Name).
Create(&models.Client{
ClientID: "test",
ClientSecret: string(secret),
GrantClient: true,
GrantRefresh: true,
Spec: 0,
Name: "默认客户端",
})
q.Proxy.
Select(q.Proxy.Version, q.Proxy.Name, q.Proxy.Host, q.Proxy.Type, q.Proxy.Secret).
Create(&m.Proxy{
Version: 1,
Name: "7a17e8b4-cdc3-4500-bf16-4a665991a7f6",
Host: "110.40.82.248",
Type: 1,
Secret: "api:123456",
})
q.Node.
Select(
q.Node.Version,
q.Node.Name,
q.Node.Host,
q.Node.Isp,
q.Node.Prov,
q.Node.City,
q.Node.Status).
Create(&m.Node{
Version: 1,
Name: "test-node",
Host: "123",
Isp: "test-isp",
Prov: "test-prov",
City: "test-city",
Status: 1})
var testSecret, _ = bcrypt.GenerateFromPassword([]byte("test"), bcrypt.DefaultCost)
var tasksSecret, _ = bcrypt.GenerateFromPassword([]byte("tasks"), bcrypt.DefaultCost)
q.Client.
Select(
q.Client.ClientID,
q.Client.ClientSecret,
q.Client.GrantClient,
q.Client.GrantRefresh,
q.Client.Spec,
q.Client.Name).
Create(&m.Client{
ClientID: "test",
ClientSecret: string(testSecret),
GrantClient: true,
GrantRefresh: true,
Spec: 0,
Name: "默认客户端",
}, &m.Client{
ClientID: "tasks",
ClientSecret: string(tasksSecret),
GrantClient: true,
GrantRefresh: true,
Spec: 0,
Name: "异步任务处理服务",
})
return nil
})
if err != nil {
panic(err)
}
slog.Info("✔ Data inserted successfully")
}

View File

@@ -1,33 +1,11 @@
package main
import (
"fmt"
"platform/pkg/env"
"platform/pkg/logs"
"platform/pkg/orm"
"platform/web/models"
q "platform/web/queries"
)
import "math"
type ResourceInfo struct {
data models.Resource
pss models.ResourcePss
}
var b62Set = make(map[string]struct{})
var b64Set = make(map[string]struct{})
func main() {
env.Init()
logs.Init()
orm.Init()
var resource = new(ResourceInfo)
data := q.Resource.As("data")
pss := q.ResourcePss.As("pss")
_ = data.Debug().Scopes(orm.Alias(data)).
Select(data.ALL, pss.ALL).
LeftJoin(q.ResourcePss.As("pss"), pss.ResourceID.EqCol(data.ID)).
Where(data.ID.Eq(1)).
Scan(&resource)
fmt.Printf("%+v\n", resource)
println(int(math.Ceil(100 * 1.1)))
println(int(math.Ceil(float64(100) * 1.1)))
}

View File

@@ -2,12 +2,18 @@ package main
import (
"context"
"encoding/json"
"errors"
"io"
"log/slog"
"net/http"
"platform/pkg/env"
"platform/pkg/logs"
"platform/pkg/orm"
"platform/pkg/rds"
"reflect"
"strconv"
"strings"
"sync"
"time"
"github.com/redis/go-redis/v9"
@@ -17,27 +23,51 @@ func main() {
Start()
}
var taskList = make(map[string]func(ctx context.Context, curr time.Time) error)
func Start() {
ctx := context.Background()
env.Init()
logs.Init()
rds.Init()
orm.Init()
taskList["stopChannels"] = stopChannels
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
// 互斥锁确保同一时间只有一个协程运行
// 如果之前的 tick 操作未完成,则跳过当前 tick
var mutex = &sync.Mutex{}
for curr := range ticker.C {
err := process(ctx, curr)
if err != nil {
panic(err)
if mutex.TryLock() {
err := process(ctx, curr)
if err != nil {
panic(err)
}
mutex.Unlock()
} else {
slog.Warn("skip tick", slog.String("tick", curr.Format("2006-01-02 15:04:05")))
}
}
}
func process(ctx context.Context, curr time.Time) error {
// todo 异步化
for name, task := range taskList {
err := task(ctx, curr)
if err != nil {
slog.Error("task failed", slog.String("task", name), slog.String("error", err.Error()))
}
}
return nil
}
func stopChannels(ctx context.Context, curr time.Time) error {
// 获取并删除
script := redis.NewScript(`
local result = redis.call('ZRANGEBYSCORE', KEYS[1], 0, ARGV[1])
@@ -47,21 +77,64 @@ func process(ctx context.Context, curr time.Time) error {
return result
`)
// 计算时间范围
// 执行脚本
result, err := script.Run(ctx, rds.Client, []string{"tasks:session"}, curr.Unix()).Result()
result, err := script.Run(ctx, rds.Client, []string{"tasks:channel"}, curr.Unix()).Result()
if err != nil {
return err
}
// 处理结果
list, ok := result.([]string)
list, ok := result.([]any)
if !ok {
return errors.New("failed to convert result to []string")
}
for _, item := range list {
// 从数据库删除授权信息
slog.Debug(item)
var ids = make([]int, len(list))
for i, item := range list {
idStr, ok := item.(string)
if !ok {
slog.Debug(reflect.TypeOf(item).String())
return errors.New("failed to convert item to string")
}
id, err := strconv.Atoi(idStr)
if err != nil {
return err
}
ids[i] = id
}
if len(ids) == 0 {
return nil
}
var body = map[string]any{
"by_ids": ids,
}
bodyStr, err := json.Marshal(body)
if err != nil {
return err
}
req, err := http.NewRequest(
http.MethodPost,
"http://localhost:8080/api/channel/remove", // todo 环境变量获取服务地址
strings.NewReader(string(bodyStr)),
)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth("tasks", "tasks")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
return errors.New("failed to stop channels: " + string(body))
}
return nil