package simwarning import ( "context" "fmt" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/cache" "strings" "time" "github.com/gogf/gf/v2/errors/gerror" ) const ( warnDedupeKeyPrefix = "iotlcm:warning" warnDedupeMinTTL = 24 * time.Hour ) func acquireWarningDedupe(ctx context.Context, hit warningHit, runTime time.Time) (bool, string, error) { key := warningDedupeKey(hit) if key == "" { return false, "", gerror.New("warning dedupe key is empty") } ok, err := cache.Instance().SetIfNotExist(ctx, key, "1", warningDedupeTTL(hit, runTime)) return ok, key, err } func acquireWarningActionDedupe(ctx context.Context, hit warningHit, action string, runTime time.Time) (bool, string, error) { action = strings.TrimSpace(action) if action == "" { return false, "", gerror.New("warning action is empty") } key := warningActionDedupeKey(hit, action) if key == "" { return false, "", gerror.New("warning action dedupe key is empty") } ok, err := cache.Instance().SetIfNotExist(ctx, key, "1", warningDedupeTTL(hit, runTime)) return ok, key, err } func releaseWarningDedupe(ctx context.Context, key string) { key = strings.TrimSpace(key) if key == "" { return } _, _ = cache.Instance().Remove(ctx, key) } func warningDedupeKey(hit warningHit) string { if hit.Config.TenantId == "" || hit.Config.Id == 0 || hit.Config.ItemId == 0 || hit.WarnStage == 0 { return "" } return fmt.Sprintf( "%s:hit:%d:%d:%s:%d:%d:%d:%s", warnDedupeKeyPrefix, hit.Config.ItemType, hit.Config.WarnUnit, hit.Config.TenantId, hit.Config.Id, hit.Config.ItemId, hit.WarnStage, warningPeriodKey(hit), ) } func warningActionDedupeKey(hit warningHit, action string) string { if hit.Config.TenantId == "" || hit.Config.Id == 0 || hit.Config.ItemId == 0 || hit.WarnStage == 0 { return "" } return fmt.Sprintf( "%s:act:%s:%d:%d:%s:%d:%d:%d:%s", warnDedupeKeyPrefix, action, hit.Config.ItemType, hit.Config.WarnUnit, hit.Config.TenantId, hit.Config.Id, hit.Config.ItemId, hit.WarnStage, warningPeriodKey(hit), ) } func warningDedupeTTL(hit warningHit, runTime time.Time) time.Duration { if runTime.IsZero() { runTime = time.Now() } expireAt := warningDedupeExpireAt(hit) if expireAt.IsZero() { return warnDedupeMinTTL } ttl := expireAt.Sub(runTime) if ttl <= 0 { return warnDedupeMinTTL } return ttl } func warningDedupeExpireAt(hit warningHit) time.Time { if !hit.DedupeExpireAt.IsZero() { return hit.DedupeExpireAt } if !hit.WindowEnd.IsZero() { return hit.WindowEnd } if !hit.PeriodEnd.IsZero() { return hit.PeriodEnd.AddDate(0, 1, 0) } return time.Time{} } func warnUnix(value time.Time) int64 { if value.IsZero() { return 0 } return value.Unix() } func warningPeriodKey(hit warningHit) string { begin, end := warningWindow(hit) return fmt.Sprintf("%d-%d", warnUnix(begin), warnUnix(end)) } func warningWindow(hit warningHit) (time.Time, time.Time) { begin := hit.WindowBegin end := hit.WindowEnd if begin.IsZero() { begin = hit.PeriodBegin } if end.IsZero() { end = hit.PeriodEnd } return begin, end } func isTrafficKind(kind string) bool { switch kind { case warnKindTrafficMb, warnKindTrafficPercent, warnKindPoolTrafficPercent: return true default: return false } } func isExpireKind(kind string) bool { switch kind { case warnKindExpireDay, warnKindExpireMonth: return true default: return false } }