package polling import ( "context" stderrors "errors" "strconv" "gorm.io/gorm" auditinfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/audit" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/pkg/auditcontext" "github.com/break/junhong_cmp_fiber/pkg/auditfailure" "github.com/break/junhong_cmp_fiber/pkg/constants" pkgerrors "github.com/break/junhong_cmp_fiber/pkg/errors" ) func runPollingTransaction(ctx context.Context, db *gorm.DB, writer *auditinfra.Writer, fn func(*gorm.DB) error) error { if db == nil || writer == nil { return pkgerrors.New(pkgerrors.CodeInvalidStatus, "统一轮询审计接缝未配置") } return db.WithContext(ctx).Transaction(fn) } func writePollingAudit(ctx context.Context, tx *gorm.DB, writer *auditinfra.Writer, input auditinfra.PollingInput) error { return writer.WritePolling(ctx, tx, input) } func recordPollingFailure(ctx context.Context, db *gorm.DB, writer *auditinfra.Writer, input auditinfra.PollingInput, originalErr error) { if input.OperatorID == 0 || input.ResourceType == "" || input.ResourceKey == "" { return } var appErr *pkgerrors.AppError if !stderrors.As(originalErr, &appErr) { appErr = pkgerrors.New(pkgerrors.CodeInternalError, "轮询操作失败") } if input.Result == "" { input.Result = constants.AuditResultFailed } if input.ErrorCode == "" { input.ErrorCode = strconv.Itoa(appErr.Code) } if input.ErrorSummary == "" { input.ErrorSummary = appErr.Message } if db != nil && writer != nil { if err := db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { return writePollingAudit(ctx, tx, writer, input) }); err == nil { return } else { originalErr = err } } linkage := auditcontext.From(ctx) auditfailure.RecordSecondaryWriteFailure( input.ActionCode, input.ResourceKey, linkage.RequestID, linkage.CorrelationID, input.ErrorCode, originalErr, ) } func pollingConfigIdentity(config *model.PollingConfig) map[string]any { return map[string]any{ "id": config.ID, "config_name": config.ConfigName, "card_condition": config.CardCondition, "card_category": config.CardCategory, "carrier_id": config.CarrierID, "priority": config.Priority, "status": config.Status, } } func pollingConfigState(config *model.PollingConfig) map[string]any { return map[string]any{ "config_name": config.ConfigName, "card_condition": config.CardCondition, "card_category": config.CardCategory, "carrier_id": config.CarrierID, "priority": config.Priority, "realname_check_interval": config.RealnameCheckInterval, "carddata_check_interval": config.CarddataCheckInterval, "package_check_interval": config.PackageCheckInterval, "protect_check_interval": config.ProtectCheckInterval, "card_status_check_interval": config.CardStatusCheckInterval, "status": config.Status, "description": config.Description, } } func pollingConcurrencyIdentity(config *model.PollingConcurrencyConfig) map[string]any { return map[string]any{"id": config.ID, "task_type": config.TaskType, "max_concurrency": config.MaxConcurrency} } func pollingAlertRuleIdentity(rule *model.PollingAlertRule) map[string]any { return map[string]any{ "id": rule.ID, "rule_name": rule.RuleName, "task_type": rule.TaskType, "metric_type": rule.MetricType, "operator": rule.Operator, "threshold": rule.Threshold, "alert_level": rule.AlertLevel, "status": rule.Status, } } func pollingAlertRuleState(rule *model.PollingAlertRule) map[string]any { return map[string]any{ "rule_name": rule.RuleName, "task_type": rule.TaskType, "metric_type": rule.MetricType, "operator": rule.Operator, "threshold": rule.Threshold, "duration_minutes": rule.DurationMinutes, "alert_level": rule.AlertLevel, "status": rule.Status, "cooldown_minutes": rule.CooldownMinutes, "notification_channels_configured": rule.NotificationChannels != "", "description": rule.Description, } } func pollingManualTriggerIdentity(log *model.PollingManualTriggerLog) map[string]any { return map[string]any{ "id": log.ID, "task_type": log.TaskType, "trigger_type": log.TriggerType, "total_count": log.TotalCount, "status": log.Status, "triggered_by": log.TriggeredBy, } } func pollingManualTriggerKey(id uint) string { return strconv.FormatUint(uint64(id), 10) } func pollingManualAttemptKey(taskType, triggerType string, operatorID uint) string { return triggerType + ":" + taskType + ":" + strconv.FormatUint(uint64(operatorID), 10) } func pollingManualAttemptIdentity(taskType, triggerType string, totalCount int, operatorID uint) map[string]any { return map[string]any{ "task_type": taskType, "trigger_type": triggerType, "total_count": totalCount, "triggered_by": operatorID, } }