Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
122 lines
4.6 KiB
Go
122 lines
4.6 KiB
Go
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,
|
|
}
|
|
}
|