Files
break fcfa347005
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m38s
修复
2026-08-12 10:42:35 +08:00

88 lines
2.9 KiB
Go

package audit
import (
"context"
stderrors "errors"
"strconv"
"go.uber.org/zap"
"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"
"github.com/break/junhong_cmp_fiber/pkg/logger"
)
// 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) {
recordSecondaryWriteFailure(ctx, input.ActionCode, primaryResourceKey(input), input.ErrorCode, err)
}
func recordBusinessAppendFailure(ctx context.Context, input AppendInput, err error) {
recordBusinessWriteFailure(ctx, input.ActionCode, primaryResourceKey(input), err)
}
func recordBusinessWriteFailure(ctx context.Context, actionCode, resourceKey string, err error) {
linkage := auditcontext.From(ctx)
logger.GetAppLogger().Error(
"业务审计写入失败,已降级",
zap.String("action", actionCode),
zap.String("resource_key", resourceKey),
zap.String("request_id", linkage.RequestID),
zap.String("correlation_id", linkage.CorrelationID),
zap.Error(err),
)
recordSecondaryWriteFailure(ctx, actionCode, resourceKey, "", err)
}
func recordSecondaryWriteFailure(ctx context.Context, actionCode, resourceKey, originalErrorCode string, err error) {
linkage := auditcontext.From(ctx)
auditfailure.RecordSecondaryWriteFailure(
actionCode, resourceKey, linkage.RequestID, linkage.CorrelationID, originalErrorCode, err,
)
}
func primaryResourceKey(input AppendInput) string {
for _, resource := range input.Resources {
if resource.Relation == constants.AuditResourceRelationPrimary {
return resource.Key
}
}
return ""
}