Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a9045ba44 | ||
|
|
bc7ee19962 | ||
|
|
2484cd4ae6 | ||
|
|
57b8a96c6d | ||
|
|
6c8ab7cb94 | ||
|
|
b2c2bd247b | ||
|
|
29d9e6db81 | ||
|
|
24fcb48c75 | ||
|
|
4911198fe7 | ||
|
|
c2af796992 | ||
|
|
51c8572e53 | ||
|
|
c15cc6d75c | ||
|
|
c0a99a4ba3 | ||
|
|
62e26bed5a | ||
|
|
9e68a2915c | ||
|
|
5b809fda1f | ||
|
|
88b782940a | ||
|
|
85c596644d | ||
|
|
ffa2d884bd | ||
|
|
813ed18610 | ||
|
|
564b11eae7 | ||
|
|
d2af0307b9 | ||
|
|
4fa6b03238 | ||
|
|
4bda78aa8c | ||
|
|
6002cc96d9 | ||
|
|
56c09f5be7 | ||
|
|
e1fb8e4c74 | ||
|
|
14f055ce7c | ||
|
|
7b7f2b0a00 |
@@ -1,76 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function build() {
|
||||
ROOT=$(dirname $0)
|
||||
ROOT=$(dirname "$0")
|
||||
NAME="edge-api"
|
||||
DIST=$ROOT/"../dist/${NAME}"
|
||||
OS=${1}
|
||||
ARCH=${2}
|
||||
TAG=${3}
|
||||
NODE_ARCHITECTS=("amd64" "386" "arm64" "mips64" "mips64le")
|
||||
NODE_ARCHITECTS=("amd64" "arm64")
|
||||
|
||||
if [ -z $OS ]; then
|
||||
if [ -z "$OS" ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $ARCH ]; then
|
||||
if [ -z "$ARCH" ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $TAG ]; then
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="community"
|
||||
fi
|
||||
|
||||
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
|
||||
VERSION=$(lookup-version "$ROOT"/../internal/const/const.go)
|
||||
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
|
||||
|
||||
# build edge-node
|
||||
NodeVersion=$(lookup-version $ROOT"/../../EdgeNode/internal/const/const.go")
|
||||
NodeVersion=$(lookup-version "$ROOT""/../../EdgeNode/internal/const/const.go")
|
||||
echo "building edge-node v${NodeVersion} ..."
|
||||
EDGE_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeNode/build/build.sh"
|
||||
if [ ! -f $EDGE_NODE_BUILD_SCRIPT ]; then
|
||||
if [ ! -f "$EDGE_NODE_BUILD_SCRIPT" ]; then
|
||||
echo "unable to find edge-node build script 'EdgeNode/build/build.sh'"
|
||||
exit
|
||||
fi
|
||||
cd $ROOT"/../../EdgeNode/build"
|
||||
cd "$ROOT""/../../EdgeNode/build" || exit
|
||||
echo "=============================="
|
||||
for arch in "${NODE_ARCHITECTS[@]}"; do
|
||||
if [ ! -f $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
|
||||
./build.sh linux $arch $TAG
|
||||
if [ ! -f "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
|
||||
./build.sh linux "$arch" $TAG
|
||||
else
|
||||
echo "use built node linux/$arch/v${NodeVersion}"
|
||||
fi
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
cd - || exit
|
||||
|
||||
rm -f $ROOT/deploy/*.zip
|
||||
rm -f "$ROOT"/deploy/*.zip
|
||||
for arch in "${NODE_ARCHITECTS[@]}"; do
|
||||
cp $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" $ROOT/deploy/edge-node-linux-${arch}-v${NodeVersion}.zip
|
||||
cp "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" "$ROOT"/deploy/edge-node-linux-"${arch}"-v"${NodeVersion}".zip
|
||||
done
|
||||
|
||||
# build edge-dns
|
||||
if [ "$TAG" = "plus" ]; then
|
||||
DNS_ROOT=$ROOT"/../../EdgeDNS"
|
||||
if [ -d $DNS_ROOT ]; then
|
||||
DNSNodeVersion=$(lookup-version $ROOT"/../../EdgeDNS/internal/const/const.go")
|
||||
if [ -d "$DNS_ROOT" ]; then
|
||||
DNSNodeVersion=$(lookup-version "$ROOT""/../../EdgeDNS/internal/const/const.go")
|
||||
echo "building edge-dns ${DNSNodeVersion} ..."
|
||||
EDGE_DNS_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeDNS/build/build.sh"
|
||||
if [ ! -f $EDGE_DNS_NODE_BUILD_SCRIPT ]; then
|
||||
if [ ! -f "$EDGE_DNS_NODE_BUILD_SCRIPT" ]; then
|
||||
echo "unable to find edge-dns build script 'EdgeDNS/build/build.sh'"
|
||||
exit
|
||||
fi
|
||||
cd $ROOT"/../../EdgeDNS/build"
|
||||
cd "$ROOT""/../../EdgeDNS/build" || exit
|
||||
echo "=============================="
|
||||
architects=("amd64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
./build.sh linux $arch $TAG
|
||||
./build.sh linux "$arch" $TAG
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
cd - || exit
|
||||
|
||||
for arch in "${architects[@]}"; do
|
||||
cp $ROOT"/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" $ROOT/deploy/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip
|
||||
cp "$ROOT""/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" "$ROOT"/deploy/edge-dns-linux-"${arch}"-v"${DNSNodeVersion}".zip
|
||||
done
|
||||
fi
|
||||
fi
|
||||
@@ -78,48 +78,48 @@ function build() {
|
||||
# build sql
|
||||
if [ $TAG = "plus" ]; then
|
||||
echo "building sql ..."
|
||||
${ROOT}/sql.sh
|
||||
"${ROOT}"/sql.sh
|
||||
fi
|
||||
|
||||
# copy files
|
||||
echo "copying ..."
|
||||
if [ ! -d $DIST ]; then
|
||||
mkdir $DIST
|
||||
mkdir $DIST/bin
|
||||
mkdir $DIST/configs
|
||||
mkdir $DIST/logs
|
||||
if [ ! -d "$DIST" ]; then
|
||||
mkdir "$DIST"
|
||||
mkdir "$DIST"/bin
|
||||
mkdir "$DIST"/configs
|
||||
mkdir "$DIST"/logs
|
||||
fi
|
||||
cp $ROOT/configs/api.template.yaml $DIST/configs/
|
||||
cp $ROOT/configs/db.template.yaml $DIST/configs/
|
||||
cp -R $ROOT/deploy $DIST/
|
||||
rm -f $dist/deploy/.gitignore
|
||||
cp -R $ROOT/installers $DIST/
|
||||
cp -R $ROOT/resources $DIST/
|
||||
rm -f $DIST/resources/ipdata/ip2region/global_region.csv
|
||||
rm -f $DIST/resources/ipdata/ip2region/ip.merge.txt
|
||||
cp "$ROOT"/configs/api.template.yaml "$DIST"/configs/
|
||||
cp "$ROOT"/configs/db.template.yaml "$DIST"/configs/
|
||||
cp -R "$ROOT"/deploy "$DIST/"
|
||||
rm -f "$DIST"/deploy/.gitignore
|
||||
cp -R "$ROOT"/installers "$DIST"/
|
||||
cp -R "$ROOT"/resources "$DIST"/
|
||||
rm -f "$DIST"/resources/ipdata/ip2region/global_region.csv
|
||||
rm -f "$DIST"/resources/ipdata/ip2region/ip.merge.txt
|
||||
|
||||
# building edge installer
|
||||
echo "building node installer ..."
|
||||
architects=("amd64" "386" "arm64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-helper-linux-${arch} $ROOT/../cmd/installer-helper/main.go
|
||||
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-helper-linux-"${arch}" "$ROOT"/../cmd/installer-helper/main.go
|
||||
done
|
||||
|
||||
# building edge dns installer
|
||||
echo "building dns node installer ..."
|
||||
architects=("amd64" "386" "arm64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-dns-helper-linux-${arch} $ROOT/../cmd/installer-dns-helper/main.go
|
||||
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-dns-helper-linux-"${arch}" "$ROOT"/../cmd/installer-dns-helper/main.go
|
||||
done
|
||||
|
||||
# building api node
|
||||
env GOOS=$OS GOARCH=$ARCH go build -tags $TAG --ldflags="-s -w" -o $DIST/bin/edge-api $ROOT/../cmd/edge-api/main.go
|
||||
env GOOS="$OS" GOARCH="$ARCH" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$DIST"/bin/edge-api "$ROOT"/../cmd/edge-api/main.go
|
||||
|
||||
# delete hidden files
|
||||
find $DIST -name ".DS_Store" -delete
|
||||
find $DIST -name ".gitignore" -delete
|
||||
find "$DIST" -name ".DS_Store" -delete
|
||||
find "$DIST" -name ".gitignore" -delete
|
||||
|
||||
echo "zip files"
|
||||
cd "${DIST}/../" || exit
|
||||
@@ -135,15 +135,15 @@ function build() {
|
||||
|
||||
function lookup-version() {
|
||||
FILE=$1
|
||||
VERSION_DATA=$(cat $FILE)
|
||||
VERSION_DATA=$(cat "$FILE")
|
||||
re="Version[ ]+=[ ]+\"([0-9.]+)\""
|
||||
if [[ $VERSION_DATA =~ $re ]]; then
|
||||
VERSION=${BASH_REMATCH[1]}
|
||||
echo $VERSION
|
||||
echo "$VERSION"
|
||||
else
|
||||
echo "could not match version"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
build $1 $2 $3
|
||||
build "$1" "$2" "$3"
|
||||
|
||||
3
dist/.gitignore
vendored
3
dist/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
*.zip
|
||||
*.zip
|
||||
edge-api
|
||||
25
go.mod
25
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/TeaOSLab/EdgeAPI
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||
|
||||
@@ -14,7 +14,6 @@ require (
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
@@ -24,3 +23,25 @@ require (
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
)
|
||||
|
||||
6
go.sum
6
go.sum
@@ -66,7 +66,6 @@ github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7F
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -238,10 +237,6 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d h1:e8fkTKras/RXQWECApM9fKlFWujjYjEClpshkmZmtYg=
|
||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c h1:ugjYZ74FJGWlfDKKraNgMyDTeS4vbXHe89JGUVQIJMo=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570 h1:zqz2FiMMkSHXWO1EsTRJDPTwX9xQ4uuyD5GAE4JGlhM=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||
@@ -561,7 +556,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.4.8"
|
||||
Version = "0.4.9"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,13 +18,13 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.4.8.1"
|
||||
UserNodeVersion = "0.3.4"
|
||||
NodeVersion = "0.4.9"
|
||||
UserNodeVersion = "0.3.5"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.4"
|
||||
DNSNodeVersion = "0.2.3"
|
||||
DNSNodeVersion = "0.2.4"
|
||||
ReportNodeVersion = "0.1.1"
|
||||
|
||||
// SQLVersion SQL版本号
|
||||
SQLVersion = "11"
|
||||
SQLVersion = "2"
|
||||
)
|
||||
|
||||
@@ -58,15 +58,22 @@ func (this *APINodeDAO) EnableAPINode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableAPINode 禁用条目
|
||||
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
||||
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", APINodeStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
|
||||
err = this.NotifyUpdate(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleAPI, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledAPINode 查找启用中的条目
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/encrypt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -49,12 +50,17 @@ func (this *DBNodeDAO) EnableDBNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableDBNode 禁用条目
|
||||
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", DBNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleDatabase, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledDBNode 查找启用中的条目
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -33,7 +34,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableFile 启用条目
|
||||
func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -42,7 +43,7 @@ func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableFile 禁用条目
|
||||
func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -51,7 +52,7 @@ func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledFile 查找启用中的条目
|
||||
func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -63,9 +64,9 @@ func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
|
||||
return result.(*File), err
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
// CreateFile 创建文件
|
||||
func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, businessType, description string, filename string, size int64, isPublic bool) (int64, error) {
|
||||
op := NewFileOperator()
|
||||
var op = NewFileOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.Type = businessType
|
||||
@@ -74,6 +75,7 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
|
||||
op.Size = size
|
||||
op.Filename = filename
|
||||
op.IsPublic = isPublic
|
||||
op.Code = utils.Sha1RandomString()
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -82,7 +84,7 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 将文件置为已完成
|
||||
// UpdateFileIsFinished 将文件置为已完成
|
||||
func (this *FileDAO) UpdateFileIsFinished(tx *dbs.Tx, fileId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(fileId).
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package models
|
||||
|
||||
// 文件管理
|
||||
// File 文件管理
|
||||
type File struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Code string `field:"code"` // 代号
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Description string `field:"description"` // 文件描述
|
||||
Filename string `field:"filename"` // 文件名
|
||||
@@ -19,6 +20,7 @@ type File struct {
|
||||
type FileOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
Code interface{} // 代号
|
||||
UserId interface{} // 用户ID
|
||||
Description interface{} // 文件描述
|
||||
Filename interface{} // 文件名
|
||||
|
||||
@@ -207,14 +207,35 @@ func (this *IPItemDAO) FindEnabledIPItem(tx *dbs.Tx, id int64) (*IPItem, error)
|
||||
|
||||
// DeleteOldItem 根据IP删除以前的旧记录
|
||||
func (this *IPItemDAO) DeleteOldItem(tx *dbs.Tx, listId int64, ipFrom string, ipTo string) error {
|
||||
_, err := this.Query(tx).
|
||||
ones, err := this.Query(tx).
|
||||
ResultPk().
|
||||
UseIndex("ipFrom").
|
||||
Attr("listId", listId).
|
||||
Attr("ipFrom", ipFrom).
|
||||
Attr("ipTo", ipTo).
|
||||
Delete()
|
||||
// 这里不通知更新
|
||||
return err
|
||||
Set("state", IPItemStateEnabled).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var itemId = int64(one.(*IPItem).Id)
|
||||
version, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(itemId).
|
||||
Set("version", version).
|
||||
Set("state", IPItemStateDisabled).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateIPItem 创建IP
|
||||
@@ -267,6 +288,8 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
op.State = IPItemStateEnabled
|
||||
op.UpdatedAt = time.Now().Unix()
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
||||
@@ -691,7 +691,6 @@ func (this *MetricStatDAO) Clean(tx *dbs.Tx) error {
|
||||
Table(table).
|
||||
Attr("itemId", item.Id).
|
||||
Lte("createdDay", expiresDay).
|
||||
UseIndex("createdDay").
|
||||
Limit(10_000). // 一次性不要删除太多,防止阻塞其他操作
|
||||
Delete()
|
||||
return err
|
||||
|
||||
@@ -237,7 +237,6 @@ func (this *MetricSumStatDAO) Clean(tx *dbs.Tx) error {
|
||||
Attr("itemId", item.Id).
|
||||
Where("(createdDay IS NULL OR createdDay<:day)").
|
||||
Param("day", expiresDay).
|
||||
UseIndex("createdDay").
|
||||
Limit(10_000). // 一次性不要删除太多,防止阻塞其他操作
|
||||
Delete()
|
||||
return err
|
||||
|
||||
@@ -47,12 +47,17 @@ func (this *MonitorNodeDAO) EnableMonitorNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableMonitorNode 禁用条目
|
||||
func (this *MonitorNodeDAO) DisableMonitorNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *MonitorNodeDAO) DisableMonitorNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", MonitorNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleMonitor, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledMonitorNode 查找启用中的条目
|
||||
|
||||
@@ -214,7 +214,7 @@ func (this *NSRouteDAO) FindAllEnabledRoutes(tx *dbs.Tx, clusterId int64, domain
|
||||
State(NSRouteStateEnabled).
|
||||
Slice(&result).
|
||||
Desc("order").
|
||||
DescPk()
|
||||
AscPk()
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
} else {
|
||||
|
||||
@@ -142,10 +142,11 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
// DNS设置
|
||||
op.DnsDomainId = dnsDomainId
|
||||
op.DnsName = dnsName
|
||||
dnsConfig := &dnsconfigs.ClusterDNSConfig{
|
||||
var dnsConfig = &dnsconfigs.ClusterDNSConfig{
|
||||
NodesAutoSync: true,
|
||||
ServersAutoSync: true,
|
||||
CNameRecords: []string{},
|
||||
CNameAsDomain: true,
|
||||
TTL: 0,
|
||||
}
|
||||
dnsJSON, err := json.Marshal(dnsConfig)
|
||||
@@ -463,7 +464,7 @@ func (this *NodeClusterDAO) ExistClusterDNSName(tx *dbs.Tx, dnsName string, excl
|
||||
}
|
||||
|
||||
// UpdateClusterDNS 修改集群DNS相关信息
|
||||
func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsName string, dnsDomainId int64, nodesAutoSync bool, serversAutoSync bool, cnameRecords []string, ttl int32) error {
|
||||
func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsName string, dnsDomainId int64, nodesAutoSync bool, serversAutoSync bool, cnameRecords []string, ttl int32, cnameAsDomain bool) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -503,6 +504,7 @@ func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsNam
|
||||
ServersAutoSync: serversAutoSync,
|
||||
CNameRecords: cnameRecords,
|
||||
TTL: ttl,
|
||||
CNameAsDomain: cnameAsDomain,
|
||||
}
|
||||
dnsJSON, err := json.Marshal(dnsConfig)
|
||||
if err != nil {
|
||||
@@ -918,7 +920,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Result("id", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "isOn", "ddosProtection").
|
||||
Result("id", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "isOn", "ddosProtection").
|
||||
Find()
|
||||
if err != nil || cluster == nil {
|
||||
return nil, err
|
||||
@@ -988,6 +990,65 @@ func (this *NodeClusterDAO) FindClusterWebPPolicy(tx *dbs.Tx, clusterId int64, c
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
// UpdateClusterUAMPolicy 修改UAM设置
|
||||
func (this *NodeClusterDAO) UpdateClusterUAMPolicy(tx *dbs.Tx, clusterId int64, uamPolicy *nodeconfigs.UAMPolicy) error {
|
||||
if uamPolicy == nil {
|
||||
err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Set("uam", dbs.SQL("null")).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, clusterId)
|
||||
}
|
||||
|
||||
uamPolicyJSON, err := json.Marshal(uamPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Set("uam", uamPolicyJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, clusterId)
|
||||
}
|
||||
|
||||
// FindClusterUAMPolicy 查询设置
|
||||
func (this *NodeClusterDAO) FindClusterUAMPolicy(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*nodeconfigs.UAMPolicy, error) {
|
||||
var cacheKey = this.Table + ":FindClusterUAMPolicy:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*nodeconfigs.UAMPolicy), nil
|
||||
}
|
||||
}
|
||||
|
||||
uamJSON, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("uam").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if IsNull(uamJSON) {
|
||||
return nodeconfigs.DefaultUAMPolicy, nil
|
||||
}
|
||||
|
||||
var policy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(uamJSON, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
// FindClusterDDoSProtection 获取集群的DDoS设置
|
||||
func (this *NodeClusterDAO) FindClusterDDoSProtection(tx *dbs.Tx, clusterId int64) (*ddosconfigs.ProtectionConfig, error) {
|
||||
one, err := this.Query(tx).
|
||||
|
||||
@@ -34,6 +34,7 @@ type NodeCluster struct {
|
||||
AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口
|
||||
IsPinned bool `field:"isPinned"` // 是否置顶
|
||||
Webp dbs.JSON `field:"webp"` // WebP设置
|
||||
Uam dbs.JSON `field:"uam"` // UAM设置
|
||||
}
|
||||
|
||||
type NodeClusterOperator struct {
|
||||
@@ -67,6 +68,7 @@ type NodeClusterOperator struct {
|
||||
AutoOpenPorts interface{} // 是否自动尝试开放端口
|
||||
IsPinned interface{} // 是否置顶
|
||||
Webp interface{} // WebP设置
|
||||
Uam interface{} // UAM设置
|
||||
}
|
||||
|
||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||
|
||||
@@ -13,9 +13,12 @@ func (this *NodeCluster) DecodeDNSConfig() (*dnsconfigs.ClusterDNSConfig, error)
|
||||
return &dnsconfigs.ClusterDNSConfig{
|
||||
NodesAutoSync: false,
|
||||
ServersAutoSync: false,
|
||||
CNameAsDomain: true,
|
||||
}, nil
|
||||
}
|
||||
dnsConfig := &dnsconfigs.ClusterDNSConfig{}
|
||||
var dnsConfig = &dnsconfigs.ClusterDNSConfig{
|
||||
CNameAsDomain: true,
|
||||
}
|
||||
err := json.Unmarshal(this.Dns, &dnsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -100,7 +100,8 @@ func (this *NodeDAO) DisableNode(tx *dbs.Tx, nodeId int64) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleNode, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledNode 查找启用中的条目
|
||||
@@ -1018,6 +1019,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
clusterIds = append(clusterIds, node.DecodeSecondaryClusterIds()...)
|
||||
var clusterIndex = 0
|
||||
config.WebPImagePolicies = map[int64]*nodeconfigs.WebPImagePolicy{}
|
||||
config.UAMPolicies = map[int64]*nodeconfigs.UAMPolicy{}
|
||||
var allowIPMaps = map[string]bool{}
|
||||
for _, clusterId := range clusterIds {
|
||||
nodeCluster, err := SharedNodeClusterDAO.FindClusterBasicInfo(tx, clusterId, cacheMap)
|
||||
@@ -1077,7 +1079,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
// 最大线程数、TCP连接数
|
||||
if clusterIndex == 0 {
|
||||
config.MaxThreads = int(nodeCluster.NodeMaxThreads)
|
||||
config.DDOSProtection = nodeCluster.DecodeDDoSProtection()
|
||||
config.DDoSProtection = nodeCluster.DecodeDDoSProtection()
|
||||
config.AutoOpenPorts = nodeCluster.AutoOpenPorts == 1
|
||||
}
|
||||
|
||||
@@ -1091,6 +1093,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
config.WebPImagePolicies[clusterId] = webpPolicy
|
||||
}
|
||||
|
||||
// UAM
|
||||
if IsNotNull(nodeCluster.Uam) {
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(nodeCluster.Uam, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.UAMPolicies[clusterId] = uamPolicy
|
||||
}
|
||||
|
||||
clusterIndex++
|
||||
}
|
||||
|
||||
@@ -1212,10 +1224,10 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
// DDOS Protection
|
||||
var ddosProtection = node.DecodeDDoSProtection()
|
||||
if ddosProtection != nil {
|
||||
if config.DDOSProtection == nil {
|
||||
config.DDOSProtection = ddosProtection
|
||||
if config.DDoSProtection == nil {
|
||||
config.DDoSProtection = ddosProtection
|
||||
} else {
|
||||
config.DDOSProtection.Merge(ddosProtection)
|
||||
config.DDoSProtection.Merge(ddosProtection)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -360,3 +360,12 @@ func (this *NodeLogDAO) UpdateAllNodeLogsRead(tx *dbs.Tx) error {
|
||||
Set("isRead", true).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// DeleteNodeLogs 删除某个节点上的日志
|
||||
func (this *NodeLogDAO) DeleteNodeLogs(tx *dbs.Tx, role nodeconfigs.NodeRole, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("role", role).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,16 +52,23 @@ func (this *NSNodeDAO) EnableNSNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableNSNode 禁用条目
|
||||
func (this *NSNodeDAO) DisableNSNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *NSNodeDAO) DisableNSNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", NSNodeStateDisabled).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
|
||||
err = this.NotifyUpdate(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleDNS, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledNSNode 查找启用中的条目
|
||||
|
||||
@@ -101,7 +101,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
maxIdleConns int32,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string,
|
||||
host string) (originId int64, err error) {
|
||||
host string,
|
||||
followPort bool) (originId int64, err error) {
|
||||
var op = NewOriginOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
@@ -167,6 +168,7 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
op.Host = host
|
||||
op.FollowPort = followPort
|
||||
|
||||
op.State = OriginStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
@@ -191,7 +193,8 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
maxIdleConns int32,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string,
|
||||
host string) error {
|
||||
host string,
|
||||
followPort bool) error {
|
||||
if originId <= 0 {
|
||||
return errors.New("invalid originId")
|
||||
}
|
||||
@@ -262,6 +265,7 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
op.Host = host
|
||||
op.FollowPort = followPort
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -304,10 +308,11 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
RequestURI: origin.HttpRequestURI,
|
||||
RequestHost: origin.Host,
|
||||
Domains: origin.DecodeDomains(),
|
||||
FollowPort: origin.FollowPort,
|
||||
}
|
||||
|
||||
if IsNotNull(origin.Addr) {
|
||||
addr := &serverconfigs.NetworkAddressConfig{}
|
||||
var addr = &serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal(origin.Addr, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -316,7 +321,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.ConnTimeout) {
|
||||
connTimeout := &shared.TimeDuration{}
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.ConnTimeout, &connTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -325,7 +330,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.ReadTimeout) {
|
||||
readTimeout := &shared.TimeDuration{}
|
||||
var readTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.ReadTimeout, &readTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -334,7 +339,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.IdleTimeout) {
|
||||
idleTimeout := &shared.TimeDuration{}
|
||||
var idleTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.IdleTimeout, &idleTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -363,7 +368,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.HttpResponseHeader) {
|
||||
ref := &shared.HTTPHeaderPolicyRef{}
|
||||
var ref = &shared.HTTPHeaderPolicyRef{}
|
||||
err = json.Unmarshal(origin.HttpResponseHeader, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -382,7 +387,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.HealthCheck) {
|
||||
healthCheck := &serverconfigs.HealthCheckConfig{}
|
||||
var healthCheck = &serverconfigs.HealthCheckConfig{}
|
||||
err = json.Unmarshal(origin.HealthCheck, healthCheck)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -391,7 +396,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.Cert) {
|
||||
ref := &sslconfigs.SSLCertRef{}
|
||||
var ref = &sslconfigs.SSLCertRef{}
|
||||
err = json.Unmarshal(origin.Cert, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -417,6 +422,19 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// CheckUserOrigin 检查源站权限
|
||||
func (this *OriginDAO) CheckUserOrigin(tx *dbs.Tx, userId int64, originId int64) error {
|
||||
reverseProxyId, err := SharedReverseProxyDAO.FindReverseProxyContainsOriginId(tx, originId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if reverseProxyId == 0 {
|
||||
// 这里我们不允许源站没有被使用
|
||||
return ErrNotFound
|
||||
}
|
||||
return SharedReverseProxyDAO.CheckUserReverseProxy(tx, userId, reverseProxyId)
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *OriginDAO) NotifyUpdate(tx *dbs.Tx, originId int64) error {
|
||||
reverseProxyId, err := SharedReverseProxyDAO.FindReverseProxyContainsOriginId(tx, originId)
|
||||
|
||||
@@ -29,6 +29,7 @@ type Origin struct {
|
||||
Ftp dbs.JSON `field:"ftp"` // FTP相关设置
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Domains dbs.JSON `field:"domains"` // 所属域名
|
||||
FollowPort bool `field:"followPort"` // 端口跟随
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ type OriginOperator struct {
|
||||
Ftp interface{} // FTP相关设置
|
||||
CreatedAt interface{} // 创建时间
|
||||
Domains interface{} // 所属域名
|
||||
FollowPort interface{} // 端口跟随
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ func (this *PlanDAO) ListEnabledPlans(tx *dbs.Tx, offset int64, size int64) (res
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Desc("order").
|
||||
DescPk().
|
||||
AscPk().
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -50,12 +50,17 @@ func (this *ReportNodeDAO) EnableReportNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableReportNode 禁用条目
|
||||
func (this *ReportNodeDAO) DisableReportNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *ReportNodeDAO) DisableReportNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", ReportNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleReport, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledReportNode 查找启用中的条目
|
||||
|
||||
@@ -99,17 +99,18 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := &serverconfigs.ReverseProxyConfig{}
|
||||
var config = &serverconfigs.ReverseProxyConfig{}
|
||||
config.Id = int64(reverseProxy.Id)
|
||||
config.IsOn = reverseProxy.IsOn
|
||||
config.RequestHostType = types.Int8(reverseProxy.RequestHostType)
|
||||
config.RequestHost = reverseProxy.RequestHost
|
||||
config.RequestHostExcludingPort = reverseProxy.RequestHostExcludingPort
|
||||
config.RequestURI = reverseProxy.RequestURI
|
||||
config.StripPrefix = reverseProxy.StripPrefix
|
||||
config.AutoFlush = reverseProxy.AutoFlush == 1
|
||||
config.FollowRedirects = reverseProxy.FollowRedirects == 1
|
||||
|
||||
schedulingConfig := &serverconfigs.SchedulingConfig{}
|
||||
var schedulingConfig = &serverconfigs.SchedulingConfig{}
|
||||
if IsNotNull(reverseProxy.Scheduling) {
|
||||
err = json.Unmarshal(reverseProxy.Scheduling, schedulingConfig)
|
||||
if err != nil {
|
||||
@@ -118,7 +119,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
config.Scheduling = schedulingConfig
|
||||
}
|
||||
if IsNotNull(reverseProxy.PrimaryOrigins) {
|
||||
originRefs := []*serverconfigs.OriginRef{}
|
||||
var originRefs = []*serverconfigs.OriginRef{}
|
||||
err = json.Unmarshal(reverseProxy.PrimaryOrigins, &originRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -135,13 +136,13 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
}
|
||||
|
||||
if IsNotNull(reverseProxy.BackupOrigins) {
|
||||
originRefs := []*serverconfigs.OriginRef{}
|
||||
var originRefs = []*serverconfigs.OriginRef{}
|
||||
err = json.Unmarshal(reverseProxy.BackupOrigins, &originRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, originConfig := range originRefs {
|
||||
originConfig, err := SharedOriginDAO.ComposeOriginConfig(tx, originConfig.OriginId, cacheMap)
|
||||
for _, ref := range originRefs {
|
||||
originConfig, err := SharedOriginDAO.ComposeOriginConfig(tx, ref.OriginId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -153,7 +154,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
|
||||
// add headers
|
||||
if IsNotNull(reverseProxy.AddHeaders) {
|
||||
addHeaders := []string{}
|
||||
var addHeaders = []string{}
|
||||
err = json.Unmarshal(reverseProxy.AddHeaders, &addHeaders)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -166,7 +167,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
config.MaxIdleConns = int(reverseProxy.MaxIdleConns)
|
||||
|
||||
if IsNotNull(reverseProxy.ConnTimeout) {
|
||||
connTimeout := &shared.TimeDuration{}
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(reverseProxy.ConnTimeout, &connTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -175,7 +176,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
}
|
||||
|
||||
if IsNotNull(reverseProxy.ReadTimeout) {
|
||||
readTimeout := &shared.TimeDuration{}
|
||||
var readTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(reverseProxy.ReadTimeout, &readTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -184,7 +185,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
}
|
||||
|
||||
if IsNotNull(reverseProxy.IdleTimeout) {
|
||||
idleTimeout := &shared.TimeDuration{}
|
||||
var idleTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(reverseProxy.IdleTimeout, &idleTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -304,6 +305,7 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
||||
reverseProxyId int64,
|
||||
requestHostType int8,
|
||||
requestHost string,
|
||||
requestHostExcludingPort bool,
|
||||
requestURI string,
|
||||
stripPrefix string,
|
||||
autoFlush bool,
|
||||
@@ -328,6 +330,7 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
||||
op.RequestHostType = requestHostType
|
||||
|
||||
op.RequestHost = requestHost
|
||||
op.RequestHostExcludingPort = requestHostExcludingPort
|
||||
op.RequestURI = requestURI
|
||||
op.StripPrefix = stripPrefix
|
||||
op.AutoFlush = autoFlush
|
||||
|
||||
@@ -4,55 +4,57 @@ import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ReverseProxy 反向代理配置
|
||||
type ReverseProxy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Scheduling dbs.JSON `field:"scheduling"` // 调度算法
|
||||
PrimaryOrigins dbs.JSON `field:"primaryOrigins"` // 主要源站
|
||||
BackupOrigins dbs.JSON `field:"backupOrigins"` // 备用源站
|
||||
StripPrefix string `field:"stripPrefix"` // 去除URL前缀
|
||||
RequestHostType uint8 `field:"requestHostType"` // 请求Host类型
|
||||
RequestHost string `field:"requestHost"` // 请求Host
|
||||
RequestURI string `field:"requestURI"` // 请求URI
|
||||
AutoFlush uint8 `field:"autoFlush"` // 是否自动刷新缓冲区
|
||||
AddHeaders dbs.JSON `field:"addHeaders"` // 自动添加的Header列表
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时时间
|
||||
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时时间
|
||||
IdleTimeout dbs.JSON `field:"idleTimeout"` // 空闲超时时间
|
||||
MaxConns uint32 `field:"maxConns"` // 最大并发连接数
|
||||
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
||||
ProxyProtocol dbs.JSON `field:"proxyProtocol"` // Proxy Protocol配置
|
||||
FollowRedirects uint8 `field:"followRedirects"` // 回源跟随
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Scheduling dbs.JSON `field:"scheduling"` // 调度算法
|
||||
PrimaryOrigins dbs.JSON `field:"primaryOrigins"` // 主要源站
|
||||
BackupOrigins dbs.JSON `field:"backupOrigins"` // 备用源站
|
||||
StripPrefix string `field:"stripPrefix"` // 去除URL前缀
|
||||
RequestHostType uint8 `field:"requestHostType"` // 请求Host类型
|
||||
RequestHost string `field:"requestHost"` // 请求Host
|
||||
RequestHostExcludingPort bool `field:"requestHostExcludingPort"` // 移除请求Host中的域名
|
||||
RequestURI string `field:"requestURI"` // 请求URI
|
||||
AutoFlush uint8 `field:"autoFlush"` // 是否自动刷新缓冲区
|
||||
AddHeaders dbs.JSON `field:"addHeaders"` // 自动添加的Header列表
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时时间
|
||||
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时时间
|
||||
IdleTimeout dbs.JSON `field:"idleTimeout"` // 空闲超时时间
|
||||
MaxConns uint32 `field:"maxConns"` // 最大并发连接数
|
||||
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
||||
ProxyProtocol dbs.JSON `field:"proxyProtocol"` // Proxy Protocol配置
|
||||
FollowRedirects uint8 `field:"followRedirects"` // 回源跟随
|
||||
}
|
||||
|
||||
type ReverseProxyOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Scheduling interface{} // 调度算法
|
||||
PrimaryOrigins interface{} // 主要源站
|
||||
BackupOrigins interface{} // 备用源站
|
||||
StripPrefix interface{} // 去除URL前缀
|
||||
RequestHostType interface{} // 请求Host类型
|
||||
RequestHost interface{} // 请求Host
|
||||
RequestURI interface{} // 请求URI
|
||||
AutoFlush interface{} // 是否自动刷新缓冲区
|
||||
AddHeaders interface{} // 自动添加的Header列表
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
ConnTimeout interface{} // 连接超时时间
|
||||
ReadTimeout interface{} // 读取超时时间
|
||||
IdleTimeout interface{} // 空闲超时时间
|
||||
MaxConns interface{} // 最大并发连接数
|
||||
MaxIdleConns interface{} // 最大空闲连接数
|
||||
ProxyProtocol interface{} // Proxy Protocol配置
|
||||
FollowRedirects interface{} // 回源跟随
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Scheduling interface{} // 调度算法
|
||||
PrimaryOrigins interface{} // 主要源站
|
||||
BackupOrigins interface{} // 备用源站
|
||||
StripPrefix interface{} // 去除URL前缀
|
||||
RequestHostType interface{} // 请求Host类型
|
||||
RequestHost interface{} // 请求Host
|
||||
RequestHostExcludingPort interface{} // 移除请求Host中的域名
|
||||
RequestURI interface{} // 请求URI
|
||||
AutoFlush interface{} // 是否自动刷新缓冲区
|
||||
AddHeaders interface{} // 自动添加的Header列表
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
ConnTimeout interface{} // 连接超时时间
|
||||
ReadTimeout interface{} // 读取超时时间
|
||||
IdleTimeout interface{} // 空闲超时时间
|
||||
MaxConns interface{} // 最大并发连接数
|
||||
MaxIdleConns interface{} // 最大空闲连接数
|
||||
ProxyProtocol interface{} // Proxy Protocol配置
|
||||
FollowRedirects interface{} // 回源跟随
|
||||
}
|
||||
|
||||
func NewReverseProxyOperator() *ReverseProxyOperator {
|
||||
|
||||
215
internal/db/models/server_bandwidth_stat_dao.go
Normal file
215
internal/db/models/server_bandwidth_stat_dao.go
Normal file
@@ -0,0 +1,215 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ServerBandwidthStatDAO dbs.DAO
|
||||
|
||||
const (
|
||||
ServerBandwidthStatTablePartials = 20 // 分表数量
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerBandwidthStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedServerBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewServerBandwidthStatDAO() *ServerBandwidthStatDAO {
|
||||
return dbs.NewDAO(&ServerBandwidthStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeServerBandwidthStats",
|
||||
Model: new(ServerBandwidthStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*ServerBandwidthStatDAO)
|
||||
}
|
||||
|
||||
var SharedServerBandwidthStatDAO *ServerBandwidthStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedServerBandwidthStatDAO = NewServerBandwidthStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateServerBandwidth 写入数据
|
||||
func (this *ServerBandwidthStatDAO) UpdateServerBandwidth(tx *dbs.Tx, userId int64, serverId int64, day string, timeAt string, bytes int64) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("invalid server id '" + types.String(serverId) + "'")
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Param("bytes", bytes).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"serverId": serverId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindMinutelyPeekBandwidthBytes 获取某分钟的带宽峰值
|
||||
// day YYYYMMDD
|
||||
// minute HHII
|
||||
func (this *ServerBandwidthStatDAO) FindMinutelyPeekBandwidthBytes(tx *dbs.Tx, serverId int64, day string, minute string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
Attr("timeAt", minute).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindDailyPeekBandwidthBytes 获取某天的带宽峰值
|
||||
// day YYYYMMDD
|
||||
func (this *ServerBandwidthStatDAO) FindDailyPeekBandwidthBytes(tx *dbs.Tx, serverId int64, day string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("day", day).
|
||||
Result("MAX(bytes)").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindMonthlyPeekBandwidthBytes 获取某月的带宽峰值
|
||||
// month YYYYMM
|
||||
func (this *ServerBandwidthStatDAO) FindMonthlyPeekBandwidthBytes(tx *dbs.Tx, serverId int64, month string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Between("day", month+"01", month+"31").
|
||||
Result("MAX(bytes)").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindServerStats 查找某个时间段的带宽统计
|
||||
// 参数:
|
||||
// - day YYYYMMDD
|
||||
// - timeAt HHII
|
||||
func (this *ServerBandwidthStatDAO) FindServerStats(tx *dbs.Tx, serverId int64, day string, timeFrom string, timeTo string) (result []*ServerBandwidthStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
Between("timeAt", timeFrom, timeTo).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
|
||||
// 如果是100%以上,则快速返回
|
||||
if percentile >= 100 {
|
||||
result, err = this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
return
|
||||
}
|
||||
|
||||
// 总数量
|
||||
total, err := this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var offset int64
|
||||
|
||||
if total > 1 {
|
||||
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||
}
|
||||
|
||||
// 查询 nth 位置
|
||||
result, err = this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Offset(offset).
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -62)) // 保留大约2个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *ServerBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(ServerBandwidthStatTablePartials)
|
||||
var resultErr error
|
||||
for i := 0; i < ServerBandwidthStatTablePartials; i++ {
|
||||
var table = this.partialTable(int64(i))
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
err := f(table, locker)
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// 获取分区表
|
||||
func (this *ServerBandwidthStatDAO) partialTable(serverId int64) string {
|
||||
return this.Table + "_" + types.String(serverId%int64(ServerBandwidthStatTablePartials))
|
||||
}
|
||||
55
internal/db/models/server_bandwidth_stat_dao_test.go
Normal file
55
internal/db/models/server_bandwidth_stat_dao_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestServerBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateServerBandwidth(tx, 1, 1, timeutil.Format("Ymd"), timeutil.Format("Hi"), 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestSeverBandwidthStatDAO_InsertManyStats(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
var count = 1 // 测试时将此值设为一个比较大的数字
|
||||
for i := 0; i < count; i++ {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -rands.Int(0, 200)))
|
||||
var minute = fmt.Sprintf("%02d%02d", rands.Int(0, 23), rands.Int(0, 59))
|
||||
err := dao.UpdateServerBandwidth(tx, 1, 1, day, minute, 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95))
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_Clean(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
var before = time.Now()
|
||||
err := dao.Clean(tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok", time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
24
internal/db/models/server_bandwidth_stat_model.go
Normal file
24
internal/db/models/server_bandwidth_stat_model.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package models
|
||||
|
||||
// ServerBandwidthStat 服务峰值带宽统计
|
||||
type ServerBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
ServerId uint64 `field:"serverId"` // 服务ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHMM
|
||||
Bytes uint64 `field:"bytes"` // 带宽字节
|
||||
}
|
||||
|
||||
type ServerBandwidthStatOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
TimeAt interface{} // 时间点HHMM
|
||||
Bytes interface{} // 带宽字节
|
||||
}
|
||||
|
||||
func NewServerBandwidthStatOperator() *ServerBandwidthStatOperator {
|
||||
return &ServerBandwidthStatOperator{}
|
||||
}
|
||||
1
internal/db/models/server_bandwidth_stat_model_ext.go
Normal file
1
internal/db/models/server_bandwidth_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -405,45 +404,6 @@ func (this *ServerDailyStatDAO) SumMonthlyBytes(tx *dbs.Tx, serverId int64, mont
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *ServerDailyStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
|
||||
total, err := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var offset int64
|
||||
|
||||
if total > 1 {
|
||||
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||
}
|
||||
result, err = this.Query(tx).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Offset(offset).
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
|
||||
// 因为是5分钟统计,所以需要除以300
|
||||
result = result / 300
|
||||
return
|
||||
}
|
||||
|
||||
// FindDailyStats 按天统计
|
||||
func (this *ServerDailyStatDAO) FindDailyStats(tx *dbs.Tx, serverId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
|
||||
@@ -83,13 +83,3 @@ func TestServerDailyStatDAO_FindDistinctPlanServerIdsBetweenDay(t *testing.T) {
|
||||
}
|
||||
t.Log(serverIds)
|
||||
}
|
||||
|
||||
func TestServerDailyStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
var dao = NewServerDailyStatDAO()
|
||||
result, err := dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("result:", result)
|
||||
}
|
||||
|
||||
@@ -338,12 +338,31 @@ func (this *ServerDAO) UpdateServerBasic(tx *dbs.Tx, serverId int64, name string
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateServerGroupIds 修改服务所在分组
|
||||
func (this *ServerDAO) UpdateServerGroupIds(tx *dbs.Tx, serverId int64, groupIds []int64) error {
|
||||
if groupIds == nil {
|
||||
groupIds = []int64{}
|
||||
}
|
||||
groupIdsJSON, err := json.Marshal(groupIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("groupIds", groupIdsJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, serverId)
|
||||
}
|
||||
|
||||
// UpdateUserServerBasic 设置用户相关的基本信息
|
||||
func (this *ServerDAO) UpdateUserServerBasic(tx *dbs.Tx, serverId int64, name string) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
op := NewServerOperator()
|
||||
var op = NewServerOperator()
|
||||
op.Id = serverId
|
||||
op.Name = name
|
||||
|
||||
@@ -752,8 +771,9 @@ func (this *ServerDAO) CountAllEnabledServersMatch(tx *dbs.Tx, groupId int64, ke
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
if regexp.MustCompile(`^\d+$`).MatchString(keyword) {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
query.Where("(id=:serverId OR name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
Param("portRange", maps.Map{"portRange": keyword}.AsJSON()).
|
||||
Param("serverId", keyword).
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
} else {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword)").
|
||||
@@ -806,8 +826,9 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
if regexp.MustCompile(`^\d+$`).MatchString(keyword) {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
query.Where("(id=:serverId OR name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
Param("portRange", string(maps.Map{"portRange": keyword}.AsJSON())).
|
||||
Param("serverId", keyword).
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
} else {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword)").
|
||||
@@ -1020,9 +1041,10 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
return cache.(*serverconfigs.ServerConfig), nil
|
||||
}
|
||||
|
||||
config := &serverconfigs.ServerConfig{}
|
||||
var config = &serverconfigs.ServerConfig{}
|
||||
config.Id = int64(server.Id)
|
||||
config.ClusterId = int64(server.ClusterId)
|
||||
config.UserId = int64(server.UserId)
|
||||
config.Type = server.Type
|
||||
config.IsOn = server.IsOn
|
||||
config.Name = server.Name
|
||||
@@ -1044,7 +1066,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// ServerNames
|
||||
if IsNotNull(server.ServerNames) {
|
||||
serverNames := []*serverconfigs.ServerNameConfig{}
|
||||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||||
err := json.Unmarshal(server.ServerNames, &serverNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1060,20 +1082,29 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
return nil, err
|
||||
}
|
||||
if clusterDNS != nil && clusterDNS.DnsDomainId > 0 {
|
||||
clusterDNSConfig, err := clusterDNS.DecodeDNSConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domain, err := dns.SharedDNSDomainDAO.FindEnabledDNSDomain(tx, int64(clusterDNS.DnsDomainId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if domain != nil {
|
||||
cname := server.DnsName + "." + domain.Name
|
||||
config.AliasServerNames = append(config.AliasServerNames, cname)
|
||||
var cname = server.DnsName + "." + domain.Name
|
||||
config.CNameDomain = cname
|
||||
if clusterDNSConfig.CNameAsDomain {
|
||||
config.CNameAsDomain = true
|
||||
config.AliasServerNames = append(config.AliasServerNames, cname)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP
|
||||
if IsNotNull(server.Http) {
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
var httpConfig = &serverconfigs.HTTPProtocolConfig{}
|
||||
err := json.Unmarshal(server.Http, httpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1083,7 +1114,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// HTTPS
|
||||
if IsNotNull(server.Https) {
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
|
||||
err := json.Unmarshal(server.Https, httpsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1105,7 +1136,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// TCP
|
||||
if IsNotNull(server.Tcp) {
|
||||
tcpConfig := &serverconfigs.TCPProtocolConfig{}
|
||||
var tcpConfig = &serverconfigs.TCPProtocolConfig{}
|
||||
err := json.Unmarshal(server.Tcp, tcpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1115,7 +1146,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// TLS
|
||||
if IsNotNull(server.Tls) {
|
||||
tlsConfig := &serverconfigs.TLSProtocolConfig{}
|
||||
var tlsConfig = &serverconfigs.TLSProtocolConfig{}
|
||||
err := json.Unmarshal(server.Tls, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1137,7 +1168,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// Unix
|
||||
if IsNotNull(server.Unix) {
|
||||
unixConfig := &serverconfigs.UnixProtocolConfig{}
|
||||
var unixConfig = &serverconfigs.UnixProtocolConfig{}
|
||||
err := json.Unmarshal(server.Unix, unixConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1147,7 +1178,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// UDP
|
||||
if IsNotNull(server.Udp) {
|
||||
udpConfig := &serverconfigs.UDPProtocolConfig{}
|
||||
var udpConfig = &serverconfigs.UDPProtocolConfig{}
|
||||
err := json.Unmarshal(server.Udp, udpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1168,7 +1199,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// ReverseProxy
|
||||
if IsNotNull(server.ReverseProxy) {
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
var reverseProxyRef = &serverconfigs.ReverseProxyRef{}
|
||||
err := json.Unmarshal(server.ReverseProxy, reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1185,7 +1216,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
}
|
||||
|
||||
// WAF策略
|
||||
clusterId := int64(server.ClusterId)
|
||||
var clusterId = int64(server.ClusterId)
|
||||
httpFirewallPolicyId, err := SharedNodeClusterDAO.FindClusterHTTPFirewallPolicyId(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -410,6 +410,17 @@ func (this *ServerGroupDAO) CheckUserGroup(tx *dbs.Tx, userId int64, groupId int
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExistsGroup 检查分组ID是否存在
|
||||
func (this *ServerGroupDAO) ExistsGroup(tx *dbs.Tx, groupId int64) (bool, error) {
|
||||
if groupId <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
return this.Query(tx).
|
||||
Pk(groupId).
|
||||
State(ServerGroupStateEnabled).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
|
||||
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
|
||||
|
||||
143
internal/db/models/user_bandwidth_stat_dao.go
Normal file
143
internal/db/models/user_bandwidth_stat_dao.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserBandwidthStatDAO dbs.DAO
|
||||
|
||||
const (
|
||||
UserBandwidthStatTablePartials = 20
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedUserBandwidthStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedUserBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewUserBandwidthStatDAO() *UserBandwidthStatDAO {
|
||||
return dbs.NewDAO(&UserBandwidthStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserBandwidthStats",
|
||||
Model: new(UserBandwidthStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserBandwidthStatDAO)
|
||||
}
|
||||
|
||||
var SharedUserBandwidthStatDAO *UserBandwidthStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserBandwidthStatDAO = NewUserBandwidthStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUserBandwidth 写入数据
|
||||
func (this *UserBandwidthStatDAO) UpdateUserBandwidth(tx *dbs.Tx, userId int64, day string, timeAt string, bytes int64) error {
|
||||
if userId <= 0 {
|
||||
// 如果用户ID不大于0,则说明服务不属于任何用户,此时不需要处理
|
||||
return nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Param("bytes", bytes).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindUserPeekBandwidthInMonth 读取某月带宽峰值
|
||||
// month YYYYMM
|
||||
func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInMonth(tx *dbs.Tx, userId int64, month string) (*UserBandwidthStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Attr("userId", userId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserBandwidthStat), nil
|
||||
}
|
||||
|
||||
// FindUserPeekBandwidthInDay 读取某日带宽峰值
|
||||
// day YYYYMMDD
|
||||
func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInDay(tx *dbs.Tx, userId int64, day string) (*UserBandwidthStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Attr("userId", userId).
|
||||
Attr("day", day).
|
||||
Desc("bytes").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserBandwidthStat), nil
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -62)) // 保留大约2个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *UserBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(UserBandwidthStatTablePartials)
|
||||
var resultErr error
|
||||
for i := 0; i < UserBandwidthStatTablePartials; i++ {
|
||||
var table = this.partialTable(int64(i))
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
err := f(table, locker)
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// 获取分区表
|
||||
func (this *UserBandwidthStatDAO) partialTable(userId int64) string {
|
||||
return this.Table + "_" + types.String(userId%int64(UserBandwidthStatTablePartials))
|
||||
}
|
||||
30
internal/db/models/user_bandwidth_stat_dao_test.go
Normal file
30
internal/db/models/user_bandwidth_stat_dao_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateUserBandwidth(tx, 1, timeutil.Format("Ymd"), timeutil.Format("Hi"), 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestUserBandwidthStatDAO_Clean(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.Clean(tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
22
internal/db/models/user_bandwidth_stat_model.go
Normal file
22
internal/db/models/user_bandwidth_stat_model.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package models
|
||||
|
||||
// UserBandwidthStat 用户月带宽峰值
|
||||
type UserBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHII
|
||||
Bytes uint64 `field:"bytes"` // 带宽
|
||||
}
|
||||
|
||||
type UserBandwidthStatOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
TimeAt interface{} // 时间点HHII
|
||||
Bytes interface{} // 带宽
|
||||
}
|
||||
|
||||
func NewUserBandwidthStatOperator() *UserBandwidthStatOperator {
|
||||
return &UserBandwidthStatOperator{}
|
||||
}
|
||||
1
internal/db/models/user_bandwidth_stat_model_ext.go
Normal file
1
internal/db/models/user_bandwidth_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -236,7 +236,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -257,7 +257,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,7 +306,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -343,7 +343,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -361,7 +361,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -382,7 +382,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
184
internal/db/models/user_identity_dao.go
Normal file
184
internal/db/models/user_identity_dao.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UserIdentityStateEnabled = 1 // 已启用
|
||||
UserIdentityStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type UserIdentityDAO dbs.DAO
|
||||
|
||||
func NewUserIdentityDAO() *UserIdentityDAO {
|
||||
return dbs.NewDAO(&UserIdentityDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserIdentities",
|
||||
Model: new(UserIdentity),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserIdentityDAO)
|
||||
}
|
||||
|
||||
var SharedUserIdentityDAO *UserIdentityDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserIdentityDAO = NewUserIdentityDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableUserIdentity 启用条目
|
||||
func (this *UserIdentityDAO) EnableUserIdentity(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", UserIdentityStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableUserIdentity 禁用条目
|
||||
func (this *UserIdentityDAO) DisableUserIdentity(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", UserIdentityStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledUserIdentity 查找启用中的条目
|
||||
func (this *UserIdentityDAO) FindEnabledUserIdentity(tx *dbs.Tx, id int64) (*UserIdentity, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", UserIdentityStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*UserIdentity), err
|
||||
}
|
||||
|
||||
// CreateUserIdentity 创建
|
||||
func (this *UserIdentityDAO) CreateUserIdentity(tx *dbs.Tx, userId int64, idType userconfigs.UserIdentityType, realName string, number string, fileIds []int64) (int64, error) {
|
||||
var op = NewUserIdentityOperator()
|
||||
op.UserId = userId
|
||||
op.Type = idType
|
||||
op.RealName = realName
|
||||
op.Number = number
|
||||
|
||||
if fileIds == nil {
|
||||
fileIds = []int64{}
|
||||
}
|
||||
fileIdsJSON, err := json.Marshal(fileIds)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.FileIds = fileIdsJSON
|
||||
|
||||
op.Status = userconfigs.UserIdentityStatusNone
|
||||
op.State = UserIdentityStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateUserIdentity 修改
|
||||
func (this *UserIdentityDAO) UpdateUserIdentity(tx *dbs.Tx, identityId int64, idType userconfigs.UserIdentityType, realName string, number string, fileIds []int64) error {
|
||||
if identityId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var op = NewUserIdentityOperator()
|
||||
op.Id = identityId
|
||||
op.Type = idType
|
||||
op.Number = number
|
||||
|
||||
if fileIds == nil {
|
||||
fileIds = []int64{}
|
||||
}
|
||||
fileIdsJSON, err := json.Marshal(fileIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.FileIds = fileIdsJSON
|
||||
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// SubmitUserIdentity 提交审核
|
||||
func (this *UserIdentityDAO) SubmitUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusSubmitted).
|
||||
Set("submittedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CancelUserIdentity 取消提交审核
|
||||
func (this *UserIdentityDAO) CancelUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusNone).
|
||||
Set("updatedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// RejectUserIdentity 拒绝
|
||||
func (this *UserIdentityDAO) RejectUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusRejected).
|
||||
Set("rejectedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// VerifyUserIdentity 通过
|
||||
func (this *UserIdentityDAO) VerifyUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusVerified).
|
||||
Set("verifiedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CheckUserIdentity 检查用户认证
|
||||
func (this *UserIdentityDAO) CheckUserIdentity(tx *dbs.Tx, userId int64, identityId int64) error {
|
||||
b, err := this.Query(tx).
|
||||
Pk(identityId).
|
||||
Attr("userId", userId).
|
||||
State(UserIdentityStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindUserIdentityStatus 查找认证信息当前状态
|
||||
func (this *UserIdentityDAO) FindUserIdentityStatus(tx *dbs.Tx, identityId int64) (userconfigs.UserIdentityStatus, error) {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Result("status").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// FindEnabledUserIdentityWithType 查找某个类型的认证信息
|
||||
func (this *UserIdentityDAO) FindEnabledUserIdentityWithType(tx *dbs.Tx, userId int64, idType userconfigs.UserIdentityType) (*UserIdentity, error) {
|
||||
one, err := this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("type", idType).
|
||||
State(UserIdentityStateEnabled).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserIdentity), nil
|
||||
}
|
||||
6
internal/db/models/user_identity_dao_test.go
Normal file
6
internal/db/models/user_identity_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
40
internal/db/models/user_identity_model.go
Normal file
40
internal/db/models/user_identity_model.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// UserIdentity 用户实名认证信息
|
||||
type UserIdentity struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 类型
|
||||
RealName string `field:"realName"` // 真实姓名
|
||||
Number string `field:"number"` // 编号
|
||||
FileIds dbs.JSON `field:"fileIds"` // 文件ID
|
||||
Status string `field:"status"` // 状态:none,submitted,verified,rejected
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
SubmittedAt uint64 `field:"submittedAt"` // 提交时间
|
||||
RejectedAt uint64 `field:"rejectedAt"` // 拒绝时间
|
||||
VerifiedAt uint64 `field:"verifiedAt"` // 认证时间
|
||||
}
|
||||
|
||||
type UserIdentityOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Type interface{} // 类型
|
||||
RealName interface{} // 真实姓名
|
||||
Number interface{} // 编号
|
||||
FileIds interface{} // 文件ID
|
||||
Status interface{} // 状态:none,submitted,verified,rejected
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
UpdatedAt interface{} // 修改时间
|
||||
SubmittedAt interface{} // 提交时间
|
||||
RejectedAt interface{} // 拒绝时间
|
||||
VerifiedAt interface{} // 认证时间
|
||||
}
|
||||
|
||||
func NewUserIdentityOperator() *UserIdentityOperator {
|
||||
return &UserIdentityOperator{}
|
||||
}
|
||||
16
internal/db/models/user_identity_model_ext.go
Normal file
16
internal/db/models/user_identity_model_ext.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
func (this *UserIdentity) DecodeFileIds() []int64 {
|
||||
if len(this.FileIds) == 0 {
|
||||
return []int64{}
|
||||
}
|
||||
|
||||
var result = []int64{}
|
||||
err := json.Unmarshal(this.FileIds, &result)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -51,12 +51,17 @@ func (this *UserNodeDAO) EnableUserNode(tx *dbs.Tx, id uint32) error {
|
||||
}
|
||||
|
||||
// DisableUserNode 禁用条目
|
||||
func (this *UserNodeDAO) DisableUserNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *UserNodeDAO) DisableUserNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", UserNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleUser, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledUserNode 查找启用中的条目
|
||||
|
||||
@@ -11,7 +11,6 @@ const (
|
||||
ProviderTypeDNSPod ProviderType = "dnspod" // DNSPod
|
||||
ProviderTypeAliDNS ProviderType = "alidns" // 阿里云DNS
|
||||
ProviderTypeHuaweiDNS ProviderType = "huaweiDNS" // 华为DNS
|
||||
ProviderTypeDNSCom ProviderType = "dnscom" // dns.com
|
||||
ProviderTypeCloudFlare ProviderType = "cloudFlare" // CloudFlare DNS
|
||||
ProviderTypeLocalEdgeDNS ProviderType = "localEdgeDNS" // 和当前系统集成的EdgeDNS
|
||||
ProviderTypeUserEdgeDNS ProviderType = "userEdgeDNS" // 通过API连接的EdgeDNS
|
||||
@@ -36,11 +35,6 @@ func FindAllProviderTypes() []maps.Map {
|
||||
"code": ProviderTypeHuaweiDNS,
|
||||
"description": "华为云解析DNS。",
|
||||
},
|
||||
/**{
|
||||
"name": "帝恩思DNS.COM",
|
||||
"code": ProviderTypeDNSCom,
|
||||
"description": "DNS.com提供的DNS服务。",
|
||||
},**/
|
||||
{
|
||||
"name": "CloudFlare DNS",
|
||||
"code": ProviderTypeCloudFlare,
|
||||
|
||||
90
internal/installers/upgrade_limiter.go
Normal file
90
internal/installers/upgrade_limiter.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package installers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UpgradeLimiterDuration = 10 // node key expire time, by seconds
|
||||
UpgradeLimiterConcurrent = 10 // 10 nodes
|
||||
UpgradeLimiterMaxBytesPerSecond = 5 * sizes.M // max bytes per second
|
||||
)
|
||||
|
||||
var SharedUpgradeLimiter = NewUpgradeLimiter()
|
||||
|
||||
// UpgradeLimiter 升级流量管理器
|
||||
type UpgradeLimiter struct {
|
||||
nodeMap map[string]int64 // key => timestamp
|
||||
|
||||
rateTimestamp int64
|
||||
rateBytes int64
|
||||
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
func NewUpgradeLimiter() *UpgradeLimiter {
|
||||
return &UpgradeLimiter{
|
||||
nodeMap: map[string]int64{},
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateNodeBytes 添加正在下载的节点流量
|
||||
func (this *UpgradeLimiter) UpdateNodeBytes(nodeType nodeconfigs.NodeRole, nodeId int64, bytes int64) {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
// 先清理
|
||||
var nowTime = time.Now().Unix()
|
||||
this.gc(nowTime)
|
||||
|
||||
// 添加
|
||||
var key = nodeType + "_" + types.String(nodeId)
|
||||
this.nodeMap[key] = nowTime
|
||||
|
||||
// 流量
|
||||
if this.rateTimestamp == nowTime {
|
||||
this.rateBytes += bytes
|
||||
} else {
|
||||
this.rateTimestamp = nowTime
|
||||
this.rateBytes = bytes
|
||||
}
|
||||
}
|
||||
|
||||
// CanUpgrade 检查是否有新的升级
|
||||
func (this *UpgradeLimiter) CanUpgrade() bool {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
var nowTime = time.Now().Unix()
|
||||
this.gc(nowTime)
|
||||
|
||||
// 限制并发节点数
|
||||
if len(this.nodeMap) >= UpgradeLimiterConcurrent {
|
||||
return false
|
||||
}
|
||||
|
||||
if this.rateTimestamp != nowTime {
|
||||
return true
|
||||
}
|
||||
|
||||
// 限制下载速度
|
||||
if this.rateBytes >= UpgradeLimiterMaxBytesPerSecond {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *UpgradeLimiter) gc(nowTime int64) {
|
||||
for nodeKey, timestamp := range this.nodeMap {
|
||||
if timestamp < nowTime-UpgradeLimiterDuration {
|
||||
delete(this.nodeMap, nodeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
27
internal/installers/upgrade_limiter_test.go
Normal file
27
internal/installers/upgrade_limiter_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package installers_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/installers"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewUpgradeLimiter(t *testing.T) {
|
||||
var limiter = installers.NewUpgradeLimiter()
|
||||
limiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, 1, 1)
|
||||
limiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, 2, 5*sizes.M)
|
||||
t.Log("limiter:", limiter)
|
||||
t.Log("canUpgrade:", limiter.CanUpgrade())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
t.Log("canUpgrade:", limiter.CanUpgrade())
|
||||
t.Log("limiter:", limiter)
|
||||
limiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, 2, 4*sizes.M)
|
||||
t.Log("canUpgrade:", limiter.CanUpgrade())
|
||||
|
||||
t.Log("limiter:", limiter)
|
||||
}
|
||||
@@ -14,579 +14,590 @@ import (
|
||||
// 注册服务
|
||||
func (this *APINode) registerServices(server *grpc.Server) {
|
||||
{
|
||||
instance := this.serviceInstance(&services.APITokenService{}).(*services.APITokenService)
|
||||
var instance = this.serviceInstance(&services.APITokenService{}).(*services.APITokenService)
|
||||
pb.RegisterAPITokenServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.AdminService{}).(*services.AdminService)
|
||||
var instance = this.serviceInstance(&services.AdminService{}).(*services.AdminService)
|
||||
pb.RegisterAdminServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeGrantService{}).(*services.NodeGrantService)
|
||||
var instance = this.serviceInstance(&services.NodeGrantService{}).(*services.NodeGrantService)
|
||||
pb.RegisterNodeGrantServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerService{}).(*services.ServerService)
|
||||
var instance = this.serviceInstance(&services.ServerService{}).(*services.ServerService)
|
||||
pb.RegisterServerServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeService{}).(*services.NodeService)
|
||||
var instance = this.serviceInstance(&services.NodeService{}).(*services.NodeService)
|
||||
pb.RegisterNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeClusterService{}).(*services.NodeClusterService)
|
||||
var instance = this.serviceInstance(&services.NodeClusterService{}).(*services.NodeClusterService)
|
||||
pb.RegisterNodeClusterServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressService{}).(*services.NodeIPAddressService)
|
||||
var instance = this.serviceInstance(&services.NodeIPAddressService{}).(*services.NodeIPAddressService)
|
||||
pb.RegisterNodeIPAddressServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressLogService{}).(*services.NodeIPAddressLogService)
|
||||
var instance = this.serviceInstance(&services.NodeIPAddressLogService{}).(*services.NodeIPAddressLogService)
|
||||
pb.RegisterNodeIPAddressLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressThresholdService{}).(*services.NodeIPAddressThresholdService)
|
||||
var instance = this.serviceInstance(&services.NodeIPAddressThresholdService{}).(*services.NodeIPAddressThresholdService)
|
||||
pb.RegisterNodeIPAddressThresholdServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.APINodeService{}).(*services.APINodeService)
|
||||
var instance = this.serviceInstance(&services.APINodeService{}).(*services.APINodeService)
|
||||
pb.RegisterAPINodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.APIMethodStatService{}).(*services.APIMethodStatService)
|
||||
var instance = this.serviceInstance(&services.APIMethodStatService{}).(*services.APIMethodStatService)
|
||||
pb.RegisterAPIMethodStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
||||
var instance = this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
||||
pb.RegisterOriginServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPWebService{}).(*services.HTTPWebService)
|
||||
var instance = this.serviceInstance(&services.HTTPWebService{}).(*services.HTTPWebService)
|
||||
pb.RegisterHTTPWebServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ReverseProxyService{}).(*services.ReverseProxyService)
|
||||
var instance = this.serviceInstance(&services.ReverseProxyService{}).(*services.ReverseProxyService)
|
||||
pb.RegisterReverseProxyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPGzipService{}).(*services.HTTPGzipService)
|
||||
var instance = this.serviceInstance(&services.HTTPGzipService{}).(*services.HTTPGzipService)
|
||||
pb.RegisterHTTPGzipServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPHeaderPolicyService{}).(*services.HTTPHeaderPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPHeaderPolicyService{}).(*services.HTTPHeaderPolicyService)
|
||||
pb.RegisterHTTPHeaderPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPHeaderService{}).(*services.HTTPHeaderService)
|
||||
var instance = this.serviceInstance(&services.HTTPHeaderService{}).(*services.HTTPHeaderService)
|
||||
pb.RegisterHTTPHeaderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPPageService{}).(*services.HTTPPageService)
|
||||
var instance = this.serviceInstance(&services.HTTPPageService{}).(*services.HTTPPageService)
|
||||
pb.RegisterHTTPPageServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPAccessLogPolicyService{}).(*services.HTTPAccessLogPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPAccessLogPolicyService{}).(*services.HTTPAccessLogPolicyService)
|
||||
pb.RegisterHTTPAccessLogPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPCachePolicyService{}).(*services.HTTPCachePolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPCachePolicyService{}).(*services.HTTPCachePolicyService)
|
||||
pb.RegisterHTTPCachePolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFirewallPolicyService{}).(*services.HTTPFirewallPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPFirewallPolicyService{}).(*services.HTTPFirewallPolicyService)
|
||||
pb.RegisterHTTPFirewallPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.FirewallService{}).(*services.FirewallService)
|
||||
var instance = this.serviceInstance(&services.FirewallService{}).(*services.FirewallService)
|
||||
pb.RegisterFirewallServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPLocationService{}).(*services.HTTPLocationService)
|
||||
var instance = this.serviceInstance(&services.HTTPLocationService{}).(*services.HTTPLocationService)
|
||||
pb.RegisterHTTPLocationServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPWebsocketService{}).(*services.HTTPWebsocketService)
|
||||
var instance = this.serviceInstance(&services.HTTPWebsocketService{}).(*services.HTTPWebsocketService)
|
||||
pb.RegisterHTTPWebsocketServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPRewriteRuleService{}).(*services.HTTPRewriteRuleService)
|
||||
var instance = this.serviceInstance(&services.HTTPRewriteRuleService{}).(*services.HTTPRewriteRuleService)
|
||||
pb.RegisterHTTPRewriteRuleServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SSLCertService{}).(*services.SSLCertService)
|
||||
var instance = this.serviceInstance(&services.SSLCertService{}).(*services.SSLCertService)
|
||||
pb.RegisterSSLCertServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SSLPolicyService{}).(*services.SSLPolicyService)
|
||||
var instance = this.serviceInstance(&services.SSLPolicyService{}).(*services.SSLPolicyService)
|
||||
pb.RegisterSSLPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SysSettingService{}).(*services.SysSettingService)
|
||||
var instance = this.serviceInstance(&services.SysSettingService{}).(*services.SysSettingService)
|
||||
pb.RegisterSysSettingServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFirewallRuleGroupService{}).(*services.HTTPFirewallRuleGroupService)
|
||||
var instance = this.serviceInstance(&services.HTTPFirewallRuleGroupService{}).(*services.HTTPFirewallRuleGroupService)
|
||||
pb.RegisterHTTPFirewallRuleGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFirewallRuleSetService{}).(*services.HTTPFirewallRuleSetService)
|
||||
var instance = this.serviceInstance(&services.HTTPFirewallRuleSetService{}).(*services.HTTPFirewallRuleSetService)
|
||||
pb.RegisterHTTPFirewallRuleSetServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DBNodeService{}).(*services.DBNodeService)
|
||||
var instance = this.serviceInstance(&services.DBNodeService{}).(*services.DBNodeService)
|
||||
pb.RegisterDBNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeLogService{}).(*services.NodeLogService)
|
||||
var instance = this.serviceInstance(&services.NodeLogService{}).(*services.NodeLogService)
|
||||
pb.RegisterNodeLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeLoginService{}).(*services.NodeLoginService)
|
||||
var instance = this.serviceInstance(&services.NodeLoginService{}).(*services.NodeLoginService)
|
||||
pb.RegisterNodeLoginServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPAccessLogService{}).(*services.HTTPAccessLogService)
|
||||
var instance = this.serviceInstance(&services.HTTPAccessLogService{}).(*services.HTTPAccessLogService)
|
||||
pb.RegisterHTTPAccessLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageService{}).(*services.MessageService)
|
||||
var instance = this.serviceInstance(&services.MessageService{}).(*services.MessageService)
|
||||
pb.RegisterMessageServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageRecipientService{}).(*services.MessageRecipientService)
|
||||
var instance = this.serviceInstance(&services.MessageRecipientService{}).(*services.MessageRecipientService)
|
||||
pb.RegisterMessageRecipientServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageReceiverService{}).(*services.MessageReceiverService)
|
||||
var instance = this.serviceInstance(&services.MessageReceiverService{}).(*services.MessageReceiverService)
|
||||
pb.RegisterMessageReceiverServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageMediaService{}).(*services.MessageMediaService)
|
||||
var instance = this.serviceInstance(&services.MessageMediaService{}).(*services.MessageMediaService)
|
||||
pb.RegisterMessageMediaServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageRecipientGroupService{}).(*services.MessageRecipientGroupService)
|
||||
var instance = this.serviceInstance(&services.MessageRecipientGroupService{}).(*services.MessageRecipientGroupService)
|
||||
pb.RegisterMessageRecipientGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageMediaInstanceService{}).(*services.MessageMediaInstanceService)
|
||||
var instance = this.serviceInstance(&services.MessageMediaInstanceService{}).(*services.MessageMediaInstanceService)
|
||||
pb.RegisterMessageMediaInstanceServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageTaskService{}).(*services.MessageTaskService)
|
||||
var instance = this.serviceInstance(&services.MessageTaskService{}).(*services.MessageTaskService)
|
||||
pb.RegisterMessageTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageTaskLogService{}).(*services.MessageTaskLogService)
|
||||
var instance = this.serviceInstance(&services.MessageTaskLogService{}).(*services.MessageTaskLogService)
|
||||
pb.RegisterMessageTaskLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeGroupService{}).(*services.NodeGroupService)
|
||||
var instance = this.serviceInstance(&services.NodeGroupService{}).(*services.NodeGroupService)
|
||||
pb.RegisterNodeGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeRegionService{}).(*services.NodeRegionService)
|
||||
var instance = this.serviceInstance(&services.NodeRegionService{}).(*services.NodeRegionService)
|
||||
pb.RegisterNodeRegionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodePriceItemService{}).(*services.NodePriceItemService)
|
||||
var instance = this.serviceInstance(&services.NodePriceItemService{}).(*services.NodePriceItemService)
|
||||
pb.RegisterNodePriceItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerGroupService{}).(*services.ServerGroupService)
|
||||
var instance = this.serviceInstance(&services.ServerGroupService{}).(*services.ServerGroupService)
|
||||
pb.RegisterServerGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPLibraryService{}).(*services.IPLibraryService)
|
||||
var instance = this.serviceInstance(&services.IPLibraryService{}).(*services.IPLibraryService)
|
||||
pb.RegisterIPLibraryServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.FileChunkService{}).(*services.FileChunkService)
|
||||
var instance = this.serviceInstance(&services.FileChunkService{}).(*services.FileChunkService)
|
||||
pb.RegisterFileChunkServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.FileService{}).(*services.FileService)
|
||||
var instance = this.serviceInstance(&services.FileService{}).(*services.FileService)
|
||||
pb.RegisterFileServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionCountryService{}).(*services.RegionCountryService)
|
||||
var instance = this.serviceInstance(&services.RegionCountryService{}).(*services.RegionCountryService)
|
||||
pb.RegisterRegionCountryServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionProvinceService{}).(*services.RegionProvinceService)
|
||||
var instance = this.serviceInstance(&services.RegionProvinceService{}).(*services.RegionProvinceService)
|
||||
pb.RegisterRegionProvinceServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionCityService{}).(*services.RegionCityService)
|
||||
var instance = this.serviceInstance(&services.RegionCityService{}).(*services.RegionCityService)
|
||||
pb.RegisterRegionCityServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionProviderService{}).(*services.RegionProviderService)
|
||||
var instance = this.serviceInstance(&services.RegionProviderService{}).(*services.RegionProviderService)
|
||||
pb.RegisterRegionProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
||||
var instance = this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
||||
pb.RegisterIPListServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPItemService{}).(*services.IPItemService)
|
||||
var instance = this.serviceInstance(&services.IPItemService{}).(*services.IPItemService)
|
||||
pb.RegisterIPItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.LogService{}).(*services.LogService)
|
||||
var instance = this.serviceInstance(&services.LogService{}).(*services.LogService)
|
||||
pb.RegisterLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSProviderService{}).(*services.DNSProviderService)
|
||||
var instance = this.serviceInstance(&services.DNSProviderService{}).(*services.DNSProviderService)
|
||||
pb.RegisterDNSProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSDomainService{}).(*services.DNSDomainService)
|
||||
var instance = this.serviceInstance(&services.DNSDomainService{}).(*services.DNSDomainService)
|
||||
pb.RegisterDNSDomainServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSService{}).(*services.DNSService)
|
||||
var instance = this.serviceInstance(&services.DNSService{}).(*services.DNSService)
|
||||
pb.RegisterDNSServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEUserService{}).(*services.ACMEUserService)
|
||||
var instance = this.serviceInstance(&services.ACMEUserService{}).(*services.ACMEUserService)
|
||||
pb.RegisterACMEUserServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMETaskService{}).(*services.ACMETaskService)
|
||||
var instance = this.serviceInstance(&services.ACMETaskService{}).(*services.ACMETaskService)
|
||||
pb.RegisterACMETaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEAuthenticationService{}).(*services.ACMEAuthenticationService)
|
||||
var instance = this.serviceInstance(&services.ACMEAuthenticationService{}).(*services.ACMEAuthenticationService)
|
||||
pb.RegisterACMEAuthenticationServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEProviderService{}).(*services.ACMEProviderService)
|
||||
var instance = this.serviceInstance(&services.ACMEProviderService{}).(*services.ACMEProviderService)
|
||||
pb.RegisterACMEProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEProviderAccountService{}).(*services.ACMEProviderAccountService)
|
||||
var instance = this.serviceInstance(&services.ACMEProviderAccountService{}).(*services.ACMEProviderAccountService)
|
||||
pb.RegisterACMEProviderAccountServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserService{}).(*services.UserService)
|
||||
var instance = this.serviceInstance(&services.UserService{}).(*services.UserService)
|
||||
pb.RegisterUserServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerDailyStatService{}).(*services.ServerDailyStatService)
|
||||
var instance = this.serviceInstance(&services.UserIdentityService{}).(*services.UserIdentityService)
|
||||
pb.RegisterUserIdentityServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.ServerDailyStatService{}).(*services.ServerDailyStatService)
|
||||
pb.RegisterServerDailyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserBillService{}).(*services.UserBillService)
|
||||
var instance = this.serviceInstance(&services.UserBillService{}).(*services.UserBillService)
|
||||
pb.RegisterUserBillServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerBillService{}).(*services.ServerBillService)
|
||||
var instance = this.serviceInstance(&services.ServerBillService{}).(*services.ServerBillService)
|
||||
pb.RegisterServerBillServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
||||
var instance = this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
||||
pb.RegisterUserNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.LoginService{}).(*services.LoginService)
|
||||
var instance = this.serviceInstance(&services.LoginService{}).(*services.LoginService)
|
||||
pb.RegisterLoginServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserAccessKeyService{}).(*services.UserAccessKeyService)
|
||||
var instance = this.serviceInstance(&services.UserAccessKeyService{}).(*services.UserAccessKeyService)
|
||||
pb.RegisterUserAccessKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SysLockerService{}).(*services.SysLockerService)
|
||||
var instance = this.serviceInstance(&services.SysLockerService{}).(*services.SysLockerService)
|
||||
pb.RegisterSysLockerServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeTaskService{}).(*services.NodeTaskService)
|
||||
var instance = this.serviceInstance(&services.NodeTaskService{}).(*services.NodeTaskService)
|
||||
pb.RegisterNodeTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeValueService{}).(*services.NodeValueService)
|
||||
var instance = this.serviceInstance(&services.NodeValueService{}).(*services.NodeValueService)
|
||||
pb.RegisterNodeValueServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DBService{}).(*services.DBService)
|
||||
var instance = this.serviceInstance(&services.DBService{}).(*services.DBService)
|
||||
pb.RegisterDBServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionCityMonthlyStatService{}).(*services.ServerRegionCityMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionCityMonthlyStatService{}).(*services.ServerRegionCityMonthlyStatService)
|
||||
pb.RegisterServerRegionCityMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionCountryMonthlyStatService{}).(*services.ServerRegionCountryMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionCountryMonthlyStatService{}).(*services.ServerRegionCountryMonthlyStatService)
|
||||
pb.RegisterServerRegionCountryMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionProvinceMonthlyStatService{}).(*services.ServerRegionProvinceMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionProvinceMonthlyStatService{}).(*services.ServerRegionProvinceMonthlyStatService)
|
||||
pb.RegisterServerRegionProvinceMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionProviderMonthlyStatService{}).(*services.ServerRegionProviderMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionProviderMonthlyStatService{}).(*services.ServerRegionProviderMonthlyStatService)
|
||||
pb.RegisterServerRegionProviderMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
|
||||
pb.RegisterServerClientSystemMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerClientBrowserMonthlyStatService{}).(*services.ServerClientBrowserMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerClientBrowserMonthlyStatService{}).(*services.ServerClientBrowserMonthlyStatService)
|
||||
pb.RegisterServerClientBrowserMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerHTTPFirewallDailyStatService{}).(*services.ServerHTTPFirewallDailyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerHTTPFirewallDailyStatService{}).(*services.ServerHTTPFirewallDailyStatService)
|
||||
pb.RegisterServerHTTPFirewallDailyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSTaskService{}).(*services.DNSTaskService)
|
||||
var instance = this.serviceInstance(&services.DNSTaskService{}).(*services.DNSTaskService)
|
||||
pb.RegisterDNSTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeClusterFirewallActionService{}).(*services.NodeClusterFirewallActionService)
|
||||
var instance = this.serviceInstance(&services.NodeClusterFirewallActionService{}).(*services.NodeClusterFirewallActionService)
|
||||
pb.RegisterNodeClusterFirewallActionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MonitorNodeService{}).(*services.MonitorNodeService)
|
||||
var instance = this.serviceInstance(&services.MonitorNodeService{}).(*services.MonitorNodeService)
|
||||
pb.RegisterMonitorNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.AuthorityNodeService{}).(*services.AuthorityNodeService)
|
||||
var instance = this.serviceInstance(&services.AuthorityNodeService{}).(*services.AuthorityNodeService)
|
||||
pb.RegisterAuthorityNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.LatestItemService{}).(*services.LatestItemService)
|
||||
var instance = this.serviceInstance(&services.LatestItemService{}).(*services.LatestItemService)
|
||||
pb.RegisterLatestItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeThresholdService{}).(*services.NodeThresholdService)
|
||||
var instance = this.serviceInstance(&services.NodeThresholdService{}).(*services.NodeThresholdService)
|
||||
pb.RegisterNodeThresholdServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFastcgiService{}).(*services.HTTPFastcgiService)
|
||||
var instance = this.serviceInstance(&services.HTTPFastcgiService{}).(*services.HTTPFastcgiService)
|
||||
pb.RegisterHTTPFastcgiServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSClusterService{}).(*nameservers.NSClusterService)
|
||||
var instance = this.serviceInstance(&nameservers.NSClusterService{}).(*nameservers.NSClusterService)
|
||||
pb.RegisterNSClusterServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSNodeService{}).(*nameservers.NSNodeService)
|
||||
var instance = this.serviceInstance(&nameservers.NSNodeService{}).(*nameservers.NSNodeService)
|
||||
pb.RegisterNSNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSDomainService{}).(*nameservers.NSDomainService)
|
||||
var instance = this.serviceInstance(&nameservers.NSDomainService{}).(*nameservers.NSDomainService)
|
||||
pb.RegisterNSDomainServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSRecordService{}).(*nameservers.NSRecordService)
|
||||
var instance = this.serviceInstance(&nameservers.NSRecordService{}).(*nameservers.NSRecordService)
|
||||
pb.RegisterNSRecordServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSRouteService{}).(*nameservers.NSRouteService)
|
||||
var instance = this.serviceInstance(&nameservers.NSRouteService{}).(*nameservers.NSRouteService)
|
||||
pb.RegisterNSRouteServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSKeyService{}).(*nameservers.NSKeyService)
|
||||
var instance = this.serviceInstance(&nameservers.NSKeyService{}).(*nameservers.NSKeyService)
|
||||
pb.RegisterNSKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSAccessLogService{}).(*nameservers.NSAccessLogService)
|
||||
var instance = this.serviceInstance(&nameservers.NSAccessLogService{}).(*nameservers.NSAccessLogService)
|
||||
pb.RegisterNSAccessLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSRecordHourlyStatService{}).(*nameservers.NSRecordHourlyStatService)
|
||||
var instance = this.serviceInstance(&nameservers.NSRecordHourlyStatService{}).(*nameservers.NSRecordHourlyStatService)
|
||||
pb.RegisterNSRecordHourlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSQuestionOptionService{}).(*nameservers.NSQuestionOptionService)
|
||||
var instance = this.serviceInstance(&nameservers.NSQuestionOptionService{}).(*nameservers.NSQuestionOptionService)
|
||||
pb.RegisterNSQuestionOptionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSService{}).(*nameservers.NSService)
|
||||
var instance = this.serviceInstance(&nameservers.NSService{}).(*nameservers.NSService)
|
||||
pb.RegisterNSServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPAuthPolicyService{}).(*services.HTTPAuthPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPAuthPolicyService{}).(*services.HTTPAuthPolicyService)
|
||||
pb.RegisterHTTPAuthPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MetricItemService{}).(*services.MetricItemService)
|
||||
var instance = this.serviceInstance(&services.MetricItemService{}).(*services.MetricItemService)
|
||||
pb.RegisterMetricItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeClusterMetricItemService{}).(*services.NodeClusterMetricItemService)
|
||||
var instance = this.serviceInstance(&services.NodeClusterMetricItemService{}).(*services.NodeClusterMetricItemService)
|
||||
pb.RegisterNodeClusterMetricItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MetricStatService{}).(*services.MetricStatService)
|
||||
var instance = this.serviceInstance(&services.MetricStatService{}).(*services.MetricStatService)
|
||||
pb.RegisterMetricStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MetricChartService{}).(*services.MetricChartService)
|
||||
var instance = this.serviceInstance(&services.MetricChartService{}).(*services.MetricChartService)
|
||||
pb.RegisterMetricChartServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerStatBoardService{}).(*services.ServerStatBoardService)
|
||||
var instance = this.serviceInstance(&services.ServerStatBoardService{}).(*services.ServerStatBoardService)
|
||||
pb.RegisterServerStatBoardServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerStatBoardChartService{}).(*services.ServerStatBoardChartService)
|
||||
var instance = this.serviceInstance(&services.ServerStatBoardChartService{}).(*services.ServerStatBoardChartService)
|
||||
pb.RegisterServerStatBoardChartServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.PlanService{}).(*services.PlanService)
|
||||
var instance = this.serviceInstance(&services.PlanService{}).(*services.PlanService)
|
||||
pb.RegisterPlanServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserPlanService{}).(*services.UserPlanService)
|
||||
var instance = this.serviceInstance(&services.UserPlanService{}).(*services.UserPlanService)
|
||||
pb.RegisterUserPlanServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerDomainHourlyStatService{}).(*services.ServerDomainHourlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerDomainHourlyStatService{}).(*services.ServerDomainHourlyStatService)
|
||||
pb.RegisterServerDomainHourlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.TrafficDailyStatService{}).(*services.TrafficDailyStatService)
|
||||
var instance = this.serviceInstance(&services.TrafficDailyStatService{}).(*services.TrafficDailyStatService)
|
||||
pb.RegisterTrafficDailyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPCacheTaskKeyService{}).(*services.HTTPCacheTaskKeyService)
|
||||
var instance = this.serviceInstance(&services.HTTPCacheTaskKeyService{}).(*services.HTTPCacheTaskKeyService)
|
||||
pb.RegisterHTTPCacheTaskKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPCacheTaskService{}).(*services.HTTPCacheTaskService)
|
||||
var instance = this.serviceInstance(&services.HTTPCacheTaskService{}).(*services.HTTPCacheTaskService)
|
||||
pb.RegisterHTTPCacheTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
var instance = this.serviceInstance(&services.ServerBandwidthStatService{}).(*services.ServerBandwidthStatService)
|
||||
pb.RegisterServerBandwidthStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
APINodeServicesRegister(this, server)
|
||||
|
||||
// TODO check service names
|
||||
for serviceName := range server.GetServiceInfo() {
|
||||
index := strings.LastIndex(serviceName, ".")
|
||||
var index = strings.LastIndex(serviceName, ".")
|
||||
if index >= 0 {
|
||||
serviceName = serviceName[index+1:]
|
||||
}
|
||||
@@ -602,7 +613,7 @@ func (this *APINode) rest(instance interface{}) {
|
||||
defer this.serviceInstanceLocker.Unlock()
|
||||
|
||||
var name = reflect.TypeOf(instance).String()
|
||||
index := strings.LastIndex(name, ".")
|
||||
var index = strings.LastIndex(name, ".")
|
||||
if index >= 0 {
|
||||
name = name[index+1:]
|
||||
}
|
||||
@@ -618,7 +629,7 @@ func (this *APINode) serviceInstance(instance interface{}) interface{} {
|
||||
this.serviceInstanceLocker.Lock()
|
||||
defer this.serviceInstanceLocker.Unlock()
|
||||
|
||||
typeName := reflect.TypeOf(instance).String()
|
||||
var typeName = reflect.TypeOf(instance).String()
|
||||
result, ok := this.serviceInstanceMap[typeName]
|
||||
if ok {
|
||||
return result
|
||||
|
||||
@@ -462,12 +462,12 @@ func (this *NSNodeService) CheckNSNodeLatestVersion(ctx context.Context, req *pb
|
||||
|
||||
// DownloadNSNodeInstallationFile 下载最新DNS节点安装文件
|
||||
func (this *NSNodeService) DownloadNSNodeInstallationFile(ctx context.Context, req *pb.DownloadNSNodeInstallationFileRequest) (*pb.DownloadNSNodeInstallationFileResponse, error) {
|
||||
_, err := this.ValidateNSNode(ctx)
|
||||
nodeId, err := this.ValidateNSNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file := installers.SharedDeployManager.FindNSNodeFile(req.Os, req.Arch)
|
||||
var file = installers.SharedDeployManager.FindNSNodeFile(req.Os, req.Arch)
|
||||
if file == nil {
|
||||
return &pb.DownloadNSNodeInstallationFileResponse{}, nil
|
||||
}
|
||||
@@ -482,6 +482,9 @@ func (this *NSNodeService) DownloadNSNodeInstallationFile(ctx context.Context, r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加下载速度监控
|
||||
installers.SharedUpgradeLimiter.UpdateNodeBytes(nodeconfigs.NodeRoleDNS, nodeId, int64(len(data)))
|
||||
|
||||
return &pb.DownloadNSNodeInstallationFileResponse{
|
||||
Sum: sum,
|
||||
Offset: offset,
|
||||
|
||||
@@ -5,10 +5,81 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 队列相关数据
|
||||
var metricStatsMap = map[string]*pb.UploadMetricStatsRequest{} // key (clusterId@nodeId@serverId@itemId) => UploadMetricStatsRequest
|
||||
var metricStatKeysQueue = make(chan string, 100_000)
|
||||
var metricStatsLocker = &sync.Mutex{}
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
// 将队列导入数据库
|
||||
var countKeys = 0
|
||||
for key := range metricStatKeysQueue {
|
||||
err := func(key string) error {
|
||||
var tx *dbs.Tx
|
||||
|
||||
metricStatsLocker.Lock()
|
||||
req, ok := metricStatsMap[key]
|
||||
if !ok {
|
||||
metricStatsLocker.Unlock()
|
||||
return nil
|
||||
}
|
||||
delete(metricStatsMap, key)
|
||||
metricStatsLocker.Unlock()
|
||||
|
||||
var pieces = strings.Split(key, "@")
|
||||
var clusterId = types.Int64(pieces[0])
|
||||
var nodeId = types.Int64(pieces[1])
|
||||
var serverId = types.Int64(pieces[2])
|
||||
var itemId = types.Int64(pieces[3])
|
||||
|
||||
// 删除旧的数据
|
||||
err := models.SharedMetricStatDAO.DeleteNodeItemStats(tx, nodeId, serverId, itemId, req.Time)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, stat := range req.MetricStats {
|
||||
err := models.SharedMetricStatDAO.CreateStat(tx, stat.Hash, clusterId, nodeId, req.ServerId, req.ItemId, stat.Keys, float64(stat.Value), req.Time, req.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 保存总和
|
||||
err = models.SharedMetricSumStatDAO.UpdateSum(tx, clusterId, nodeId, req.ServerId, req.Time, req.ItemId, req.Version, req.Count, req.Total)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}(key)
|
||||
if err != nil {
|
||||
remotelogs.Error("METRIC_STAT", "upload metric stats failed: "+err.Error())
|
||||
}
|
||||
|
||||
// 人为限速
|
||||
countKeys++
|
||||
if countKeys >= 100 {
|
||||
countKeys = 0
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// MetricStatService 指标统计数据相关服务
|
||||
type MetricStatService struct {
|
||||
BaseService
|
||||
@@ -27,24 +98,18 @@ func (this *MetricStatService) UploadMetricStats(ctx context.Context, req *pb.Up
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 删除旧的数据
|
||||
err = models.SharedMetricStatDAO.DeleteNodeItemStats(tx, nodeId, req.ServerId, req.ItemId, req.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var key = types.String(clusterId) + "@" + types.String(nodeId) + "@" + types.String(req.ServerId) + "@" + types.String(req.ItemId)
|
||||
metricStatsLocker.Lock()
|
||||
metricStatsMap[key] = req
|
||||
|
||||
select {
|
||||
case metricStatKeysQueue <- key:
|
||||
default:
|
||||
// 如果满了就删除
|
||||
delete(metricStatsMap, key)
|
||||
}
|
||||
|
||||
for _, stat := range req.MetricStats {
|
||||
err := models.SharedMetricStatDAO.CreateStat(tx, stat.Hash, clusterId, nodeId, req.ServerId, req.ItemId, stat.Keys, float64(stat.Value), req.Time, req.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 保存总和
|
||||
err = models.SharedMetricSumStatDAO.UpdateSum(tx, clusterId, nodeId, req.ServerId, req.Time, req.ItemId, req.Version, req.Count, req.Total)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metricStatsLocker.Unlock()
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -1602,12 +1602,12 @@ func (this *NodeService) UpdateNodeUp(ctx context.Context, req *pb.UpdateNodeUpR
|
||||
|
||||
// DownloadNodeInstallationFile 下载最新边缘节点安装文件
|
||||
func (this *NodeService) DownloadNodeInstallationFile(ctx context.Context, req *pb.DownloadNodeInstallationFileRequest) (*pb.DownloadNodeInstallationFileResponse, error) {
|
||||
_, err := this.ValidateNode(ctx)
|
||||
nodeId, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file := installers.SharedDeployManager.FindNodeFile(req.Os, req.Arch)
|
||||
var file = installers.SharedDeployManager.FindNodeFile(req.Os, req.Arch)
|
||||
if file == nil {
|
||||
return &pb.DownloadNodeInstallationFileResponse{}, nil
|
||||
}
|
||||
@@ -1622,6 +1622,9 @@ func (this *NodeService) DownloadNodeInstallationFile(ctx context.Context, req *
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加下载速度监控
|
||||
installers.SharedUpgradeLimiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, nodeId, int64(len(data)))
|
||||
|
||||
return &pb.DownloadNodeInstallationFileResponse{
|
||||
Sum: sum,
|
||||
Offset: offset,
|
||||
|
||||
@@ -429,7 +429,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
dnsInfo, err := models.SharedNodeClusterDAO.FindClusterDNSInfo(tx, req.NodeClusterId, nil)
|
||||
if err != nil {
|
||||
@@ -457,6 +457,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
ServersAutoSync: dnsConfig.ServersAutoSync,
|
||||
CnameRecords: dnsConfig.CNameRecords,
|
||||
Ttl: dnsConfig.TTL,
|
||||
CnameAsDomain: dnsConfig.CNameAsDomain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -471,7 +472,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
Provider: nil,
|
||||
}, nil
|
||||
}
|
||||
pbDomain := &pb.DNSDomain{
|
||||
var pbDomain = &pb.DNSDomain{
|
||||
Id: int64(domain.Id),
|
||||
Name: domain.Name,
|
||||
IsOn: domain.IsOn,
|
||||
@@ -515,6 +516,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
ServersAutoSync: dnsConfig.ServersAutoSync,
|
||||
CnameRecords: dnsConfig.CNameRecords,
|
||||
Ttl: dnsConfig.TTL,
|
||||
CnameAsDomain: dnsConfig.CNameAsDomain,
|
||||
DefaultRoute: defaultRoute,
|
||||
}, nil
|
||||
}
|
||||
@@ -527,7 +529,7 @@ func (this *NodeClusterService) CountAllEnabledNodeClustersWithDNSProviderId(ctx
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeClusterDAO.CountAllEnabledClustersWithDNSProviderId(tx, req.DnsProviderId)
|
||||
if err != nil {
|
||||
@@ -544,7 +546,7 @@ func (this *NodeClusterService) CountAllEnabledNodeClustersWithDNSDomainId(ctx c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeClusterDAO.CountAllEnabledClustersWithDNSDomainId(tx, req.DnsDomainId)
|
||||
if err != nil {
|
||||
@@ -561,7 +563,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClustersWithDNSDomainId(ctx co
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
clusters, err := models.SharedNodeClusterDAO.FindAllEnabledClustersWithDNSDomainId(tx, req.DnsDomainId)
|
||||
if err != nil {
|
||||
@@ -589,7 +591,7 @@ func (this *NodeClusterService) CheckNodeClusterDNSName(ctx context.Context, req
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
exists, err := models.SharedNodeClusterDAO.ExistClusterDNSName(tx, req.DnsName, req.NodeClusterId)
|
||||
if err != nil {
|
||||
@@ -606,9 +608,9 @@ func (this *NodeClusterService) UpdateNodeClusterDNS(ctx context.Context, req *p
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDNS(tx, req.NodeClusterId, req.DnsName, req.DnsDomainId, req.NodesAutoSync, req.ServersAutoSync, req.CnameRecords, req.Ttl)
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDNS(tx, req.NodeClusterId, req.DnsName, req.DnsDomainId, req.NodesAutoSync, req.ServersAutoSync, req.CnameRecords, req.Ttl, req.CnameAsDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1040,6 +1042,18 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
|
||||
result.WebpIsOn = nodeconfigs.DefaultWebPImagePolicy.IsOn
|
||||
}
|
||||
|
||||
// UAM
|
||||
if models.IsNotNull(cluster.Uam) {
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(cluster.Uam, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.UamIsOn = uamPolicy.IsOn
|
||||
} else {
|
||||
result.UamIsOn = nodeconfigs.DefaultUAMPolicy.IsOn
|
||||
}
|
||||
|
||||
// system service
|
||||
if models.IsNotNull(cluster.SystemServices) {
|
||||
var servicesMap = map[string]maps.Map{}
|
||||
@@ -1104,13 +1118,18 @@ func (this *NodeClusterService) UpdateNodeClusterWebPPolicy(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var webpPolicy = &nodeconfigs.WebPImagePolicy{}
|
||||
err = json.Unmarshal(req.WebpPolicyJSON, webpPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = webpPolicy.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate webp policy failed: " + err.Error())
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterWebPPolicy(tx, req.NodeClusterId, webpPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1118,6 +1137,53 @@ func (this *NodeClusterService) UpdateNodeClusterWebPPolicy(ctx context.Context,
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledNodeClusterUAMPolicy 读取集群UAM策略
|
||||
func (this *NodeClusterService) FindEnabledNodeClusterUAMPolicy(ctx context.Context, req *pb.FindEnabledNodeClusterUAMPolicyRequest) (*pb.FindEnabledNodeClusterUAMPolicyResponse, error) {
|
||||
_, _, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
uamPolicy, err := models.SharedNodeClusterDAO.FindClusterUAMPolicy(tx, req.NodeClusterId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uamPolicyJSON, err := json.Marshal(uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindEnabledNodeClusterUAMPolicyResponse{
|
||||
UamPolicyJSON: uamPolicyJSON,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeClusterUAMPolicy 设置集群的UAM策略
|
||||
func (this *NodeClusterService) UpdateNodeClusterUAMPolicy(ctx context.Context, req *pb.UpdateNodeClusterUAMPolicyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(req.UamPolicyJSON, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = uamPolicy.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate uam policy failed: " + err.Error())
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterUAMPolicy(tx, req.NodeClusterId, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindNodeClusterDDoSProtection 获取集群的DDOS设置
|
||||
func (this *NodeClusterService) FindNodeClusterDDoSProtection(ctx context.Context, req *pb.FindNodeClusterDDoSProtectionRequest) (*pb.FindNodeClusterDDoSProtectionResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
|
||||
@@ -32,7 +32,7 @@ func (this *NodeTaskService) FindNodeTasks(ctx context.Context, req *pb.FindNode
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pbTasks := []*pb.NodeTask{}
|
||||
var pbTasks = []*pb.NodeTask{}
|
||||
for _, task := range tasks {
|
||||
pbTasks = append(pbTasks, &pb.NodeTask{
|
||||
Id: int64(task.Id),
|
||||
@@ -44,13 +44,13 @@ func (this *NodeTaskService) FindNodeTasks(ctx context.Context, req *pb.FindNode
|
||||
}
|
||||
|
||||
// 边缘节点版本更新任务
|
||||
if nodeType == rpcutils.UserTypeNode {
|
||||
if nodeType == rpcutils.UserTypeNode && installers.SharedUpgradeLimiter.CanUpgrade() {
|
||||
status, err := models.SharedNodeDAO.FindNodeStatus(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != nil && len(status.OS) > 0 && len(status.Arch) > 0 && len(status.BuildVersion) > 0 {
|
||||
deployFile := installers.SharedDeployManager.FindNodeFile(status.OS, status.Arch)
|
||||
var deployFile = installers.SharedDeployManager.FindNodeFile(status.OS, status.Arch)
|
||||
if deployFile != nil {
|
||||
if stringutil.VersionCompare(deployFile.Version, status.BuildVersion) > 0 {
|
||||
pbTasks = append(pbTasks, &pb.NodeTask{
|
||||
|
||||
@@ -72,7 +72,7 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host)
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -87,20 +87,23 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
// TODO 校验权限
|
||||
err = models.SharedOriginDAO.CheckUserOrigin(tx, userId, req.OriginId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if req.Addr == nil {
|
||||
return nil, errors.New("'addr' can not be nil")
|
||||
}
|
||||
addrMap := maps.Map{
|
||||
var addrMap = maps.Map{
|
||||
"protocol": req.Addr.Protocol,
|
||||
"portRange": req.Addr.PortRange,
|
||||
"host": req.Addr.Host,
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 校验参数
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
if len(req.ConnTimeoutJSON) > 0 {
|
||||
@@ -139,7 +142,7 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host)
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -154,11 +157,14 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
// TODO 校验权限
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
|
||||
tx := this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedOriginDAO.CheckUserOrigin(tx, userId, req.OriginId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
origin, err := models.SharedOriginDAO.FindEnabledOrigin(tx, req.OriginId)
|
||||
if err != nil {
|
||||
@@ -196,11 +202,14 @@ func (this *OriginService) FindEnabledOriginConfig(ctx context.Context, req *pb.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
// TODO 校验权限
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
|
||||
tx := this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedOriginDAO.CheckUserOrigin(tx, userId, req.OriginId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
config, err := models.SharedOriginDAO.ComposeOriginConfig(tx, req.OriginId, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -84,7 +84,7 @@ func (this *ReverseProxyService) FindEnabledReverseProxyConfig(ctx context.Conte
|
||||
}
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
config, err := models.SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, req.ReverseProxyId, nil)
|
||||
if err != nil {
|
||||
@@ -189,7 +189,7 @@ func (this *ReverseProxyService) UpdateReverseProxy(ctx context.Context, req *pb
|
||||
}
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 校验参数
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
@@ -216,7 +216,7 @@ func (this *ReverseProxyService) UpdateReverseProxy(ctx context.Context, req *pb
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedReverseProxyDAO.UpdateReverseProxy(tx, req.ReverseProxyId, types.Int8(req.RequestHostType), req.RequestHost, req.RequestURI, req.StripPrefix, req.AutoFlush, req.AddHeaders, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.ProxyProtocolJSON, req.FollowRedirects)
|
||||
err = models.SharedReverseProxyDAO.UpdateReverseProxy(tx, req.ReverseProxyId, types.Int8(req.RequestHostType), req.RequestHost, req.RequestHostExcludingPort, req.RequestURI, req.StripPrefix, req.AutoFlush, req.AddHeaders, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.ProxyProtocolJSON, req.FollowRedirects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -192,6 +192,56 @@ func (this *ServerService) UpdateServerBasic(ctx context.Context, req *pb.Update
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateServerGroupIds 修改服务所在分组
|
||||
func (this *ServerService) UpdateServerGroupIds(ctx context.Context, req *pb.UpdateServerGroupIdsRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 检查分组IDs
|
||||
for _, groupId := range req.ServerGroupIds {
|
||||
if userId > 0 {
|
||||
err = models.SharedServerGroupDAO.CheckUserGroup(tx, userId, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
b, err := models.SharedServerGroupDAO.ExistsGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !b {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 增加默认分组
|
||||
if userId > 0 {
|
||||
config, err := models.SharedSysSettingDAO.ReadUserServerConfig(tx)
|
||||
if err == nil && config.GroupId > 0 && !lists.ContainsInt64(req.ServerGroupIds, config.GroupId) {
|
||||
req.ServerGroupIds = append(req.ServerGroupIds, config.GroupId)
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
err = models.SharedServerDAO.UpdateServerGroupIds(tx, req.ServerId, req.ServerGroupIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateServerIsOn 修改服务是否启用
|
||||
func (this *ServerService) UpdateServerIsOn(ctx context.Context, req *pb.UpdateServerIsOnRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
@@ -199,7 +249,7 @@ func (this *ServerService) UpdateServerIsOn(ctx context.Context, req *pb.UpdateS
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
@@ -832,8 +882,9 @@ func (this *ServerService) FindEnabledServer(ctx context.Context, req *pb.FindEn
|
||||
continue
|
||||
}
|
||||
pbGroups = append(pbGroups, &pb.ServerGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
UserId: int64(group.UserId),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
@@ -43,6 +44,12 @@ func init() {
|
||||
// 导入统计数据
|
||||
goman.New(func() {
|
||||
var duration = 30 * time.Minute
|
||||
|
||||
// 小内存的要快速处理
|
||||
if utils.SystemMemoryGB() <= 2 {
|
||||
duration = 15 * time.Minute
|
||||
}
|
||||
|
||||
if Tea.IsTesting() {
|
||||
// 测试条件下缩短时间,以便进行观察
|
||||
duration = 10 * time.Second
|
||||
|
||||
107
internal/rpc/services/service_server_bandwidth_stat.go
Normal file
107
internal/rpc/services/service_server_bandwidth_stat.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var serverBandwidthStatsMap = map[string]*pb.ServerBandwidthStat{} // key => bandwidth
|
||||
var serverBandwidthStatsLocker = &sync.Mutex{}
|
||||
|
||||
func init() {
|
||||
var ticker = time.NewTicker(5 * time.Minute)
|
||||
if Tea.IsTesting() {
|
||||
ticker = time.NewTicker(1 * time.Minute)
|
||||
}
|
||||
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
func() {
|
||||
var tx *dbs.Tx
|
||||
|
||||
serverBandwidthStatsLocker.Lock()
|
||||
var m = serverBandwidthStatsMap
|
||||
serverBandwidthStatsMap = map[string]*pb.ServerBandwidthStat{}
|
||||
serverBandwidthStatsLocker.Unlock()
|
||||
|
||||
for _, stat := range m {
|
||||
err := models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.Day, stat.TimeAt, stat.Bytes)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerBandwidthStatService", "dump bandwidth stats failed: "+err.Error())
|
||||
}
|
||||
|
||||
if stat.UserId > 0 {
|
||||
err = models.SharedUserBandwidthStatDAO.UpdateUserBandwidth(tx, stat.UserId, stat.Day, stat.TimeAt, stat.Bytes)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedUserBandwidthStatDAO", "dump bandwidth stats failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ServerBandwidthCacheKey 组合缓存Key
|
||||
func ServerBandwidthCacheKey(serverId int64, day string, timeAt string) string {
|
||||
return types.String(serverId) + "@" + day + "@" + timeAt
|
||||
}
|
||||
|
||||
func ServerBandwidthGetCacheBytes(serverId int64, day string, timeAt string) int64 {
|
||||
var key = ServerBandwidthCacheKey(serverId, day, timeAt)
|
||||
var bytes int64 = 0
|
||||
|
||||
serverBandwidthStatsLocker.Lock()
|
||||
stat, ok := serverBandwidthStatsMap[key]
|
||||
if ok {
|
||||
bytes = stat.Bytes
|
||||
}
|
||||
serverBandwidthStatsLocker.Unlock()
|
||||
|
||||
return bytes
|
||||
}
|
||||
|
||||
type ServerBandwidthStatService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// UploadServerBandwidthStats 上传带宽统计
|
||||
func (this *ServerBandwidthStatService) UploadServerBandwidthStats(ctx context.Context, req *pb.UploadServerBandwidthStatsRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, stat := range req.ServerBandwidthStats {
|
||||
var key = ServerBandwidthCacheKey(stat.ServerId, stat.Day, stat.TimeAt)
|
||||
serverBandwidthStatsLocker.Lock()
|
||||
oldStat, ok := serverBandwidthStatsMap[key]
|
||||
if ok {
|
||||
oldStat.Bytes += stat.Bytes
|
||||
} else {
|
||||
serverBandwidthStatsMap[key] = &pb.ServerBandwidthStat{
|
||||
Id: 0,
|
||||
UserId: stat.UserId,
|
||||
ServerId: stat.ServerId,
|
||||
Day: stat.Day,
|
||||
TimeAt: stat.TimeAt,
|
||||
Bytes: stat.Bytes,
|
||||
}
|
||||
}
|
||||
serverBandwidthStatsLocker.Unlock()
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/tasks"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -84,7 +85,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
result.CountServers = countServers
|
||||
|
||||
// 按日流量统计
|
||||
dayFrom := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
var dayFrom = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
dailyTrafficStats, err := stats.SharedNodeClusterTrafficDailyStatDAO.FindDailyStats(tx, req.NodeClusterId, dayFrom, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -102,8 +103,8 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
}
|
||||
|
||||
// 小时流量统计
|
||||
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
hourTo := timeutil.Format("YmdH")
|
||||
var hourFrom = timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
var hourTo = timeutil.Format("YmdH")
|
||||
hourlyTrafficStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindHourlyStatsWithClusterId(tx, req.NodeClusterId, hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -304,7 +305,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Conte
|
||||
}
|
||||
|
||||
// 按日流量统计
|
||||
dayFrom := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
var dayFrom = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
dailyTrafficStats, err := stats.SharedNodeTrafficDailyStatDAO.FindDailyStats(tx, "node", req.NodeId, dayFrom, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -322,8 +323,8 @@ func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Conte
|
||||
}
|
||||
|
||||
// 小时流量统计
|
||||
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
hourTo := timeutil.Format("YmdH")
|
||||
var hourFrom = timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
var hourTo = timeutil.Format("YmdH")
|
||||
hourlyTrafficStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindHourlyStatsWithNodeId(tx, "node", req.NodeId, hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -407,8 +408,100 @@ func (this *ServerStatBoardService) ComposeServerStatBoard(ctx context.Context,
|
||||
var result = &pb.ComposeServerStatBoardResponse{}
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 带宽统计
|
||||
{
|
||||
var month = timeutil.Format("Ym")
|
||||
var day = timeutil.Format("Ymd")
|
||||
|
||||
// 当前N分钟区间
|
||||
{
|
||||
// 查询最近的两个时段,以尽可能获取数据
|
||||
var minute1 = timeutil.FormatTime("Hi", time.Now().Unix()/300*300)
|
||||
var minute2 = timeutil.FormatTime("Hi", time.Now().Unix()/300*300-300)
|
||||
|
||||
for _, minute := range []string{minute1, minute2} {
|
||||
bytes, err := models.SharedServerBandwidthStatDAO.FindMinutelyPeekBandwidthBytes(tx, req.ServerId, day, minute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bytes == 0 {
|
||||
// 尝试从缓存中读取
|
||||
bytes = ServerBandwidthGetCacheBytes(req.ServerId, day, minute)
|
||||
}
|
||||
|
||||
if bytes > 0 {
|
||||
result.MinutelyPeekBandwidthBytes = bytes
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当天
|
||||
{
|
||||
bytes, err := models.SharedServerBandwidthStatDAO.FindDailyPeekBandwidthBytes(tx, req.ServerId, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.DailyPeekBandwidthBytes = bytes
|
||||
}
|
||||
|
||||
// 当月
|
||||
{
|
||||
bytes, err := models.SharedServerBandwidthStatDAO.FindMonthlyPeekBandwidthBytes(tx, req.ServerId, month)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.MonthlyPeekBandwidthBytes = bytes
|
||||
}
|
||||
|
||||
// 上月
|
||||
{
|
||||
bytes, err := models.SharedServerBandwidthStatDAO.FindMonthlyPeekBandwidthBytes(tx, req.ServerId, timeutil.Format("Ym", time.Now().AddDate(0, -1, 0)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.LastMonthlyPeekBandwidthBytes = bytes
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var bandwidthMinutes = utils.RangeMinutes(time.Now(), 12, 5)
|
||||
var bandwidthStatMap = map[string]*pb.ServerBandwidthStat{}
|
||||
for _, r := range utils.GroupMinuteRanges(bandwidthMinutes) {
|
||||
bandwidthStats, err := models.SharedServerBandwidthStatDAO.FindServerStats(tx, req.ServerId, r.Day, r.MinuteFrom, r.MinuteTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range bandwidthStats {
|
||||
bandwidthStatMap[stat.Day+"@"+stat.TimeAt] = &pb.ServerBandwidthStat{
|
||||
Id: int64(stat.Id),
|
||||
ServerId: int64(stat.ServerId),
|
||||
Day: stat.Day,
|
||||
TimeAt: stat.TimeAt,
|
||||
Bytes: int64(stat.Bytes),
|
||||
}
|
||||
}
|
||||
}
|
||||
var pbBandwidthStats = []*pb.ServerBandwidthStat{}
|
||||
for _, minute := range bandwidthMinutes {
|
||||
stat, ok := bandwidthStatMap[minute.Day+"@"+minute.Minute]
|
||||
if ok {
|
||||
pbBandwidthStats = append(pbBandwidthStats, stat)
|
||||
} else {
|
||||
pbBandwidthStats = append(pbBandwidthStats, &pb.ServerBandwidthStat{
|
||||
Id: 0,
|
||||
ServerId: req.ServerId,
|
||||
Day: minute.Day,
|
||||
TimeAt: minute.Minute,
|
||||
Bytes: ServerBandwidthGetCacheBytes(req.ServerId, minute.Day, minute.Minute), // 从当前缓存中读取
|
||||
})
|
||||
}
|
||||
}
|
||||
result.MinutelyBandwidthStats = pbBandwidthStats
|
||||
}
|
||||
|
||||
// 按日流量统计
|
||||
dayFrom := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
var dayFrom = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
dailyTrafficStats, err := models.SharedServerDailyStatDAO.FindDailyStats(tx, req.ServerId, dayFrom, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -426,8 +519,8 @@ func (this *ServerStatBoardService) ComposeServerStatBoard(ctx context.Context,
|
||||
}
|
||||
|
||||
// 小时流量统计
|
||||
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
hourTo := timeutil.Format("YmdH")
|
||||
var hourFrom = timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
var hourTo = timeutil.Format("YmdH")
|
||||
hourlyTrafficStats, err := models.SharedServerDailyStatDAO.FindHourlyStats(tx, req.ServerId, hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -387,16 +387,16 @@ func (this *UserService) UpdateUserLogin(ctx context.Context, req *pb.UpdateUser
|
||||
|
||||
// ComposeUserDashboard 取得用户Dashboard数据
|
||||
func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.ComposeUserDashboardRequest) (*pb.ComposeUserDashboardResponse, error) {
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId != req.UserId {
|
||||
return nil, this.PermissionError()
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 网站数量
|
||||
countServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", req.UserId, 0, configutils.BoolStateAll, []string{})
|
||||
@@ -404,61 +404,81 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 时间相关
|
||||
var currentMonth = timeutil.Format("Ym")
|
||||
var currentDay = timeutil.Format("Ymd")
|
||||
|
||||
// 本月总流量
|
||||
month := timeutil.Format("Ym")
|
||||
monthlyTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserMonthly(tx, req.UserId, month)
|
||||
monthlyTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserMonthly(tx, req.UserId, currentMonth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 本月带宽峰值
|
||||
monthlyPeekTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserMonthlyPeek(tx, req.UserId, 0, month)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var monthlyPeekBandwidthBytes int64 = 0
|
||||
{
|
||||
stat, err := models.SharedUserBandwidthStatDAO.FindUserPeekBandwidthInMonth(tx, req.UserId, currentMonth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if stat != nil {
|
||||
monthlyPeekBandwidthBytes = int64(stat.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// 本日带宽峰值
|
||||
var dailyPeekBandwidthBytes int64 = 0
|
||||
{
|
||||
stat, err := models.SharedUserBandwidthStatDAO.FindUserPeekBandwidthInDay(tx, req.UserId, currentDay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if stat != nil {
|
||||
dailyPeekBandwidthBytes = int64(stat.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// 今日总流量
|
||||
day := timeutil.Format("Ymd")
|
||||
dailyTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 今日带宽峰值
|
||||
dailyPeekTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserDailyPeek(tx, req.UserId, 0, day)
|
||||
dailyTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, currentDay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 近 15 日流量带宽趋势
|
||||
dailyTrafficStats := []*pb.ComposeUserDashboardResponse_DailyStat{}
|
||||
dailyPeekTrafficStats := []*pb.ComposeUserDashboardResponse_DailyStat{}
|
||||
var dailyTrafficStats = []*pb.ComposeUserDashboardResponse_DailyTrafficStat{}
|
||||
var dailyPeekBandwidthStats = []*pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{}
|
||||
|
||||
for i := 14; i >= 0; i-- {
|
||||
day := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -i))
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -i))
|
||||
|
||||
dailyTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
|
||||
// 流量
|
||||
trafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dailyPeekTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserDailyPeek(tx, req.UserId, 0, day)
|
||||
// 峰值带宽
|
||||
peekBandwidthBytesStat, err := models.SharedUserBandwidthStatDAO.FindUserPeekBandwidthInDay(tx, req.UserId, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var peekBandwidthBytes int64 = 0
|
||||
if peekBandwidthBytesStat != nil {
|
||||
peekBandwidthBytes = int64(peekBandwidthBytesStat.Bytes)
|
||||
}
|
||||
|
||||
dailyTrafficStats = append(dailyTrafficStats, &pb.ComposeUserDashboardResponse_DailyStat{Day: day, Count: dailyTrafficBytes})
|
||||
dailyPeekTrafficStats = append(dailyPeekTrafficStats, &pb.ComposeUserDashboardResponse_DailyStat{Day: day, Count: dailyPeekTrafficBytes})
|
||||
dailyTrafficStats = append(dailyTrafficStats, &pb.ComposeUserDashboardResponse_DailyTrafficStat{Day: day, Bytes: trafficBytes})
|
||||
dailyPeekBandwidthStats = append(dailyPeekBandwidthStats, &pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{Day: day, Bytes: peekBandwidthBytes})
|
||||
}
|
||||
|
||||
return &pb.ComposeUserDashboardResponse{
|
||||
CountServers: countServers,
|
||||
MonthlyTrafficBytes: monthlyTrafficBytes,
|
||||
MonthlyPeekTrafficBytes: monthlyPeekTrafficBytes,
|
||||
DailyTrafficBytes: dailyTrafficBytes,
|
||||
DailyPeekTrafficBytes: dailyPeekTrafficBytes,
|
||||
DailyTrafficStats: dailyTrafficStats,
|
||||
DailyPeekTrafficStats: dailyPeekTrafficStats,
|
||||
CountServers: countServers,
|
||||
MonthlyTrafficBytes: monthlyTrafficBytes,
|
||||
MonthlyPeekBandwidthBytes: monthlyPeekBandwidthBytes,
|
||||
DailyTrafficBytes: dailyTrafficBytes,
|
||||
DailyPeekBandwidthBytes: dailyPeekBandwidthBytes,
|
||||
DailyTrafficStats: dailyTrafficStats,
|
||||
DailyPeekBandwidthStats: dailyPeekBandwidthStats,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
228
internal/rpc/services/service_user_identity.go
Normal file
228
internal/rpc/services/service_user_identity.go
Normal file
@@ -0,0 +1,228 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
)
|
||||
|
||||
// UserIdentityService 用户身份认证服务
|
||||
type UserIdentityService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateUserIdentity 创建身份认证信息
|
||||
func (this *UserIdentityService) CreateUserIdentity(ctx context.Context, req *pb.CreateUserIdentityRequest) (*pb.CreateUserIdentityResponse, error) {
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch req.Type {
|
||||
case userconfigs.UserIdentityTypeIDCard:
|
||||
if len(req.FileIds) < 2 {
|
||||
return nil, errors.New("need for file(s) for id card")
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("unknown identity type '" + req.Type + "'")
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
identityId, err := models.SharedUserIdentityDAO.CreateUserIdentity(tx, userId, req.Type, req.RealName, req.Number, req.FileIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateUserIdentityResponse{UserIdentityId: identityId}, nil
|
||||
}
|
||||
|
||||
// FindUserEnabledUserIdentityWithType 查看身份认证信息
|
||||
func (this *UserIdentityService) FindUserEnabledUserIdentityWithType(ctx context.Context, req *pb.FindUserEnabledUserIdentityWithTypeRequest) (*pb.FindUserEnabledUserIdentityWithTypeResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
identity, err := models.SharedUserIdentityDAO.FindEnabledUserIdentityWithType(tx, req.UserId, req.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if identity == nil {
|
||||
return &pb.FindUserEnabledUserIdentityWithTypeResponse{
|
||||
UserIdentity: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindUserEnabledUserIdentityWithTypeResponse{
|
||||
UserIdentity: &pb.UserIdentity{
|
||||
Id: int64(identity.Id),
|
||||
Type: identity.Type,
|
||||
RealName: identity.RealName,
|
||||
Number: identity.Number,
|
||||
FileIds: identity.DecodeFileIds(),
|
||||
Status: identity.Status,
|
||||
CreatedAt: int64(identity.CreatedAt),
|
||||
UpdatedAt: int64(identity.UpdatedAt),
|
||||
SubmittedAt: int64(identity.SubmittedAt),
|
||||
RejectedAt: int64(identity.RejectedAt),
|
||||
VerifiedAt: int64(identity.VerifiedAt),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateUserIdentity 修改身份认证信息
|
||||
func (this *UserIdentityService) UpdateUserIdentity(ctx context.Context, req *pb.UpdateUserIdentityRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查用户
|
||||
err = models.SharedUserIdentityDAO.CheckUserIdentity(tx, userId, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
status, err := models.SharedUserIdentityDAO.FindUserIdentityStatus(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(status) > 0 && status != userconfigs.UserIdentityStatusNone {
|
||||
return nil, errors.New("identity status should be '" + userconfigs.UserIdentityStatusNone + "' instead of '" + status + "'")
|
||||
}
|
||||
|
||||
err = models.SharedUserIdentityDAO.UpdateUserIdentity(tx, req.UserIdentityId, req.Type, req.RealName, req.Number, req.FileIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// SubmitUserIdentity 提交审核身份认证信息
|
||||
func (this *UserIdentityService) SubmitUserIdentity(ctx context.Context, req *pb.SubmitUserIdentityRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查用户
|
||||
err = models.SharedUserIdentityDAO.CheckUserIdentity(tx, userId, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
status, err := models.SharedUserIdentityDAO.FindUserIdentityStatus(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(status) > 0 && status != userconfigs.UserIdentityStatusNone {
|
||||
return nil, errors.New("identity status should be '" + userconfigs.UserIdentityStatusNone + "' instead of '" + status + "'")
|
||||
}
|
||||
|
||||
err = models.SharedUserIdentityDAO.SubmitUserIdentity(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CancelUserIdentity 取消提交身份审核认证信息
|
||||
func (this *UserIdentityService) CancelUserIdentity(ctx context.Context, req *pb.CancelUserIdentityRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查用户
|
||||
err = models.SharedUserIdentityDAO.CheckUserIdentity(tx, userId, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
status, err := models.SharedUserIdentityDAO.FindUserIdentityStatus(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != userconfigs.UserIdentityStatusSubmitted {
|
||||
return nil, errors.New("identity status should be '" + userconfigs.UserIdentityStatusSubmitted + "' instead of '" + status + "'")
|
||||
}
|
||||
|
||||
err = models.SharedUserIdentityDAO.CancelUserIdentity(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// RejectUserIdentity 拒绝用户身份认证信息
|
||||
func (this *UserIdentityService) RejectUserIdentity(ctx context.Context, req *pb.RejectUserIdentityRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查状态
|
||||
status, err := models.SharedUserIdentityDAO.FindUserIdentityStatus(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != userconfigs.UserIdentityStatusSubmitted {
|
||||
return nil, errors.New("identity status should be '" + userconfigs.UserIdentityStatusSubmitted + "' instead of '" + status + "'")
|
||||
}
|
||||
|
||||
err = models.SharedUserIdentityDAO.RejectUserIdentity(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// VerifyUserIdentity 通过用户身份认证信息
|
||||
func (this *UserIdentityService) VerifyUserIdentity(ctx context.Context, req *pb.VerifyUserIdentityRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查状态
|
||||
status, err := models.SharedUserIdentityDAO.FindUserIdentityStatus(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != userconfigs.UserIdentityStatusSubmitted {
|
||||
return nil, errors.New("identity status should be '" + userconfigs.UserIdentityStatusSubmitted + "' instead of '" + status + "'")
|
||||
}
|
||||
|
||||
err = models.SharedUserIdentityDAO.VerifyUserIdentity(tx, req.UserIdentityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -78,6 +78,9 @@ var upgradeFuncs = []*upgradeVersion{
|
||||
{
|
||||
"0.4.8", upgradeV0_4_8,
|
||||
},
|
||||
{
|
||||
"0.4.9", upgradeV0_4_9,
|
||||
},
|
||||
}
|
||||
|
||||
// UpgradeSQLData 升级SQL数据
|
||||
@@ -676,7 +679,7 @@ func upgradeV0_4_7(db *dbs.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// v0.4.7
|
||||
// v0.4.8
|
||||
func upgradeV0_4_8(db *dbs.DB) error {
|
||||
// 设置edgeIPLists中的serverId
|
||||
{
|
||||
@@ -727,3 +730,65 @@ func upgradeV0_4_8(db *dbs.DB) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// v0.4.9
|
||||
func upgradeV0_4_9(db *dbs.DB) error {
|
||||
// 升级用户UI配置
|
||||
{
|
||||
one, err := db.FindOne("SELECT value FROM edgeSysSettings WHERE code=?", systemconfigs.SettingCodeUserUIConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if one != nil {
|
||||
var valueJSON = one.GetBytes("value")
|
||||
if len(valueJSON) > 0 {
|
||||
var config = &systemconfigs.UserUIConfig{}
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err == nil {
|
||||
config.ShowTrafficCharts = true
|
||||
config.ShowBandwidthCharts = true
|
||||
config.BandwidthUnit = systemconfigs.BandwidthUnitBit
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return errors.New("encode UserUIConfig failed: " + err.Error())
|
||||
} else {
|
||||
_, err := db.Exec("UPDATE edgeSysSettings SET value=? WHERE code=?", configJSON, systemconfigs.SettingCodeUserUIConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 升级管理配置
|
||||
{
|
||||
one, err := db.FindOne("SELECT value FROM edgeSysSettings WHERE code=?", systemconfigs.SettingCodeAdminSecurityConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if one != nil {
|
||||
var valueJSON = one.GetBytes("value")
|
||||
if len(valueJSON) > 0 {
|
||||
var config = &systemconfigs.SecurityConfig{}
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err == nil {
|
||||
config.DenySearchEngines = true
|
||||
config.DenySpiders = true
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return errors.New("encode SecurityConfig failed: " + err.Error())
|
||||
} else {
|
||||
_, err := db.Exec("UPDATE edgeSysSettings SET value=? WHERE code=?", configJSON, systemconfigs.SettingCodeAdminSecurityConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -194,3 +194,23 @@ func TestUpgradeSQLData_v0_4_8(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
|
||||
func TestUpgradeSQLData_v0_4_9(t *testing.T) {
|
||||
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
err = upgradeV0_4_9(db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
77
internal/utils/maps/fixed_map.go
Normal file
77
internal/utils/maps/fixed_map.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package maputils
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type FixedMap struct {
|
||||
m map[string]any
|
||||
keys []string
|
||||
|
||||
maxSize int
|
||||
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
func NewFixedMap(maxSize int) *FixedMap {
|
||||
return &FixedMap{
|
||||
m: map[string]any{},
|
||||
maxSize: maxSize,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *FixedMap) Set(key string, item any) {
|
||||
if this.maxSize <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
_, ok := this.m[key]
|
||||
if ok {
|
||||
this.m[key] = item
|
||||
|
||||
// TODO 将key转到keys末尾
|
||||
} else {
|
||||
// 是否已满
|
||||
if len(this.keys) >= this.maxSize {
|
||||
var firstKey = this.keys[0]
|
||||
delete(this.m, firstKey)
|
||||
this.keys = this.keys[1:]
|
||||
}
|
||||
|
||||
// 新加入
|
||||
this.m[key] = item
|
||||
this.keys = append(this.keys, key)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *FixedMap) Get(key string) (value any, ok bool) {
|
||||
this.locker.RLock()
|
||||
value, ok = this.m[key]
|
||||
this.locker.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (this *FixedMap) Has(key string) bool {
|
||||
this.locker.RLock()
|
||||
_, ok := this.m[key]
|
||||
this.locker.RUnlock()
|
||||
return ok
|
||||
}
|
||||
|
||||
func (this *FixedMap) Size() int {
|
||||
this.locker.RLock()
|
||||
defer this.locker.RUnlock()
|
||||
return len(this.keys)
|
||||
}
|
||||
|
||||
func (this *FixedMap) Reset() {
|
||||
this.locker.Lock()
|
||||
this.m = map[string]any{}
|
||||
this.keys = []string{}
|
||||
this.locker.Unlock()
|
||||
}
|
||||
42
internal/utils/maps/fixed_map_test.go
Normal file
42
internal/utils/maps/fixed_map_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package maputils_test
|
||||
|
||||
import (
|
||||
maputils "github.com/TeaOSLab/EdgeAPI/internal/utils/maps"
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewFixedMap(t *testing.T) {
|
||||
var a = assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
var m = maputils.NewFixedMap(5)
|
||||
m.Set("a", 1)
|
||||
m.Set("b", 2)
|
||||
a.IsTrue(m.Has("a"))
|
||||
a.IsTrue(m.Has("b"))
|
||||
a.IsFalse(m.Has("c"))
|
||||
}
|
||||
|
||||
{
|
||||
var m = maputils.NewFixedMap(5)
|
||||
m.Set("a", 1)
|
||||
m.Set("b", 2)
|
||||
m.Set("c", 3)
|
||||
m.Set("d", 4)
|
||||
m.Set("e", 5)
|
||||
a.IsTrue(m.Size() == 5)
|
||||
m.Set("f", 6)
|
||||
a.IsTrue(m.Size() == 5)
|
||||
a.IsFalse(m.Has("a"))
|
||||
}
|
||||
|
||||
{
|
||||
var m = maputils.NewFixedMap(5)
|
||||
m.Set("a", 1)
|
||||
t.Log(m.Get("a"))
|
||||
t.Log(m.Get("b"))
|
||||
}
|
||||
}
|
||||
21
internal/utils/sha1.go
Normal file
21
internal/utils/sha1.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
const sha1RandomPrefix = "SHA1_RANDOM"
|
||||
|
||||
var sha1Id int64 = 0
|
||||
|
||||
func Sha1RandomString() string {
|
||||
var s = sha1RandomPrefix + types.String(time.Now().UnixNano()) + "@" + types.String(rands.Int64()) + "@" + types.String(atomic.AddInt64(&sha1Id, 1))
|
||||
return fmt.Sprintf("%x", sha1.Sum([]byte(s)))
|
||||
}
|
||||
16
internal/utils/sha1_test.go
Normal file
16
internal/utils/sha1_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSha1Random(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
var s = utils.Sha1RandomString()
|
||||
t.Log("["+types.String(len(s))+"]", s)
|
||||
}
|
||||
}
|
||||
27
internal/utils/system.go
Normal file
27
internal/utils/system.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
)
|
||||
|
||||
var systemTotalMemory = -1
|
||||
|
||||
func init() {
|
||||
_ = SystemMemoryGB()
|
||||
}
|
||||
|
||||
func SystemMemoryGB() int {
|
||||
if systemTotalMemory > 0 {
|
||||
return systemTotalMemory
|
||||
}
|
||||
|
||||
stat, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
systemTotalMemory = int(stat.Total / 1024 / 1024 / 1024)
|
||||
return systemTotalMemory
|
||||
}
|
||||
14
internal/utils/system_test.go
Normal file
14
internal/utils/system_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSystemMemoryGB(t *testing.T) {
|
||||
t.Log(utils.SystemMemoryGB())
|
||||
t.Log(utils.SystemMemoryGB())
|
||||
t.Log(utils.SystemMemoryGB())
|
||||
}
|
||||
@@ -9,6 +9,19 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 分钟时间点
|
||||
type timeMinute struct {
|
||||
Day string
|
||||
Minute string
|
||||
}
|
||||
|
||||
// 分钟时间范围
|
||||
type timeMinuteRange struct {
|
||||
Day string
|
||||
MinuteFrom string
|
||||
MinuteTo string
|
||||
}
|
||||
|
||||
// RangeDays 计算日期之间的所有日期,格式为YYYYMMDD
|
||||
func RangeDays(dayFrom string, dayTo string) ([]string, error) {
|
||||
ok, err := regexp.MatchString(`^\d{8}$`, dayFrom)
|
||||
@@ -79,15 +92,15 @@ func RangeMonths(dayFrom string, dayTo string) ([]string, error) {
|
||||
dayFrom, dayTo = dayTo, dayFrom
|
||||
}
|
||||
|
||||
result := []string{dayFrom[:6]}
|
||||
var result = []string{dayFrom[:6]}
|
||||
|
||||
year := types.Int(dayFrom[:4])
|
||||
month := types.Int(dayFrom[4:6])
|
||||
day := types.Int(dayFrom[6:])
|
||||
t := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
|
||||
var year = types.Int(dayFrom[:4])
|
||||
var month = types.Int(dayFrom[4:6])
|
||||
var day = types.Int(dayFrom[6:])
|
||||
var t = time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
|
||||
for {
|
||||
t = t.AddDate(0, 0, 20)
|
||||
newDay := timeutil.Format("Ymd", t)
|
||||
var newDay = timeutil.Format("Ymd", t)
|
||||
if newDay <= dayTo {
|
||||
var monthString = newDay[:6]
|
||||
if !lists.ContainsString(result, monthString) {
|
||||
@@ -129,17 +142,17 @@ func RangeHours(hourFrom string, hourTo string) ([]string, error) {
|
||||
}
|
||||
|
||||
// 不能超过N天
|
||||
maxHours := 100 - 1 // -1 是去掉默认加入的dayFrom
|
||||
result := []string{hourFrom}
|
||||
var maxHours = 100 - 1 // -1 是去掉默认加入的dayFrom
|
||||
var result = []string{hourFrom}
|
||||
|
||||
year := types.Int(hourFrom[:4])
|
||||
month := types.Int(hourFrom[4:6])
|
||||
day := types.Int(hourFrom[6:8])
|
||||
hour := types.Int(hourFrom[8:])
|
||||
t := time.Date(year, time.Month(month), day, hour, 0, 0, 0, time.Local)
|
||||
var year = types.Int(hourFrom[:4])
|
||||
var month = types.Int(hourFrom[4:6])
|
||||
var day = types.Int(hourFrom[6:8])
|
||||
var hour = types.Int(hourFrom[8:])
|
||||
var t = time.Date(year, time.Month(month), day, hour, 0, 0, 0, time.Local)
|
||||
for {
|
||||
t = t.Add(1 * time.Hour)
|
||||
newHour := timeutil.Format("YmdH", t)
|
||||
var newHour = timeutil.Format("YmdH", t)
|
||||
if newHour <= hourTo {
|
||||
result = append(result, newHour)
|
||||
} else {
|
||||
@@ -154,3 +167,56 @@ func RangeHours(hourFrom string, hourTo string) ([]string, error) {
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// RangeMinutes 计算若干个时间点,返回结果为 [ [day1, minute1], [day2, minute2] ... ]
|
||||
func RangeMinutes(toTime time.Time, count int, everyMinutes int64) []timeMinute {
|
||||
var everySeconds = everyMinutes * 60
|
||||
if everySeconds <= 0 {
|
||||
everySeconds = 300
|
||||
}
|
||||
var result = []timeMinute{}
|
||||
var fromTime = time.Unix(toTime.Unix()-everySeconds*int64(count-1), 0)
|
||||
for {
|
||||
var timestamp = fromTime.Unix() / everySeconds * everySeconds
|
||||
result = append(result, timeMinute{
|
||||
Day: timeutil.FormatTime("Ymd", timestamp),
|
||||
Minute: timeutil.FormatTime("Hi", timestamp),
|
||||
})
|
||||
fromTime = time.Unix(fromTime.Unix()+everySeconds, 0)
|
||||
|
||||
count--
|
||||
if count <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GroupMinuteRanges 将时间点分组
|
||||
func GroupMinuteRanges(minutes []timeMinute) []timeMinuteRange {
|
||||
var result = []*timeMinuteRange{}
|
||||
var lastDay = ""
|
||||
var lastRange *timeMinuteRange
|
||||
for _, minute := range minutes {
|
||||
if minute.Day != lastDay {
|
||||
lastDay = minute.Day
|
||||
lastRange = &timeMinuteRange{
|
||||
Day: minute.Day,
|
||||
MinuteFrom: minute.Minute,
|
||||
MinuteTo: minute.Minute,
|
||||
}
|
||||
result = append(result, lastRange)
|
||||
} else {
|
||||
if lastRange != nil {
|
||||
lastRange.MinuteTo = minute.Minute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var finalResult = []timeMinuteRange{}
|
||||
for _, minutePtr := range result {
|
||||
finalResult = append(finalResult, *minutePtr)
|
||||
}
|
||||
return finalResult
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package utils
|
||||
package utils_test
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRangeDays(t *testing.T) {
|
||||
days, err := RangeDays("20210101", "20210115")
|
||||
days, err := utils.RangeDays("20210101", "20210115")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -11,7 +15,7 @@ func TestRangeDays(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRangeMonth(t *testing.T) {
|
||||
days, err := RangeMonths("20200101", "20210115")
|
||||
days, err := utils.RangeMonths("20200101", "20210115")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -20,7 +24,7 @@ func TestRangeMonth(t *testing.T) {
|
||||
|
||||
func TestRangeHours(t *testing.T) {
|
||||
{
|
||||
hours, err := RangeHours("2021010100", "2021010123")
|
||||
hours, err := utils.RangeHours("2021010100", "2021010123")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -28,10 +32,49 @@ func TestRangeHours(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
hours, err := RangeHours("2021010105", "2021010112")
|
||||
hours, err := utils.RangeHours("2021010105", "2021010112")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(hours)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRangeMinutes(t *testing.T) {
|
||||
{
|
||||
var minutes = utils.RangeMinutes(time.Now(), 5, 5)
|
||||
t.Log(minutes)
|
||||
}
|
||||
|
||||
{
|
||||
var minutes = utils.RangeMinutes(time.Now(), 5, 3)
|
||||
t.Log(minutes)
|
||||
}
|
||||
|
||||
{
|
||||
var now = time.Now()
|
||||
var hour = now.Hour()
|
||||
var minute = now.Minute()
|
||||
now = now.Add(-time.Duration(hour) * time.Hour)
|
||||
now = now.Add(-time.Duration(minute-7) * time.Minute) // 后一天的 00:07 开始往前计算
|
||||
var minutes = utils.RangeMinutes(now, 5, 5)
|
||||
t.Log(minutes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupMinuteRanges(t *testing.T) {
|
||||
{
|
||||
var minutes = utils.GroupMinuteRanges(utils.RangeMinutes(time.Now(), 5, 5))
|
||||
t.Log(minutes)
|
||||
}
|
||||
|
||||
{
|
||||
var now = time.Now()
|
||||
var hour = now.Hour()
|
||||
var minute = now.Minute()
|
||||
now = now.Add(-time.Duration(hour) * time.Hour)
|
||||
now = now.Add(-time.Duration(minute-7) * time.Minute) // 后一天的 00:07 开始往前计算
|
||||
var minutes = utils.GroupMinuteRanges(utils.RangeMinutes(now, 5, 5))
|
||||
t.Log(minutes)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user