修改app config格式

This commit is contained in:
xiabin 2025-02-24 17:27:51 +08:00
parent e92287bb62
commit 0f88992db9
9 changed files with 135 additions and 80 deletions

View File

@ -20,6 +20,9 @@ jobs:
- service: auth - service: auth
dockerfile: app/auth_service/Dockerfile dockerfile: app/auth_service/Dockerfile
image: auth image: auth
- service: admin
dockerfile: app/admin_service/Dockerfile
image: admin
steps: steps:
- uses: https://gitea.youtukeji.com.cn/actions/checkout@v4 - uses: https://gitea.youtukeji.com.cn/actions/checkout@v4
@ -44,4 +47,8 @@ jobs:
docker-compose down --remove-orphans docker-compose down --remove-orphans
docker-compose up -d --build docker-compose up -d --build
env: env:
COMPOSE_PROJECT_NAME: youtu_grpc COMPOSE_PROJECT_NAME: youtu_grpc
steps:
- name: clean up
run: |
docker rmi $(docker images -f "dangling=true" -q)

View File

@ -0,0 +1,33 @@
FROM golang:alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED=0
ENV GOPROXY=https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update --no-cache && apk add --no-cache tzdata
RUN apk add --no-cache git
WORKDIR /build
ADD go.mod .
ADD go.sum .
RUN go env -w GOPRIVATE=gitea.youtukeji.com.cn
RUN go mod download
COPY . .
RUN go build -ldflags="-s -w" -o /app/admin ./app/admin_service/admin_service.go
FROM alpine
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ=Asia/Shanghai
WORKDIR /app
COPY --from=builder /app/admin /app/admin
EXPOSE 8888
CMD ["/app/admin"]

View File

