package business import ( "context" "kra/internal/biz/business" "kra/internal/service/dto" "strconv" "strings" ) type AlertGovernanceUsecase interface { Candidates(context.Context, string, int) ([]*business.AlertChannelOption, error) Gap(context.Context) (*business.AlertGap, error) SaveGap(context.Context, bool, int) error List(context.Context, business.AlertExemptionFilter, ...business.ListOption) ([]*business.AlertExemption, int64, error) Add(context.Context, business.ChannelKey, string) error Remove(context.Context, uint64) error } func (s *AlertGovernanceService) Candidates(ctx context.Context, keyword string) ([]*dto.AlertChannelOption, error) { if len([]rune(keyword)) > 100 { return nil, business.ErrAlertRecordInput } rows, err := s.uc.Candidates(ctx, keyword, 30) if err != nil { return nil, err } result := make([]*dto.AlertChannelOption, 0, len(rows)) for _, row := range rows { result = append(result, &dto.AlertChannelOption{ID: row.ID, SourceDB: row.SourceDB, Account: row.Name}) } return result, nil } type AlertGovernanceService struct{ uc AlertGovernanceUsecase } func NewAlertGovernanceService(uc *business.AlertGovernanceUsecase) *AlertGovernanceService { return &AlertGovernanceService{uc} } func (s *AlertGovernanceService) Gap(ctx context.Context) (*dto.AlertGapRequest, error) { v, err := s.uc.Gap(ctx) if err != nil { return nil, err } return &dto.AlertGapRequest{Enabled: v.Enabled, Days: v.Days}, nil } func (s *AlertGovernanceService) SaveGap(ctx context.Context, req *dto.AlertGapRequest) error { if req == nil || req.Days < 1 || req.Days > 2147483647 { return business.ErrAlertRuleInput } return s.uc.SaveGap(ctx, req.Enabled, req.Days) } func (s *AlertGovernanceService) List(ctx context.Context, req *dto.AlertExemptionQuery) (*dto.AlertExemptionPage, error) { if req == nil { return nil, business.ErrAlertRecordInput } page, size := max(req.Page, 1), req.PageSize if size < 1 { size = 10 } size = min(size, 500) if page > int(^uint(0)>>1)/size { return nil, business.ErrAlertRecordInput } rows, total, err := s.uc.List(ctx, business.AlertExemptionFilter{Name: strings.TrimSpace(req.Name), Active: req.Active}, business.ListOffset((page-1)*size), business.ListLimit(size)) if err != nil { return nil, err } out := &dto.AlertExemptionPage{Total: total, Rows: make([]*dto.AlertExemptionResponse, 0, len(rows))} for _, r := range rows { out.Rows = append(out.Rows, &dto.AlertExemptionResponse{ID: r.ID, SourceDB: r.SourceDB, PromoteID: r.ChannelKey.ID, ChannelName: r.ChannelName, AddedName: r.AddedName, AddedAt: localTime(&r.AddedAt), Reason: r.Reason, Active: r.RemovedAt == nil, RemovedName: r.RemovedName, RemovedAt: localTime(r.RemovedAt), RemoveReason: r.RemoveReason}) } return out, nil } func (s *AlertGovernanceService) Add(ctx context.Context, req *dto.AlertExemptionRequest) error { if req == nil || len([]rune(req.Reason)) > 500 { return business.ErrAlertRecordInput } id, err := strconv.ParseUint(req.PromoteID.String(), 10, 64) if err != nil || id == 0 { return business.ErrAlertRecordInput } return s.uc.Add(ctx, business.ChannelKey{SourceDB: req.SourceDB, ID: id}, req.Reason) } func (s *AlertGovernanceService) Remove(ctx context.Context, id uint64) error { if id == 0 { return business.ErrAlertRecordInput } return s.uc.Remove(ctx, id) } func (s *AlertRecordService) Ignore(ctx context.Context, req *dto.AlertIgnoreRequest) error { if req == nil || len(req.IDs) == 0 || len(req.IDs) > 500 { return business.ErrAlertRecordInput } ids := make([]uint64, 0, len(req.IDs)) seen := map[uint64]bool{} for _, n := range req.IDs { id, err := strconv.ParseUint(n.String(), 10, 64) if err != nil || id == 0 { return business.ErrAlertRecordInput } if !seen[id] { ids = append(ids, id) seen[id] = true } } return s.uc.Ignore(ctx, ids) }