完善ecpm模块
This commit is contained in:
parent
2ec91867f2
commit
e13b3dfa8c
@ -1,6 +1,6 @@
|
|||||||
Name: douyinecpmcalculationservice.rpc
|
Name: douyin_ecpm_calculation_service.rpc
|
||||||
ListenOn: 0.0.0.0:8080
|
ListenOn: 0.0.0.0:8080
|
||||||
Etcd:
|
Etcd:
|
||||||
Hosts:
|
Hosts:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
Key: douyinecpmcalculationservice.rpc
|
Key: douyin_ecpm_calculation_service.rpc
|
||||||
|
@ -2,6 +2,14 @@ package logic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/auth_service/auth_service"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/douyin_ecpm_calculation_service/douyin_ecpm_calculation_service"
|
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/douyin_ecpm_calculation_service/douyin_ecpm_calculation_service"
|
||||||
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/douyin_ecpm_calculation_service/internal/svc"
|
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/douyin_ecpm_calculation_service/internal/svc"
|
||||||
@ -23,8 +31,157 @@ func NewGetEcpmLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEcpmLo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *GetEcpmLogic) GetEcpm(in *douyin_ecpm_calculation_service.GetEcpmRequest) (*douyin_ecpm_calculation_service.GetEcpmResponse, error) {
|
func (l *GetEcpmLogic) GetEcpm(in *douyin_ecpm_calculation_service.GetEcpmRequest) (response *douyin_ecpm_calculation_service.GetEcpmResponse, err error) {
|
||||||
// todo: add your logic here and delete this line
|
//获取抖音accessToken
|
||||||
|
res, err := l.svcCtx.AuthServiceClient.GetAccessToken(l.ctx, &auth_service.GetAccessTokenRequest{
|
||||||
return &douyin_ecpm_calculation_service.GetEcpmResponse{}, nil
|
AppId: in.AppId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取抖音ECPM数据
|
||||||
|
list, err := GetEcpmData(res.AccessToken, in.AppId, in.OpenId, time.Now().Format(time.DateOnly))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算ECPM具体值
|
||||||
|
ecpm := CalcEcpm(list)
|
||||||
|
|
||||||
|
//获取后端配置的ECPM值
|
||||||
|
config, ok := l.svcCtx.EcpmConfig.Get(in.AppId)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("未找到小程序配置")
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断是否满足条件
|
||||||
|
if ecpm > config.Value && len(list) > config.View {
|
||||||
|
response.Ok = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算ECPM值
|
||||||
|
func CalcEcpm(res []Record) (ecpm float64) {
|
||||||
|
// 计算 ECPM
|
||||||
|
totalRecords := len(res)
|
||||||
|
|
||||||
|
// 如果没有记录,则返回 0
|
||||||
|
if totalRecords == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
totalCost := 0
|
||||||
|
|
||||||
|
for _, record := range res {
|
||||||
|
totalCost += record.Cost
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总 cost / 100000 * 1000 / 总记录数
|
||||||
|
ecpm = float64(totalCost) / 100000 * 1000 / float64(totalRecords)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEcpmData 获取ECPM数据
|
||||||
|
// appId: 小程序id
|
||||||
|
// openId: 抖音openId
|
||||||
|
// dateHour: 日期
|
||||||
|
func GetEcpmData(accessToken, appId, openId, dateHour string) (list []Record, err error) {
|
||||||
|
list, err = GetEcpm(GetEcpmParams{
|
||||||
|
AppId: appId,
|
||||||
|
OpenId: openId,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
DateHour: dateHour,
|
||||||
|
PageSize: 500,
|
||||||
|
PageNo: 1,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const getEcpm = "https://minigame.zijieapi.com/mgplatform/api/apps/data/get_ecpm" // 获取ECPM
|
||||||
|
|
||||||
|
// GetEcpm 获取ECPM
|
||||||
|
// https://bytedance.larkoffice.com/docx/Vg4yd0RDSovZINxJDyIc6THhnod
|
||||||
|
// 根据分页大小循环获取,聚合总数返回
|
||||||
|
func GetEcpm(params GetEcpmParams) (list []Record, err error) {
|
||||||
|
fullURL := fmt.Sprintf("%s?open_id=%s&mp_id=%s&access_token=%s&date_hour=%s&page_size=500&page_no=", getEcpm, params.OpenId, params.AppId, params.AccessToken, params.DateHour)
|
||||||
|
for {
|
||||||
|
fullURL += strconv.Itoa(params.PageNo)
|
||||||
|
var responseBody []byte
|
||||||
|
func() {
|
||||||
|
// 调用抖音 API
|
||||||
|
var resp *http.Response
|
||||||
|
resp, err = http.Get(fullURL)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("调用抖音 API 失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
// 读取抖音 API 响应数据
|
||||||
|
responseBody, err = io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("读取抖音 API 响应失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 解析抖音 API 响应数据
|
||||||
|
var apiResponse GetEcpmResponseData
|
||||||
|
err = json.Unmarshal(responseBody, &apiResponse)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("解析 API 响应数据失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 API 是否返回错误
|
||||||
|
if apiResponse.ErrNo != 0 {
|
||||||
|
err = fmt.Errorf("抖音 API 返回错误: %s (错误码: %d)", apiResponse.ErrMsg, apiResponse.ErrNo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list = append(list, apiResponse.Data.Records...)
|
||||||
|
|
||||||
|
// 当页数据小于总页数时,无更多数据,返回
|
||||||
|
if len(apiResponse.Data.Records) <= params.PageSize {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params.PageNo++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEcpmParams 获取ECPM参数
|
||||||
|
type GetEcpmParams struct {
|
||||||
|
AppId string `json:"app_id" form:"app_id"`
|
||||||
|
OpenId string `json:"open_id" form:"open_id"`
|
||||||
|
AccessToken string `json:"access_token" form:"access_token"`
|
||||||
|
DateHour string `json:"date_hour" form:"date_hour"`
|
||||||
|
PageSize int `json:"page_size" form:"page_size"`
|
||||||
|
PageNo int `json:"page_no" form:"page_no"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetEcpmResponseData struct {
|
||||||
|
BaseResp struct {
|
||||||
|
StatusCode int `json:"StatusCode"`
|
||||||
|
StatusMessage string `json:"StatusMessage"`
|
||||||
|
} `json:"BaseResp"`
|
||||||
|
Data struct {
|
||||||
|
Records []Record `json:"records"`
|
||||||
|
Total int `json:"total"`
|
||||||
|
} `json:"data"`
|
||||||
|
ErrMsg string `json:"err_msg"`
|
||||||
|
ErrNo int `json:"err_no"`
|
||||||
|
LogID string `json:"log_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Record struct {
|
||||||
|
Aid string `json:"aid"`
|
||||||
|
Cost int `json:"cost"`
|
||||||
|
Did string `json:"did"`
|
||||||
|
EventName string `json:"event_name"`
|
||||||
|
EventTime string `json:"event_time"`
|
||||||
|
OpenID string `json:"open_id"`
|
||||||
|
ID int `json:"id"`
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,5 @@ func NewPingLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PingLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *PingLogic) Ping(in *douyin_ecpm_calculation_service.Request) (*douyin_ecpm_calculation_service.Response, error) {
|
func (l *PingLogic) Ping(in *douyin_ecpm_calculation_service.Request) (*douyin_ecpm_calculation_service.Response, error) {
|
||||||
// todo: add your logic here and delete this line
|
return &douyin_ecpm_calculation_service.Response{Pong: in.Ping}, nil
|
||||||
|
|
||||||
return &douyin_ecpm_calculation_service.Response{}, nil
|
|
||||||
}
|
}
|
||||||
|
51
douyin_ecpm_calculation_service/internal/svc/ecpm_config.go
Normal file
51
douyin_ecpm_calculation_service/internal/svc/ecpm_config.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package svc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EcpmConfigCli struct {
|
||||||
|
*sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEcpmConfig() *EcpmConfigCli {
|
||||||
|
return &EcpmConfigCli{
|
||||||
|
Map: &sync.Map{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ecpm struct {
|
||||||
|
AppId string `json:"app_id"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
View int `json:"view"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EcpmConfigCli) Get(appId string) (*Ecpm, bool) {
|
||||||
|
v, ok := c.Map.Load(appId)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return v.(*Ecpm), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EcpmConfigCli) Set(appId string, ecpmConfig *Ecpm) {
|
||||||
|
c.Map.Store(appId, ecpmConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EcpmConfigCli) SetAll(list []Ecpm) {
|
||||||
|
c.Map.Clear()
|
||||||
|
for _, v := range list {
|
||||||
|
c.Map.Store(v.AppId, &v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EcpmConfigCli) SetAllByJson(data []byte) {
|
||||||
|
var list []Ecpm
|
||||||
|
err := json.Unmarshal(data, &list)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.SetAll(list)
|
||||||
|
}
|
@ -1,13 +1,85 @@
|
|||||||
package svc
|
package svc
|
||||||
|
|
||||||
import "gitea.youtukeji.com.cn/xiabin/youtu_grpc/douyin_ecpm_calculation_service/internal/config"
|
import (
|
||||||
|
"context"
|
||||||
|
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/auth_service/auth_service"
|
||||||
|
"gitea.youtukeji.com.cn/xiabin/youtu_grpc/douyin_ecpm_calculation_service/internal/config"
|
||||||
|
"github.com/zeromicro/go-zero/core/conf"
|
||||||
|
"github.com/zeromicro/go-zero/core/discov"
|
||||||
|
"github.com/zeromicro/go-zero/zrpc"
|
||||||
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
)
|
||||||
|
|
||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
|
AuthServiceClient auth_service.AuthServiceClient
|
||||||
|
etcdCli *clientv3.Client
|
||||||
|
EcpmConfig *EcpmConfigCli
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
return &ServiceContext{
|
svc := &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//初始化etcd客户端
|
||||||
|
svc.initEtcd()
|
||||||
|
|
||||||
|
//初始化auth_service客户端
|
||||||
|
svc.initAuthServiceClient()
|
||||||
|
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
const EcpmConfigWatchKey = "ecpm_config"
|
||||||
|
|
||||||
|
func (svc *ServiceContext) initEtcd() {
|
||||||
|
|
||||||
|
//初始化etcd客户端
|
||||||
|
cli, err := clientv3.NewFromURL(svc.Config.Etcd.Hosts[0])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取ecpm配置
|
||||||
|
res, err := cli.Get(context.Background(), EcpmConfigWatchKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置ecpm配置
|
||||||
|
for _, kv := range res.Kvs {
|
||||||
|
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.EcpmConfig = NewEcpmConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
// initAuthServiceClient inits the AuthServiceClient.
|
||||||
|
func (svc *ServiceContext) initAuthServiceClient() {
|
||||||
|
clientConf := zrpc.RpcClientConf{}
|
||||||
|
clientConf.Token = "auth_service.rpc.key"
|
||||||
|
clientConf.App = "auth_service.rpc"
|
||||||
|
err := conf.FillDefault(&clientConf) // 填充默认值,比如 trace 透传等,参考服务配置说明
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
clientConf.Etcd = discov.EtcdConf{ // 通过 etcd 服务发现
|
||||||
|
Hosts: svc.Config.Etcd.Hosts,
|
||||||
|
Key: "auth_service.rpc",
|
||||||
|
}
|
||||||
|
|
||||||
|
svc.AuthServiceClient = auth_service.NewAuthServiceClient(zrpc.MustNewClient(clientConf).Conn())
|
||||||
}
|
}
|
||||||
|
13
go.mod
13
go.mod
@ -6,13 +6,18 @@ toolchain go1.23.6
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.0-20250123094517-b5871b3f4784
|
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.0-20250123094517-b5871b3f4784
|
||||||
|
github.com/go-gorm/caches/v4 v4.0.5
|
||||||
github.com/silenceper/wechat/v2 v2.1.7
|
github.com/silenceper/wechat/v2 v2.1.7
|
||||||
github.com/zeromicro/go-zero v1.8.0
|
github.com/zeromicro/go-zero v1.8.0
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.18
|
||||||
google.golang.org/grpc v1.70.0
|
google.golang.org/grpc v1.70.0
|
||||||
google.golang.org/protobuf v1.36.4
|
google.golang.org/protobuf v1.36.4
|
||||||
|
gorm.io/driver/mysql v1.5.7
|
||||||
|
gorm.io/gorm v1.25.12
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
@ -29,6 +34,7 @@ require (
|
|||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||||
github.com/go-openapi/swag v0.22.4 // indirect
|
github.com/go-openapi/swag v0.22.4 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
@ -37,6 +43,8 @@ require (
|
|||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.17.9 // indirect
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
@ -54,9 +62,8 @@ require (
|
|||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.7.0 // indirect
|
github.com/redis/go-redis/v9 v9.7.0 // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
go.etcd.io/etcd/api/v3 v3.5.15 // indirect
|
go.etcd.io/etcd/api/v3 v3.5.18 // indirect
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.5.18 // indirect
|
||||||
go.etcd.io/etcd/client/v3 v3.5.15 // indirect
|
|
||||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
|
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
|
||||||
|
28
go.sum
28
go.sum
@ -1,3 +1,5 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.0-20250123094517-b5871b3f4784 h1:Ey/s51gRB3rpN/TCXY1rAqZulktSlkdXrxyfBtnEtAc=
|
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.0-20250123094517-b5871b3f4784 h1:Ey/s51gRB3rpN/TCXY1rAqZulktSlkdXrxyfBtnEtAc=
|
||||||
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.0-20250123094517-b5871b3f4784/go.mod h1:o3XiYjUmxptrwcYPbTwNc2SQSOeOj7qbQPdNNVU0H5w=
|
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.0-20250123094517-b5871b3f4784/go.mod h1:o3XiYjUmxptrwcYPbTwNc2SQSOeOj7qbQPdNNVU0H5w=
|
||||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||||
@ -43,6 +45,8 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
|
|||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/go-gorm/caches/v4 v4.0.5 h1:Sdj9vxbEM0sCmv5+s5o6GzoVMuraWF0bjJJvUU+7c1U=
|
||||||
|
github.com/go-gorm/caches/v4 v4.0.5/go.mod h1:Ms8LnWVoW4GkTofpDzFH8OfDGNTjLxQDyxBmRN67Ujw=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
@ -58,6 +62,9 @@ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogB
|
|||||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
@ -100,6 +107,10 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslC
|
|||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
@ -206,12 +217,12 @@ github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M
|
|||||||
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||||
github.com/zeromicro/go-zero v1.8.0 h1:4g/8VW+fOyM51HZYPeI3mXIZdEX+Fl6SsdYX2H5PYw4=
|
github.com/zeromicro/go-zero v1.8.0 h1:4g/8VW+fOyM51HZYPeI3mXIZdEX+Fl6SsdYX2H5PYw4=
|
||||||
github.com/zeromicro/go-zero v1.8.0/go.mod h1:xDBF+/iDzj30zPvu6HNUIbpz1J6+/g3Sx9D/DytJfss=
|
github.com/zeromicro/go-zero v1.8.0/go.mod h1:xDBF+/iDzj30zPvu6HNUIbpz1J6+/g3Sx9D/DytJfss=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.15 h1:3KpLJir1ZEBrYuV2v+Twaa/e2MdDCEZ/70H+lzEiwsk=
|
go.etcd.io/etcd/api/v3 v3.5.18 h1:Q4oDAKnmwqTo5lafvB+afbgCDF7E35E4EYV2g+FNGhs=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.15/go.mod h1:N9EhGzXq58WuMllgH9ZvnEr7SI9pS0k0+DHZezGp7jM=
|
go.etcd.io/etcd/api/v3 v3.5.18/go.mod h1:uY03Ob2H50077J7Qq0DeehjM/A9S8PhVfbQ1mSaMopU=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.15 h1:fo0HpWz/KlHGMCC+YejpiCmyWDEuIpnTDzpJLB5fWlA=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.18 h1:mZPOYw4h8rTk7TeJ5+3udUkfVGBqc+GCjOJYd68QgNM=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.15/go.mod h1:mXDI4NAOwEiszrHCb0aqfAYNCrZP4e9hRca3d1YK8EU=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.18/go.mod h1:BxVf2o5wXG9ZJV+/Cu7QNUiJYk4A29sAhoI5tIRsCu4=
|
||||||
go.etcd.io/etcd/client/v3 v3.5.15 h1:23M0eY4Fd/inNv1ZfU3AxrbbOdW79r9V9Rl62Nm6ip4=
|
go.etcd.io/etcd/client/v3 v3.5.18 h1:nvvYmNHGumkDjZhTHgVU36A9pykGa2K4lAJ0yY7hcXA=
|
||||||
go.etcd.io/etcd/client/v3 v3.5.15/go.mod h1:CLSJxrYjvLtHsrPKsy7LmZEE+DK2ktfd2bN4RhBMwlU=
|
go.etcd.io/etcd/client/v3 v3.5.18/go.mod h1:kmemwOsPU9broExyhYsBxX4spCTDX3yLgPMWtpBXG6E=
|
||||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
|
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
|
||||||
@ -352,6 +363,11 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||||
|
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||||
|
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
|
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||||
|
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||||
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
|
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
|
||||||
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
|
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
|
||||||
k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q=
|
k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q=
|
||||||
|
24
pkg/gorm/init_db.go
Normal file
24
pkg/gorm/init_db.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package gorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
redisCacher "gitea.youtukeji.com.cn/xiabin/youtu_grpc/pkg/gorm/redis"
|
||||||
|
"github.com/go-gorm/caches/v4"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewDBWithCache(dataSource gorm.Dialector, config *gorm.Config, redisClient *redis.Client) (db *gorm.DB, err error) {
|
||||||
|
db, err = gorm.Open(dataSource, config)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = UseCache(db, redisClient)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func UseCache(db *gorm.DB, redisClient *redis.Client) (err error) {
|
||||||
|
return db.Use(&caches.Caches{Conf: &caches.Config{
|
||||||
|
Easer: true,
|
||||||
|
Cacher: redisCacher.New(redisClient),
|
||||||
|
}})
|
||||||
|
}
|
73
pkg/gorm/redis/cacher.go
Normal file
73
pkg/gorm/redis/cacher.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/go-gorm/caches/v4"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cacher struct {
|
||||||
|
rdb *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(rdb *redis.Client) *Cacher {
|
||||||
|
return &Cacher{rdb: rdb}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cacher) Get(ctx context.Context, key string, q *caches.Query[any]) (*caches.Query[any], error) {
|
||||||
|
res, err := c.rdb.Get(ctx, key).Result()
|
||||||
|
if errors.Is(err, redis.Nil) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.Unmarshal([]byte(res)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return q, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cacher) Store(ctx context.Context, key string, val *caches.Query[any]) error {
|
||||||
|
res, err := val.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.rdb.Set(ctx, key, res, 300*time.Second) // Set proper cache time
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cacher) Invalidate(ctx context.Context) error {
|
||||||
|
var (
|
||||||
|
cursor uint64
|
||||||
|
keys []string
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
var (
|
||||||
|
k []string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
k, cursor, err = c.rdb.Scan(ctx, cursor, fmt.Sprintf("%s*", caches.IdentifierPrefix), 0).Result()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
keys = append(keys, k...)
|
||||||
|
if cursor == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(keys) > 0 {
|
||||||
|
if _, err := c.rdb.Del(ctx, keys...).Result(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user