package audit import ( "context" stderrors "errors" "strconv" "gorm.io/gorm" "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" ) // RecordFailure 在业务回滚后使用独立短事务记录失败或拒绝事实。 func (w *Writer) RecordFailure(ctx context.Context, db *gorm.DB, input AppendInput, originalErr error) { fillFailureInput(&input, originalErr) if w == nil || db == nil { recordFailureWriteError(ctx, input, pkgerrors.New(pkgerrors.CodeInvalidStatus, "统一审计失败记录接缝未配置")) return } if err := db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { return w.Append(ctx, tx, input) }); err != nil { recordFailureWriteError(ctx, input, err) } } func fillFailureInput(input *AppendInput, originalErr error) { var appErr *pkgerrors.AppError if stderrors.As(originalErr, &appErr) && appErr != nil { if input.Result == "" { input.Result = constants.AuditResultDenied if appErr.Code == pkgerrors.CodeDatabaseError || appErr.Code == pkgerrors.CodeInternalError { input.Result = constants.AuditResultFailed } } input.ErrorCode = strconv.Itoa(appErr.Code) input.ErrorSummary = appErr.Message return } if input.Result == "" { input.Result = constants.AuditResultFailed } input.ErrorCode = strconv.Itoa(pkgerrors.CodeInternalError) input.ErrorSummary = "业务操作失败" } func recordFailureWriteError(ctx context.Context, input AppendInput, err error) { linkage := auditcontext.From(ctx) resourceKey := "" for _, resource := range input.Resources { if resource.Relation == constants.AuditResourceRelationPrimary { resourceKey = resource.Key break } } auditfailure.RecordSecondaryWriteFailure( input.ActionCode, resourceKey, linkage.RequestID, linkage.CorrelationID, input.ErrorCode, err, ) }