package biz
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
"strings"
"voucher/internal/biz/bo"
"voucher/internal/biz/vo"
"voucher/internal/pkg/lock"
)
func (this *VoucherBiz) alarm(ctx context.Context, order *bo.OrderBo, errMsg string) error {
// 1小时 内 指定的批次号 发放 发生错误 预警
c := vo.OrderConsumeFailAlarmKey.BuildCache([]string{order.ProductNo})
_, err := this.rdb.Rdb.Get(ctx, c.Key).Result()
if err == nil {
// 缓存存在,直接返回
return nil
}
if err != redis.Nil {
return fmt.Errorf(fmt.Sprintf("alarm 获取redis缓存%s异常:%v", c.Key, err))
}
cl := vo.OrderConsumeFailAlarmLockKey.BuildCache([]string{order.ProductNo})
return lock.NewMutex(this.rdb.Rdb, cl.TTL).Lock(ctx, cl.Key, func(ctx context.Context) error {
// 二次获取,判定处理,以免获取锁后又执行了一次
cacheValue, err3 := this.rdb.Rdb.Get(ctx, c.Key).Result()
if err3 != nil && err3 != redis.Nil {
return fmt.Errorf(fmt.Sprintf("alarm 二次获取redis缓存%s异常:%v", c.Key, err))
}
if len(cacheValue) > 0 {
return nil // 有直接返回
}
// 通知
title := fmt.Sprintf("券发放异常")
if err = this.DingMixRepo.SendMarkdownMessage(ctx, title, alarmText2(order, errMsg)); err != nil {
return err
}
if err = this.rdb.Rdb.Set(ctx, c.Key, order.ProductNo, c.TTL).Err(); err != nil {
return fmt.Errorf(fmt.Sprintf("设置redis缓存%s异常:%v", c.Key, err))
}
return nil
})
}
func (this *VoucherBiz) alarmText(_ context.Context, order *bo.OrderBo, errMsg string) string {
remarks := fmt.Sprintf("订单号:%s,商品编号:%s,原因:%s", order.OrderNo, order.ProductNo, errMsg)
msg := "# " +
"立减金发放报警通知
" +
" \n" +
"" +
"券领取发生异常了" +
"[%s]" +
""
return fmt.Sprintf(msg, remarks)
}
func alarmText2(order *bo.OrderBo, errMsg string) string {
var card strings.Builder
// 警示信息(简化版)
card.WriteString("⚠️ **券发放异常** ⚠️\n\n")
// 订单信息(通过引用和代码块模拟小字体)
card.WriteString("> **订单信息:**\n\n")
card.WriteString(fmt.Sprintf("> AppID: `%s`\n\n", order.AppID))
card.WriteString(fmt.Sprintf("> OpenID: `%s`\n\n", order.Account))
card.WriteString(fmt.Sprintf("> 批次号: `%s`\n\n", order.BatchNo))
card.WriteString(fmt.Sprintf("> 活动号: `%s`\n\n", order.ProductNo))
card.WriteString(fmt.Sprintf("> 订单号: `%s`\n\n", order.OrderNo))
card.WriteString(fmt.Sprintf("> 招行订单号: `%s`\n", order.OutBizNo))
card.WriteString("\n")
// 报警原因(通过引用和代码块模拟小字体)
card.WriteString("> **❗ 报警原因:**\n\n")
card.WriteString(fmt.Sprintf("> `%s`\n", errMsg))
return card.String()
}