by Robin at 20241107

This commit is contained in:
Leufolium 2024-11-07 17:05:13 +08:00
parent 521d7694c2
commit 9b830999aa
12 changed files with 169 additions and 31 deletions

View File

@ -66,6 +66,7 @@ const (
DefaultZoneTextKey = "default_zone_text"
AuditTaskCollectionReflectKey = "audit_task_collection_reflect"
NotifBannerInfoKey = "notif_banner_info"
AcctPunishmentRealEndTimeKey = "acct_punishment_real_endtime"
)
// del_flag

View File

@ -7,8 +7,8 @@ const (
Notif_Audit = 1 // 审核消息
Notif_Vas = 2 // 付费消息
)
const (
SysNotifTemp_CancelNotif = -1 // 取消推送通知
SysNotifTemp_FirstLogin = 1 // 首次登录
SysNotifTemp_StreamerPunished = 2 // 主播封禁
SysNotifTemp_StreamerPunishmentEnds = 3 // 主播封禁结束

View File

@ -185,6 +185,7 @@ var ErrCodeMsgMap = map[ErrCode]string{
ErrCodeAccountPunishmentHasFinished: "账号处罚已正常结束,无法执行该操作!",
ErrCodeAccountPunishmentHasBeenInterrupted: "账号处罚已提前中止,无法执行该操作!",
ErrCodeAccountPunishmentStreamerOnly: "该账号处罚行为仅能对主播进行!",
ErrCodeAccountPunishmentEndTimeCalcFail: "账号处罚结束时间计算错误",
ErrCodeAccountCancellationSrvFail: "账户注销服务错误",
ErrCodeAccountCancellationNotExist: "账户注销不存在",
@ -518,6 +519,7 @@ const (
ErrCodeAccountPunishmentHasFinished ErrCode = -32005 // 账号处罚已正常结束
ErrCodeAccountPunishmentHasBeenInterrupted ErrCode = -32006 // 账号处罚已提前中止
ErrCodeAccountPunishmentStreamerOnly ErrCode = -32007 // 该账号处罚仅能对主播进行
ErrCodeAccountPunishmentEndTimeCalcFail ErrCode = -32008 // 账号处罚结束时间计算错误
// Zone: 33xxx
ErrCodeZoneSrvOk ErrCode = ErrCodeOk

View File

@ -0,0 +1,5 @@
package interfaces
type NidAccessible interface {
GetNid() int64
}

View File

@ -0,0 +1,26 @@
package apollostruct
// 账号处罚结束实际生效时间配置,用于通知推送服务
/* 在账号处罚创建时除了立即给用户推送一条封禁通知还会写一条解禁通知推送时间为处罚的结束时间
正常来说账号处罚结束时间 = 账号处罚创建时间 + 触发时长
但由于具体场景存在的时延在上述计算得到的账号处罚的结束时间处罚可能还未结束
如主播推荐列表每1个小时推送一次故它实际生效时间应该是结束时间顺延的下一个小时整点
动态推荐列表每5分钟推送一次故它实际生效时间应该是结束时间顺延的下一个5分整点*/
/* 我们认为用户实际感知到的处罚结束应该在他收到通知的时候所以解禁的通知时间需要根据具体场景延后一些
interval_map表示具体场景的定时任务每隔多少时间执行一次单位为秒
比如对于主播推荐列表时间间隔就是3600秒解禁通知的时间戳需要补足至3600秒的倍数
*/
/*
default_interval表示推送定时通知的定时任务的时间间隔
如果这条封禁的场景没有定时推送的需求则解禁通知的时间戳补足至default_interval的倍数即可
用以满足用户实际感知到的处罚结束应该在他收到通知的时候
需要注意interval_map每个键值对的值必须是default_interval的倍数否则推送通知会产生异常
*/
type AcctPunishmentRealEndtimeCfg struct {
IntervalMap map[string]int64 `json:"interval_map"` // 时间间隔map
DefaultInterval int64 `json:"default_interval"` // 默认通知时间间隔
}

View File

@ -4,7 +4,6 @@ import (
"service/api/consts"
accountpunishmentproto "service/api/proto/accountpunishment/proto"
"service/app/mix/dao"
"service/bizcommon/util"
"service/dbstruct"
"service/library/logger"
"time"
@ -36,7 +35,6 @@ func (p *AccountPunishment) OpCreate(ctx *gin.Context, req *accountpunishmentpro
nowTime := time.Now().Unix()
req.AccountPunishment.Id = goproto.Int64(accountpunishmentIdSeq.Seq)
req.AccountPunishment.Status = goproto.Int64(consts.AccountPunishment_Punishing)
req.AccountPunishment.EndTime = goproto.Int64(nowTime + util.DerefInt64(req.Duration))
req.AccountPunishment.Ct = goproto.Int64(nowTime)
req.AccountPunishment.Ut = goproto.Int64(nowTime)
req.AccountPunishment.DelFlag = goproto.Int64(consts.Exist)

View File

@ -2,12 +2,15 @@ package service
import (
"service/api/consts"
"service/api/interfaces"
accountpunishmentproto "service/api/proto/accountpunishment/proto"
zoneproto "service/api/proto/zone/proto"
"service/bizcommon/util"
"service/dbstruct"
"service/library/logger"
"github.com/gin-gonic/gin"
goproto "google.golang.org/protobuf/proto"
)
var DefaultNotifBuilderHandler *NotifBuilderHandler
@ -28,6 +31,7 @@ func NewNotifBuilderHandler() *NotifBuilderHandler {
}
func (handler *NotifBuilderHandler) init() {
handler.handleSysNotifCancelNotif()
handler.handleSysFirstLogin()
handler.handleSysStreamerPunished()
handler.handleSysPswdChanged()
@ -38,6 +42,13 @@ func (handler *NotifBuilderHandler) init() {
handler.handleSysZoneThirdPartnerCreated()
}
func (handler *NotifBuilderHandler) handleSysNotifCancelNotif() {
handler.handlerMap[consts.SysNotifTemp_CancelNotif] = func(ctx *gin.Context, args ...any) {
nidAccessor := args[0].(interfaces.NidAccessible)
DefaultService.utilWriteNotifCancel(ctx, nidAccessor)
}
}
func (handler *NotifBuilderHandler) handleSysFirstLogin() {
handler.handlerMap[consts.SysNotifTemp_FirstLogin] = func(ctx *gin.Context, args ...any) {
account := args[0].(*dbstruct.Account)
@ -53,7 +64,17 @@ func (handler *NotifBuilderHandler) handleSysStreamerPunished() {
consts.AccountPunishmentMap[acctpunishment.GetType()], util.FormatTsAsNotifT(acctpunishment.GetEndTime()))
// 解禁通知
if !acctpunishment.IsPermanent() {
DefaultService.utilWriteCrontabNotifInfo(ctx, consts.SysNotifTemp_StreamerPunishmentEnds, acctpunishment.GetMid(), acctpunishment.GetEndTime())
argsMap := make(map[string]any)
argsMap["push_time"] = acctpunishment.GetEndTime()
argsMap["nid_save_func"] = func(ctx *gin.Context, nid int64) error {
return _DefaultAccountPunishment.OpUpdate(ctx, &accountpunishmentproto.OpUpdateReq{
AccountPunishment: &dbstruct.AccountPunishment{
Id: acctpunishment.Id,
Nid: goproto.Int64(nid),
},
})
}
DefaultService.utilWriteNotifInfoByMap(ctx, consts.SysNotifTemp_StreamerPunishmentEnds, acctpunishment.GetMid(), argsMap)
}
}
}

View File

@ -3754,7 +3754,17 @@ func (s *Service) OpCreateAccountPunishment(ctx *gin.Context, req *accountpunish
return
}
err := _DefaultAccountPunishment.OpCreate(ctx, req)
// 计算处罚结束的通知时间
req.AccountPunishment.EndTime = goproto.Int64(time.Now().Unix() + util.DerefInt64(req.Duration))
realEndTime, err := s.utilCalcAccountPunishmentEndNotifTime(req.AccountPunishment)
if err != nil {
logger.Error("utilCalcAccountPunishmentEndNotifTime fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeAccountPunishmentSrvFail
return
}
req.AccountPunishment.EndTime = goproto.Int64(realEndTime)
err = _DefaultAccountPunishment.OpCreate(ctx, req)
if err != nil {
logger.Error("OpCreate fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeAccountPunishmentSrvFail
@ -3790,6 +3800,21 @@ func (s *Service) OpUnblockAccountPunishment(ctx *gin.Context, req *accountpunis
ec = errcode.ErrCodeAccountPunishmentSrvFail
return
}
// 取消该条推送
acctpunishment, err := _DefaultAccountPunishment.OpListById(ctx, util.DerefInt64(req.Id))
if err == qmgo.ErrNoSuchDocuments {
ec = errcode.ErrCodeAccountPunishmentNotExist
err = nil
return
}
if err != nil {
logger.Error("OpListById fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeAccountPunishmentSrvFail
return
}
DefaultNotifBuilderHandler.Handle(ctx, consts.SysNotifTemp_CancelNotif, acctpunishment)
return
}

View File

@ -2116,6 +2116,21 @@ func (s *Service) UtilEncryptVideosForZoneMomentVOs(ctx *gin.Context, list []*zo
}
}
func (s *Service) utilWriteNotifCancel(ctx *gin.Context, nidAccessor interfaces.NidAccessible) {
// 获取通知builder
notifBuilders := make([]*dbstruct.NotifBuilder, 0)
notifBuildersObj, ok := ctx.Get("notif_builders")
if ok {
notifBuilders = notifBuildersObj.([]*dbstruct.NotifBuilder)
}
notifBuilders = append(notifBuilders, &dbstruct.NotifBuilder{
TemplateId: consts.SysNotifTemp_CancelNotif,
NidGetter: nidAccessor.GetNid,
})
ctx.Set("notif_builders", notifBuilders)
}
func (s *Service) utilWriteNotifInfo(ctx *gin.Context, notifTempId int64, objMid int64, notifTempParams ...any) {
// 获取通知builder
notifBuilders := make([]*dbstruct.NotifBuilder, 0)
@ -2132,23 +2147,6 @@ func (s *Service) utilWriteNotifInfo(ctx *gin.Context, notifTempId int64, objMid
ctx.Set("notif_builders", notifBuilders)
}
func (s *Service) utilWriteCrontabNotifInfo(ctx *gin.Context, notifTempId int64, objMid int64, pushTime int64, notifTempParams ...any) {
// 获取通知builder
notifBuilders := make([]*dbstruct.NotifBuilder, 0)
notifBuildersObj, ok := ctx.Get("notif_builders")
if ok {
notifBuilders = notifBuildersObj.([]*dbstruct.NotifBuilder)
}
notifBuilders = append(notifBuilders, &dbstruct.NotifBuilder{
TemplateId: notifTempId,
ObjMids: []int64{objMid},
PushTime: pushTime,
TemplateParams: notifTempParams,
})
ctx.Set("notif_builders", notifBuilders)
}
func (s *Service) utilWriteNotifInfoByMap(ctx *gin.Context, notifTempId int64, objMid int64, mp map[string]any) {
// 获取通知builder
notifBuilders := make([]*dbstruct.NotifBuilder, 0)
@ -2191,6 +2189,32 @@ func (s *Service) utilWriteNotifInfoByMap(ctx *gin.Context, notifTempId int64, o
notifBuilder.PushTime = pushTimeObj.(int64)
}
nidSaveFuncObj, ok := mp["nid_save_func"]
if ok {
notifBuilder.NidSaveFunc = nidSaveFuncObj.(func(ctx *gin.Context, nid int64) error)
}
notifBuilders = append(notifBuilders, notifBuilder)
ctx.Set("notif_builders", notifBuilders)
}
func (s *Service) utilCalcAccountPunishmentEndNotifTime(acctpunishment *dbstruct.AccountPunishment) (int64, error) {
notifTime := acctpunishment.GetEndTime()
cfg := apollostruct.AcctPunishmentRealEndtimeCfg{}
err := apollo.GetJson(consts.AcctPunishmentRealEndTimeKey, &cfg, apollo.ApolloOpts().SetNamespace("application"))
if err != nil {
logger.Error("Apollo read failed : %v", err)
return 0, err
}
interval, ok := cfg.IntervalMap[fmt.Sprint(acctpunishment.GetType())]
if !ok {
interval = cfg.DefaultInterval
}
if notifTime%interval != 0 { // 已经是倍数则不再顺延
notifTime = (notifTime/interval + 1) * interval
}
return notifTime, nil
}

View File

@ -14,6 +14,7 @@ type AccountPunishment struct {
Duration *int64 `json:"duration" bson:"duration"` // 处罚时长
EndTime *int64 `json:"end_time" bson:"end_time"` // 处罚结束时间
Status *int64 `json:"status" bson:"status"` // 处罚结果
Nid *int64 `json:"nid" bson:"nid"` // 通知表id用于控制推送
Ct *int64 `json:"ct" bson:"ct"` // 创建时间
Ut *int64 `json:"ut" bson:"ut"` // 更新时间
DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记
@ -60,3 +61,10 @@ func (p *AccountPunishment) GetType() int64 {
}
return *p.Type
}
func (p *AccountPunishment) GetNid() int64 {
if p == nil || p.Nid == nil {
return 0
}
return *p.Nid
}

View File

@ -1,5 +1,9 @@
package dbstruct
import (
"github.com/gin-gonic/gin"
)
type Notification struct {
Id *int64 `json:"id" bson:"_id"` // 系统通知表id
SubMid *int64 `json:"sub_mid" bson:"sub_mid"` // 通知发送人mid
@ -104,4 +108,6 @@ type NotifBuilder struct {
Action string // 行为
Params string // 行为参数
PushTime int64 // 推送时间
NidSaveFunc func(ctx *gin.Context, nid int64) error // nid存储函数一般用于取消推送
NidGetter func() int64 // nid访问器
}

View File

@ -32,6 +32,21 @@ func InitNotifSender(_DefaultNotification *logic.Notification, _DefaultNotifBcst
notifBuilders := notifBuildersObj.([]*dbstruct.NotifBuilder)
for _, notifBuilder := range notifBuilders {
// 如果是取消推送,则更新推送状态为已取消
if notifBuilder.TemplateId == consts.SysNotifTemp_CancelNotif {
err := _DefaultNotification.OpUpdate(ctx, &notificationproto.OpUpdateReq{
Notification: &dbstruct.Notification{
Id: goproto.Int64(notifBuilder.NidGetter()),
Status: goproto.Int64(consts.Notification_Cancelled),
},
})
if err != nil {
logger.Error("_DefaultNotification OpUpdate failed : %v", err)
}
continue
}
notification := &dbstruct.Notification{}
notification.SubMid = goproto.Int64(0)
@ -80,6 +95,13 @@ func InitNotifSender(_DefaultNotification *logic.Notification, _DefaultNotifBcst
ctx.Next()
}
// 将通知id暂存若暂存失败则不广播该条通知因业务无法再控制其停止
err = notifBuilder.NidSaveFunc(ctx, notification.GetId())
if err != nil {
logger.Error("通知id暂存失败:%v", err)
continue
}
nids := make([]int64, 0)
nids = append(nids, notification.GetId())