diff --git a/configs/config_test.yaml b/configs/config_test.yaml
index 3dbf33f..18e801b 100644
--- a/configs/config_test.yaml
+++ b/configs/config_test.yaml
@@ -78,6 +78,14 @@ cmb:
orgNo: "LANSEXIONGDI" # 发码机构号,固定值,掌上生活优惠券系统提供
notifyUrl: "https://sandbox.cdcc.cmbchina.com/AccessGateway/transIn/updateCodeStatus.json" # 招行测试回调地址
+#告警配置
+alarm:
+ webhookURL: "https://oapi.dingtalk.com/robot/send?access_token=5f10c2213cbf8168985cb2d061ebb1a5f70bd1dd47ec7cef58fa6fe545d52588"
+ secret: "SEC77b63d70a9e22317144e712b4538ce1e0013db885c65f7f9bae283e8958b39eb"
+ isAll: false
+ atMobiles:
+ - "15221117226"
+
#配置日志
logs:
business: business.log #业务日志路径:如果不写日志,则不配置或配置为空
diff --git a/internal/biz/cmb/cmb.go b/internal/biz/cmb/cmb.go
index f366aaf..f66c123 100644
--- a/internal/biz/cmb/cmb.go
+++ b/internal/biz/cmb/cmb.go
@@ -19,6 +19,7 @@ type Cmb struct {
WechatCpnRepo wechatrepo.WechatCpnRepo
GenerateMixRepo mixrepos.GenerateMixRepo
CmbMixRepo mixrepos.CmbMixRepo
+ DingMixRepo mixrepos.DingMixRepo
}
func NewCmb(
@@ -32,6 +33,7 @@ func NewCmb(
WechatCpnRepo wechatrepo.WechatCpnRepo,
GenerateMixRepo mixrepos.GenerateMixRepo,
CmbMixRepo mixrepos.CmbMixRepo,
+ DingMixRepo mixrepos.DingMixRepo,
) *Cmb {
return &Cmb{
bc: bc,
@@ -44,5 +46,6 @@ func NewCmb(
WechatCpnRepo: WechatCpnRepo,
GenerateMixRepo: GenerateMixRepo,
CmbMixRepo: CmbMixRepo,
+ DingMixRepo: DingMixRepo,
}
}
diff --git a/internal/biz/cmb/order_consume.go b/internal/biz/cmb/order_consume.go
index f104d7b..7d28053 100644
--- a/internal/biz/cmb/order_consume.go
+++ b/internal/biz/cmb/order_consume.go
@@ -163,11 +163,75 @@ func (v *Cmb) success(ctx context.Context, order *bo.OrderBo, orderWechat *bo.Or
return v.OrderRepo.Success(ctx, order.ID)
}
-func (v *Cmb) fail(ctx context.Context, order *bo.OrderBo, orderWechat *bo.OrderWechatBo, remarks string) error {
+func (v *Cmb) fail(ctx context.Context, order *bo.OrderBo, orderWechat *bo.OrderWechatBo, errMsg string) error {
- if err := v.OrderWechatRepo.Fail(ctx, orderWechat.ID, remarks); err != nil {
+ if err := v.OrderWechatRepo.Fail(ctx, orderWechat.ID, errMsg); err != nil {
return err
}
- return v.OrderRepo.Fail(ctx, order.ID)
+ if err := v.OrderRepo.Fail(ctx, order.ID); err != nil {
+ return err
+ }
+
+ return v.alarm(ctx, order, errMsg)
+}
+
+func (v *Cmb) alarm(ctx context.Context, order *bo.OrderBo, errMsg string) error {
+
+ // 1小时 内 指定的批次号 发放 发生错误 预警
+ c := vo.OrderConsumeFailAlarmKey.BuildCache([]string{order.ProductNo})
+
+ _, err := v.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(v.rdb.Rdb, cl.TTL).Lock(ctx, cl.Key, func(ctx context.Context) error {
+ // 二次获取,判定处理,以免获取锁后又执行了一次
+
+ cacheValue, err := v.rdb.Rdb.Get(ctx, c.Key).Result()
+
+ if err != nil && err != redis.Nil {
+ return fmt.Errorf(fmt.Sprintf("alarm 二次获取redis缓存%s异常:%v", c.Key, err))
+ }
+
+ if cacheValue != "" {
+ return nil // 有直接返回
+ }
+
+ // 通知
+ text := v.alarmText(ctx, order, errMsg)
+ if err = v.DingMixRepo.SendMarkdownMessage(ctx, text); err != nil {
+ return err
+ }
+
+ if err := v.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 (v *Cmb) 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)
}
diff --git a/internal/biz/mixrepos/ding.go b/internal/biz/mixrepos/ding.go
index 5908baa..86ca87c 100644
--- a/internal/biz/mixrepos/ding.go
+++ b/internal/biz/mixrepos/ding.go
@@ -3,5 +3,5 @@ package mixrepos
import "context"
type DingMixRepo interface {
- SendMarkdownMessage(_ context.Context, text string) error
+ SendMarkdownMessage(ctx context.Context, text string) error
}
diff --git a/internal/biz/vo/cache.go b/internal/biz/vo/cache.go
index 0a2b62d..fcdc1ab 100644
--- a/internal/biz/vo/cache.go
+++ b/internal/biz/vo/cache.go
@@ -16,6 +16,9 @@ const (
NotifyConsume CacheKey = "notify_consume"
NotifyRetryConsume CacheKey = "notify_retry_consume"
+ OrderConsumeFailAlarmKey CacheKey = "order_consume_fail_alarm"
+ OrderConsumeFailAlarmLockKey CacheKey = "order_consume_fail_alarm_lock"
+
WechatNotifyRegisterTagCacheKey CacheKey = "wechat_notify_register_tag"
WechatNotifyRegisterTagCacheLockKey CacheKey = "wechat_notify_register_tag_lock"
@@ -27,9 +30,11 @@ var CacheKeyMap = map[CacheKey]time.Duration{
CmbQueryLockKey: 30 * time.Second,
CmbProductQueryLockKey: 30 * time.Second,
OrderConsume: 60 * time.Second,
+ OrderConsumeFailAlarmKey: 3600 * time.Second, // 1小时
+ OrderConsumeFailAlarmLockKey: 60 * time.Second,
NotifyConsume: 60 * time.Second,
NotifyRetryConsume: 60 * time.Second,
- WechatNotifyRegisterTagCacheKey: 86400 * time.Second,
+ WechatNotifyRegisterTagCacheKey: 86400 * time.Second, // 1天
WechatNotifyRegisterTagCacheLockKey: 30 * time.Second,
WechatNotifyConsumeLockKey: 30 * time.Second,
}
@@ -45,7 +50,11 @@ func (s CacheKey) GetValue() string {
func (s CacheKey) BuildCache(strArr []string) *Cache {
- k := helper.BuildStr(s.GetValue(), strArr)
+ k := ""
+
+ if len(strArr) > 0 {
+ k = helper.BuildStr(s.GetValue(), strArr)
+ }
c := &Cache{
Key: k,
@@ -63,7 +72,11 @@ func (s CacheKey) BuildCache(strArr []string) *Cache {
func (s CacheKey) BuildCacheUint64(ids []uint64) *Cache {
- k := helper.BuildStr(s.GetValue(), ids)
+ k := ""
+
+ if len(ids) > 0 {
+ k = helper.BuildStr(s.GetValue(), ids)
+ }
c := &Cache{
Key: k,
diff --git a/internal/data/mixrepoimpl/provider_set.go b/internal/data/mixrepoimpl/provider_set.go
index 6c9900f..9a3ba66 100644
--- a/internal/data/mixrepoimpl/provider_set.go
+++ b/internal/data/mixrepoimpl/provider_set.go
@@ -9,4 +9,5 @@ var ProviderMixRepoImplSet = wire.NewSet(
NewGenerateMixRepoImpl,
NewMQSendMixRepoImpl,
NewCmbMixRepoImpl,
+ NewDingMixRepoImpl,
)
diff --git a/internal/pkg/ding/ding.go b/internal/pkg/ding/ding.go
index 966c673..2aedcab 100644
--- a/internal/pkg/ding/ding.go
+++ b/internal/pkg/ding/ding.go
@@ -119,7 +119,7 @@ func (c *TalkClient) SendLinkMessage(title, text, messageURL, picURL string, atM
func (c *TalkClient) SendMarkdownMessage(title, text string, atMobiles []string, isAtAll bool) error {
var atStr string
for _, mobile := range atMobiles {
- atStr += fmt.Sprintf("@%s", mobile)
+ atStr += fmt.Sprintf("@%s", mobile)
}
text += atStr
diff --git a/internal/pkg/ding/ding_test.go b/internal/pkg/ding/ding_test.go
index 5be4f4b..a6c1f57 100644
--- a/internal/pkg/ding/ding_test.go
+++ b/internal/pkg/ding/ding_test.go
@@ -47,7 +47,8 @@ func TestSendLinkMessage(t *testing.T) {
func TestSendMarkdownMessage(t *testing.T) {
markdownTitle := "测试 Markdown 消息"
- markdownText := "# 立减金发放平台报警通知
\n不好了,订单发放发生异常了,错误内容[批次号不存在]@相关人员。"
+ //markdownText := "# 立减金发放平台报警通知
\n不好了,订单发放发生异常了,错误内容[批次号不存在]@相关人员。"
+ markdownText := alarmText("批次号不存在")
atMobiles := []string{"18666173766", "15102807142"}
@@ -62,6 +63,21 @@ func TestSendMarkdownMessage(t *testing.T) {
}
}
+func alarmText(errMsg string) string {
+
+ remarks := fmt.Sprintf("订单号:%s,商品编号:%s,错误原因:%s", "123456", "001", errMsg)
+
+ msg := "# " +
+ "立减金发放平台报警通知
" +
+ " \n" +
+ "" +
+ "不好了,订单发放发生异常了,错误内容" +
+ "[%s]@相关人员。" +
+ ""
+
+ return fmt.Sprintf(msg, remarks)
+}
+
func TestSend(t *testing.T) {
webhookURL := "your_webhook_url"
secret := "your_secret"