86 lines
1.9 KiB
Go
86 lines
1.9 KiB
Go
package services
|
||
|
||
import (
|
||
"context"
|
||
"platform/pkg/orm"
|
||
"platform/web/models"
|
||
)
|
||
|
||
type NodeServiceErr string
|
||
|
||
func (e NodeServiceErr) Error() string {
|
||
return string(e)
|
||
}
|
||
|
||
var Node = &nodeService{}
|
||
|
||
type nodeService struct{}
|
||
|
||
func (s *nodeService) Filter(ctx context.Context, userId int32, count int, config ...NodeFilterConfig) ([]*models.Node, error) {
|
||
_config := NodeFilterConfig{}
|
||
if len(config) > 0 {
|
||
_config = config[0]
|
||
}
|
||
|
||
// 筛选符合条件且未分配给用户过的节点
|
||
// 静态条件:省,市,运营商
|
||
// 排序方式,1.分配给该用户的次数 2.分配给全部用户的次数 3.todo 节点的健康状态
|
||
var nodes []*FilteredNode
|
||
orm.DB.Raw(filterSqlRaw, userId, _config.Isp, _config.Prov, _config.City).
|
||
Limit(count).
|
||
Find(&nodes)
|
||
|
||
// todo 异步任务关闭代理
|
||
|
||
// todo 异步任务缩容
|
||
|
||
return nil, nil
|
||
}
|
||
|
||
type NodeFilterConfig struct {
|
||
Isp string `json:"isp"`
|
||
Prov string `json:"prov"`
|
||
City string `json:"city"`
|
||
}
|
||
|
||
type NodeFilterAsyncTask struct {
|
||
Config NodeFilterConfig `json:"config"`
|
||
Count int `json:"count"`
|
||
}
|
||
|
||
// 筛选节点的SQL语句,暂时用不到
|
||
// 筛选已连接的符合条件且未分配给用户过的节点
|
||
//
|
||
// 静态条件:省,市,运营商
|
||
// 排序方式,1.分配给该用户的次数 2.分配给全部用户的次数
|
||
const filterSqlRaw = `
|
||
select
|
||
n.id as id,
|
||
n.name as name,
|
||
n.host as host,
|
||
n.fwd_port as fwd_port,
|
||
count(c.*) as total,
|
||
count(c.*) filter ( where c.user_id = ? ) as assigned
|
||
from
|
||
node n
|
||
left join public.channel c
|
||
on n.id = c.node_id and c.expiration > now() and c.deleted_at is null
|
||
where
|
||
n.isp = ? and
|
||
n.prov = ? and
|
||
n.city = ?
|
||
group by
|
||
n.id
|
||
order by
|
||
assigned, total
|
||
`
|
||
|
||
type FilteredNode struct {
|
||
Id int32 `json:"id"`
|
||
Name string `json:"name"`
|
||
Host string `json:"host"`
|
||
FwdPort int32 `json:"fwd_port"`
|
||
Total int32 `json:"total"`
|
||
Assigned int32 `json:"assigned"`
|
||
}
|