增加双端下载
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
package cpcDownloadCfgSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"stat/api/proto"
|
||||
"stat/common/genId"
|
||||
"stat/common/log"
|
||||
"stat/models/cpcDownloadCfg"
|
||||
"stat/service/cacheSer"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
const (
|
||||
cacheTTL = 2 * time.Minute
|
||||
)
|
||||
|
||||
func cacheKey(appId int32, channel string) string {
|
||||
return fmt.Sprintf("cpc_download_cfg#%d#%s", appId, channel)
|
||||
}
|
||||
|
||||
// findEnabled 按 (appId, channel) 命中启用的配置;命中缓存(包含未找到的负缓存)
|
||||
func findEnabled(ctx context.Context, appId int32, channel string) *cpcDownloadCfg.CpcDownloadCfg {
|
||||
key := cacheKey(appId, channel)
|
||||
if v, ok := cacheSer.Cache.Get(key); ok {
|
||||
if doc, ok := v.(*cpcDownloadCfg.CpcDownloadCfg); ok {
|
||||
return doc
|
||||
}
|
||||
// 负缓存
|
||||
return nil
|
||||
}
|
||||
filter := bson.M{
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.AppId: appId,
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.Channel: channel,
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.Status: true,
|
||||
}
|
||||
doc, err := cpcDownloadCfg.FindOneCpcDownloadCfg(ctx, filter)
|
||||
if err != nil {
|
||||
// 写入负缓存,避免高频未命中击穿
|
||||
cacheSer.Cache.Set(key, false, cacheTTL)
|
||||
return nil
|
||||
}
|
||||
cacheSer.Cache.Set(key, doc, cacheTTL)
|
||||
return doc
|
||||
}
|
||||
|
||||
// GetLandingPage 按 appId+channel 获取 iOS 落地页 URL,无配置返回空字符串
|
||||
func GetLandingPage(ctx context.Context, appId int32, channel string) string {
|
||||
if doc := findEnabled(ctx, appId, channel); doc != nil {
|
||||
return doc.LandingPage
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetDownloadUrl 按 appId+channel 获取 Android 下载地址,无配置返回空字符串
|
||||
func GetDownloadUrl(ctx context.Context, appId int32, channel string) string {
|
||||
if doc := findEnabled(ctx, appId, channel); doc != nil {
|
||||
return doc.DownloadUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetIosDownSuff 按 appId+channel 获取 mobileconfig 文件名
|
||||
func GetIosDownSuff(ctx context.Context, appId int32, channel string) string {
|
||||
if doc := findEnabled(ctx, appId, channel); doc != nil {
|
||||
return doc.IosDownSuff
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func invalidateCache(appId int32, channel string) {
|
||||
cacheSer.Cache.Delete(cacheKey(appId, channel))
|
||||
}
|
||||
|
||||
// List 后台列表
|
||||
func List(ctx context.Context, req *proto.CpcDownloadCfgListReq) (*proto.CpcDownloadCfgListResp, error) {
|
||||
resp := &proto.CpcDownloadCfgListResp{
|
||||
Total: 0,
|
||||
List: make(cpcDownloadCfg.CpcDownloadCfgList, 0),
|
||||
}
|
||||
filter := bson.M{}
|
||||
if req.AppId != nil {
|
||||
filter[cpcDownloadCfg.FN.CpcDownloadCfg.AppId] = *req.AppId
|
||||
}
|
||||
if req.Channel != "" {
|
||||
filter[cpcDownloadCfg.FN.CpcDownloadCfg.Channel] = req.Channel
|
||||
}
|
||||
if req.Status != nil {
|
||||
filter[cpcDownloadCfg.FN.CpcDownloadCfg.Status] = *req.Status
|
||||
}
|
||||
|
||||
total, err := cpcDownloadCfg.CountCpcDownloadCfgs(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opt := &options.FindOptions{}
|
||||
opt.SetSort(bson.D{{Key: cpcDownloadCfg.FN.CpcDownloadCfg.CreatedAt, Value: -1}})
|
||||
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||
opt.SetLimit(req.PageSize)
|
||||
list, err := cpcDownloadCfg.FindManyCpcDownloadCfg(ctx, filter, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Total = total
|
||||
resp.List = list
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Add 新增
|
||||
func Add(ctx context.Context, req *proto.AddCpcDownloadCfgReq) error {
|
||||
now := time.Now()
|
||||
doc := &cpcDownloadCfg.CpcDownloadCfg{
|
||||
Id: genId.GetCpcDownloadCfgId(),
|
||||
AppId: req.AppId,
|
||||
Channel: req.Channel,
|
||||
LandingPage: req.LandingPage,
|
||||
DownloadUrl: req.DownloadUrl,
|
||||
IosDownSuff: req.IosDownSuff,
|
||||
Remark: req.Remark,
|
||||
Status: req.Status,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := cpcDownloadCfg.InsertOneCpcDownloadCfg(ctx, doc); err != nil {
|
||||
return err
|
||||
}
|
||||
invalidateCache(doc.AppId, doc.Channel)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update 更新
|
||||
func Update(ctx context.Context, req *proto.UpdateCpcDownloadCfgReq) error {
|
||||
old, err := cpcDownloadCfg.FindOneCpcDownloadCfg(ctx, bson.M{
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.Id: req.Id,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
set := bson.M{
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.UpdatedAt: time.Now(),
|
||||
}
|
||||
if req.AppId != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.AppId] = *req.AppId
|
||||
}
|
||||
if req.Channel != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.Channel] = *req.Channel
|
||||
}
|
||||
if req.LandingPage != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.LandingPage] = *req.LandingPage
|
||||
}
|
||||
if req.DownloadUrl != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.DownloadUrl] = *req.DownloadUrl
|
||||
}
|
||||
if req.IosDownSuff != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.IosDownSuff] = *req.IosDownSuff
|
||||
}
|
||||
if req.Remark != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.Remark] = *req.Remark
|
||||
}
|
||||
if req.Status != nil {
|
||||
set[cpcDownloadCfg.FN.CpcDownloadCfg.Status] = *req.Status
|
||||
}
|
||||
if err := cpcDownloadCfg.UpdateOneCpcDownloadCfg(ctx, bson.M{
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.Id: req.Id,
|
||||
}, bson.M{"$set": set}); err != nil {
|
||||
return err
|
||||
}
|
||||
// 同时清空旧 key 与新 key
|
||||
invalidateCache(old.AppId, old.Channel)
|
||||
if req.AppId != nil || req.Channel != nil {
|
||||
newAppId := old.AppId
|
||||
newChannel := old.Channel
|
||||
if req.AppId != nil {
|
||||
newAppId = *req.AppId
|
||||
}
|
||||
if req.Channel != nil {
|
||||
newChannel = *req.Channel
|
||||
}
|
||||
invalidateCache(newAppId, newChannel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Del 删除
|
||||
func Del(ctx context.Context, id int64) error {
|
||||
old, err := cpcDownloadCfg.FindOneCpcDownloadCfg(ctx, bson.M{
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.Id: id,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn("cpcDownloadCfg Del FindOne failed", log.E(err))
|
||||
}
|
||||
if _, err := cpcDownloadCfg.DelOneCpcDownloadCfg(ctx, bson.M{
|
||||
cpcDownloadCfg.FN.CpcDownloadCfg.Id: id,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if old != nil {
|
||||
invalidateCache(old.AppId, old.Channel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user