@ -22,7 +22,7 @@ message GetAppListResponse {
message AppInfo { message AppInfo {
int32 id = 1; int32 id = 1;
int32 type = 2; string type = 2;
string app_id = 3; string app_id = 3;
string secret = 4; string secret = 4;
string remark = 5; string remark = 5;

View File

@ -192,7 +192,7 @@ func (x *GetAppListResponse) GetAppList() []*AppInfo {
type AppInfo struct { type AppInfo struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Type int32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"` Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
AppId string `protobuf:"bytes,3,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"` AppId string `protobuf:"bytes,3,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"`
Secret string `protobuf:"bytes,4,opt,name=secret,proto3" json:"secret,omitempty"` Secret string `protobuf:"bytes,4,opt,name=secret,proto3" json:"secret,omitempty"`
Remark string `protobuf:"bytes,5,opt,name=remark,proto3" json:"remark,omitempty"` Remark string `protobuf:"bytes,5,opt,name=remark,proto3" json:"remark,omitempty"`
@ -239,11 +239,11 @@ func (x *AppInfo) GetId() int32 {
return 0 return 0
} }
func (x *AppInfo) GetType() int32 { func (x *AppInfo) GetType() string {
if x != nil { if x != nil {
return x.Type return x.Type
} }
return 0 return ""
} }
func (x *AppInfo) GetAppId() string { func (x *AppInfo) GetAppId() string {
@ -298,7 +298,7 @@ var file_admin_service_proto_rawDesc = string([]byte{
0x2e, 0x41, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4c, 0x69, 0x73,
0x74, 0x22, 0x9a, 0x01, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, 0x74, 0x22, 0x9a, 0x01, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x79, 0x70, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
0x65, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72,
0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,

View File

@ -4,11 +4,12 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strconv"
"gitea.youtukeji.com.cn/youtu/youtu_grpc/app/admin_service/admin_service" "gitea.youtukeji.com.cn/youtu/youtu_grpc/app/admin_service/admin_service"
"slices"
"strings"
"gitea.youtukeji.com.cn/youtu/youtu_grpc/app/admin_service/internal/svc" "gitea.youtukeji.com.cn/youtu/youtu_grpc/app/admin_service/internal/svc"
clientv3 "go.etcd.io/etcd/client/v3"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -27,53 +28,62 @@ func NewGetAppListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetApp
} }
} }
// 定义数据结构 // EcpmConfig 定义数据结构
type EcpmConfig struct { type EcpmConfig struct {
AppID string `json:"appId"` AppID string `json:"appId"`
ECPM int `json:"eCPM"` ECPM float32 `json:"eCPM"`
IPU int `json:"IPU"` IPU uint32 `json:"IPU"`
} }
type AppData struct { type AppData struct {
AppID string `json:"appId"` AppID string `json:"appId"`
AppSecret string `json:"appSecret"` AppSecret string `json:"appSecret"`
Type string `json:"type"` Type string `json:"type"`
Remark string `json:"remark"`
} }
type MergedAppInfo struct { type MergedAppInfo struct {
AppID string `json:"appId"` AppID string `json:"appId"`
ECPM int `json:"eCPM,omitempty"` ECPM float32 `json:"eCPM,omitempty"`
IPU int `json:"IPU,omitempty"` IPU uint32 `json:"IPU,omitempty"`
AppSecret string `json:"appSecret,omitempty"` AppSecret string `json:"appSecret,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
Remark string `json:"remark,omitempty"`
} }
// GetAppList 获取app列表 // GetAppList 获取app列表
func (l *GetAppListLogic) GetAppList(_ *admin_service.GetAppListRequest) (res *admin_service.GetAppListResponse, err error) { func (l *GetAppListLogic) GetAppList(_ *admin_service.GetAppListRequest) (res *admin_service.GetAppListResponse, err error) {
// 从ETCD获取ecpm配置 // 从ETCD获取ecpm配置
ecpmResp, err := l.svcCtx.EtcdClient.Get(l.ctx, "/youtu/ecpm/config") ecpmResp, err := l.svcCtx.EtcdClient.Get(l.ctx, "/youtu/app/ecpm/config", clientv3.WithPrefix())
if err != nil { if err != nil {
return nil, fmt.Errorf("获取ecpm配置失败: %v", err) return nil, fmt.Errorf("获取ecpm配置失败: %v", err)
} }
var ecpmConfigs []EcpmConfig // 解析ecpm配置
if len(ecpmResp.Kvs) > 0 { ecpmConfigs := make([]EcpmConfig, 0, len(ecpmResp.Kvs))
if err := json.Unmarshal(ecpmResp.Kvs[0].Value, &ecpmConfigs); err != nil { for _, kv := range ecpmResp.Kvs {
cfg := EcpmConfig{}
if err := json.Unmarshal(kv.Value, &cfg); err != nil {
return nil, fmt.Errorf("解析ecpm配置失败: %v", err) return nil, fmt.Errorf("解析ecpm配置失败: %v", err)
} }
cfg.AppID = strings.TrimPrefix(string(kv.Key), "/youtu/app/ecpm/config/")
ecpmConfigs = append(ecpmConfigs, cfg)
} }
// 从ETCD获取app数据 // 从ETCD获取app数据
appDataResp, err := l.svcCtx.EtcdClient.Get(l.ctx, "/youtu/appData") appDataResp, err := l.svcCtx.EtcdClient.Get(l.ctx, "/youtu/app/account", clientv3.WithPrefix())
if err != nil { if err != nil {
return nil, fmt.Errorf("获取app数据失败: %v", err) return nil, fmt.Errorf("获取app数据失败: %v", err)
} }
var appDatas []AppData appDatas := make([]AppData, 0, len(appDataResp.Kvs))
if len(appDataResp.Kvs) > 0 { for _, kv := range appDataResp.Kvs {
if err := json.Unmarshal(appDataResp.Kvs[0].Value, &appDatas); err != nil { appData := AppData{}
if err := json.Unmarshal(kv.Value, &appData); err != nil {
return nil, fmt.Errorf("解析app数据失败: %v", err) return nil, fmt.Errorf("解析app数据失败: %v", err)
} }
appData.AppID = strings.TrimPrefix(string(kv.Key), "/youtu/app/account/")
appDatas = append(appDatas, appData)
} }
// 创建合并映射 // 创建合并映射
@ -93,11 +103,13 @@ func (l *GetAppListLogic) GetAppList(_ *admin_service.GetAppListRequest) (res *a
if info, exists := merged[app.AppID]; exists { if info, exists := merged[app.AppID]; exists {
info.AppSecret = app.AppSecret info.AppSecret = app.AppSecret
info.Type = app.Type info.Type = app.Type
info.Remark = app.Remark
} else { } else {
merged[app.AppID] = &MergedAppInfo{ merged[app.AppID] = &MergedAppInfo{
AppID: app.AppID, AppID: app.AppID,
AppSecret: app.AppSecret, AppSecret: app.AppSecret,
Type: app.Type, Type: app.Type,
Remark: app.Remark,
} }
} }
} }
@ -112,17 +124,25 @@ func (l *GetAppListLogic) GetAppList(_ *admin_service.GetAppListRequest) (res *a
appInfo := &admin_service.AppInfo{ appInfo := &admin_service.AppInfo{
AppId: info.AppID, AppId: info.AppID,
Secret: info.AppSecret, Secret: info.AppSecret,
Ecpm: float32(info.ECPM), Ecpm: info.ECPM,
Ipu: uint32(info.IPU), Ipu: info.IPU,
} Type: info.Type,
Remark: info.Remark,
// 转换type为int32
if typeInt, err := strconv.Atoi(info.Type); err == nil {
appInfo.Type = int32(typeInt)
} }
res.AppList = append(res.AppList, appInfo) res.AppList = append(res.AppList, appInfo)
} }
slices.SortFunc(res.AppList, func(i, j *admin_service.AppInfo) int {
if i.AppId < j.AppId {
return -1
}
return 1
})
for i, info := range res.AppList {
info.Id = int32(i + 1)
}
return res, nil return res, nil
} }

View File

@ -14,12 +14,12 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/zeromicro/go-zero/core/conf" "github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/core/discov" "github.com/zeromicro/go-zero/core/discov"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/zrpc" "github.com/zeromicro/go-zero/zrpc"
clientv3 "go.etcd.io/etcd/client/v3" clientv3 "go.etcd.io/etcd/client/v3"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"strings"
) )
type ServiceContext struct { type ServiceContext struct {
@ -73,7 +73,7 @@ type AppData struct {
type AppDataList []AppData type AppDataList []AppData
const AppDataWatchKey = "/youtu/appData" const AppDataWatchKey = "/youtu/app/account/"
func (svc *ServiceContext) InitClient() { func (svc *ServiceContext) InitClient() {
@ -85,37 +85,37 @@ func (svc *ServiceContext) InitClient() {
} }
go func() { go func() {
ch := make(chan []byte) ch := make(chan config.WatchKV)
go config.EtcdGetOneAndWatch(context.TODO(), cli, AppDataWatchKey, ch) go config.EtcdGetOneAndWatch(context.TODO(), cli, AppDataWatchKey, ch)
//从通道中尝试取值(监视的信息) //从通道中尝试取值(监视的信息)
for res := range ch { for res := range ch {
var appDataArr AppDataList appData := AppData{}
err = json.Unmarshal(res, &appDataArr) err = json.Unmarshal(res.Value, &appData)
if err != nil { if err != nil {
logx.Errorf("etcd watch %s json.Unmarshal: %v", AppDataWatchKey, err) logx.Errorf("etcd watch %s json.Unmarshal: %v", AppDataWatchKey, err)
continue continue
} }
svc.SaveDW(appDataArr, svc.dwCache)
appData.AppId = strings.TrimPrefix(res.Key, AppDataWatchKey)
svc.SaveDW(appData, svc.dwCache)
} }
}() }()
} }
func (svc *ServiceContext) SaveDW(arr []AppData, dwCache cache.Cache) { func (svc *ServiceContext) SaveDW(v AppData, dwCache cache.Cache) {
svc.Cli.Clear()
//配置小程序cli抖音&微信) //配置小程序cli抖音&微信)
for _, v := range arr { var c cli2.DWClient
var c cli2.DWClient switch v.Type {
switch v.Type { case cli2.DouyinClientType:
case cli2.DouyinClientType: c = cli2.NewDouYinApi(v.AppId, v.AppSecret, dwCache)
c = cli2.NewDouYinApi(v.AppId, v.AppSecret, dwCache) case cli2.WechatClientType:
case cli2.WechatClientType: c = cli2.NewWechatApi(v.AppId, v.AppSecret, dwCache)
c = cli2.NewWechatApi(v.AppId, v.AppSecret, dwCache) default:
default: return
continue
}
svc.Cli.Set(v.AppId, c)
} }
svc.Cli.Set(v.AppId, c)
} }
func (svc *ServiceContext) DeleteDWCache(appId string) (err error) { func (svc *ServiceContext) DeleteDWCache(appId string) (err error) {

View File

@ -41,13 +41,17 @@ func (c *EcpmConfigCli) SetAll(list []Ecpm) {
} }
} }
func (c *EcpmConfigCli) SetAllByJson(data []byte) { func (c *EcpmConfigCli) SetEcpm(list Ecpm) {
var list []Ecpm c.Map.Store(list.AppId, &list)
}
func (c *EcpmConfigCli) SetAllByJson(appId string, data []byte) {
var list Ecpm
err := json.Unmarshal(data, &list) err := json.Unmarshal(data, &list)
if err != nil { if err != nil {
return return
} }
list.AppId = appId
slog.Info("set ecpm config", slog.AnyValue(list)) slog.Info("set ecpm config", slog.AnyValue(list))
c.SetAll(list) c.SetEcpm(list)
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/zeromicro/go-zero/core/discov" "github.com/zeromicro/go-zero/core/discov"
"github.com/zeromicro/go-zero/zrpc" "github.com/zeromicro/go-zero/zrpc"
clientv3 "go.etcd.io/etcd/client/v3" clientv3 "go.etcd.io/etcd/client/v3"
"strings"
) )
type ServiceContext struct { type ServiceContext struct {
@ -32,7 +33,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
return svc return svc
} }
const EcpmConfigWatchKey = "/youtu/ecpm/config" const EcpmConfigWatchKey = "/youtu/app/ecpm/config/"
func (svc *ServiceContext) initEtcd() { func (svc *ServiceContext) initEtcd() {
@ -44,28 +45,13 @@ func (svc *ServiceContext) initEtcd() {
panic(err) panic(err)
} }
//获取ecpm配置 ch := make(chan config.WatchKV)
res, err := cli.Get(context.Background(), EcpmConfigWatchKey) go config.EtcdGetOneAndWatch(context.Background(), cli, EcpmConfigWatchKey, ch)
if err != nil {
panic(err)
}
//设置ecpm配置 for res := range ch {
for _, kv := range res.Kvs { svc.EcpmConfig.SetAllByJson(strings.TrimPrefix(res.Key, EcpmConfigWatchKey), res.Value)
svc.EcpmConfig.SetAllByJson(kv.Value)
} }
//监听etcd
go func() {
ch := cli.Watch(context.Background(), EcpmConfigWatchKey)
//从通道中尝试取值(监视的信息)
for res := range ch {
for _, evt := range res.Events {
svc.EcpmConfig.SetAllByJson(evt.Kv.Value)
}
}
}()
svc.etcdCli = cli svc.etcdCli = cli
} }

View File

@ -77,21 +77,26 @@ func SetConfig(b, serverName string) (err error) {
return return
} }
type WatchKV struct {
Key string
Value []byte
}
// EtcdGetOneAndWatch 获取etcd配置并监听对应的key // EtcdGetOneAndWatch 获取etcd配置并监听对应的key
func EtcdGetOneAndWatch(ctx context.Context, cli *clientv3.Client, key string, ch chan []byte) { func EtcdGetOneAndWatch(ctx context.Context, cli *clientv3.Client, key string, ch chan WatchKV) {
defer close(ch) defer close(ch)
b, err := cli.Get(ctx, key) b, err := cli.Get(ctx, key, clientv3.WithPrefix())
if err != nil { if err != nil {
return return
} }
for _, kv := range b.Kvs { for _, kv := range b.Kvs {
ch <- kv.Value ch <- WatchKV{Key: string(kv.Key), Value: kv.Value}
} }
resCh := cli.Watch(ctx, key) resCh := cli.Watch(ctx, key, clientv3.WithPrefix())
for res := range resCh { for res := range resCh {
for _, event := range res.Events { for _, event := range res.Events {
ch <- event.Kv.Value ch <- WatchKV{Key: string(event.Kv.Key), Value: event.Kv.Value}
} }
} }