收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
39
internal/service/order_package_invalidate/audit.go
Normal file
39
internal/service/order_package_invalidate/audit.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package order_package_invalidate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
)
|
||||
|
||||
func (s *Service) writeInvalidateTaskAudit(ctx context.Context, tx *gorm.DB, task *model.OrderPackageInvalidateTask, before, after map[string]any, result, phase, errorCode, errorSummary string) error {
|
||||
return s.auditWriter.WriteTask(ctx, tx, audit.TaskInput{
|
||||
EventID: audit.TaskEventID(constants.AuditResourceOrderPackageInvalidateTask, task.ID, phase),
|
||||
ActionCode: constants.AuditActionOrderPackageInvalidateTaskCreated,
|
||||
Summary: "创建订单套餐批量失效任务", TaskID: task.ID, TaskNo: task.TaskNo,
|
||||
Actor: audit.ActorInput{
|
||||
Kind: constants.AuditActorAccount, ID: strconv.FormatUint(uint64(middleware.GetUserIDFromContext(ctx)), 10),
|
||||
Name: middleware.GetUsernameFromContext(ctx),
|
||||
},
|
||||
Source: constants.AuditSourceAdminAPI, ScopeType: constants.AuditScopePlatform,
|
||||
Result: result, ErrorCode: errorCode, ErrorSummary: errorSummary,
|
||||
IdentitySnapshot: map[string]any{"id": task.ID, "task_no": task.TaskNo, "file_name": task.FileName},
|
||||
BeforeData: before, AfterData: after,
|
||||
})
|
||||
}
|
||||
|
||||
func invalidateTaskState(task *model.OrderPackageInvalidateTask) map[string]any {
|
||||
if task == nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]any{
|
||||
"status": task.Status, "total_count": task.TotalCount,
|
||||
"success_count": task.SuccessCount, "fail_count": task.FailCount,
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,18 @@ package order_package_invalidate
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditfailure"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
@@ -21,17 +25,23 @@ import (
|
||||
type Service struct {
|
||||
taskStore *postgres.OrderPackageInvalidateTaskStore
|
||||
queueClient *queue.Client
|
||||
auditWriter *audit.Writer
|
||||
}
|
||||
|
||||
// New 创建 Service 实例
|
||||
func New(
|
||||
taskStore *postgres.OrderPackageInvalidateTaskStore,
|
||||
queueClient *queue.Client,
|
||||
auditWriters ...*audit.Writer,
|
||||
) *Service {
|
||||
return &Service{
|
||||
service := &Service{
|
||||
taskStore: taskStore,
|
||||
queueClient: queueClient,
|
||||
}
|
||||
if len(auditWriters) > 0 {
|
||||
service.auditWriter = auditWriters[0]
|
||||
}
|
||||
return service
|
||||
}
|
||||
|
||||
// InvalidateTaskPayload Worker 任务载荷
|
||||
@@ -59,7 +69,15 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateOrderPackageInvalid
|
||||
Updater: userID,
|
||||
}
|
||||
|
||||
if err := s.taskStore.Create(ctx, task); err != nil {
|
||||
if s.auditWriter == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "订单套餐失效任务统一审计接缝未配置")
|
||||
}
|
||||
if err := s.taskStore.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.taskStore.WithTx(tx).Create(ctx, task); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.writeInvalidateTaskAudit(ctx, tx, task, nil, invalidateTaskState(task), constants.AuditResultSuccess, "created", "", "")
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "创建任务失败")
|
||||
}
|
||||
|
||||
@@ -71,7 +89,17 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateOrderPackageInvalid
|
||||
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeOrderPackageInvalidate)),
|
||||
)
|
||||
if err != nil {
|
||||
s.taskStore.UpdateStatus(ctx, task.ID, model.ImportTaskStatusFailed, "任务入队失败: "+err.Error())
|
||||
secondaryErr := s.taskStore.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
before := invalidateTaskState(task)
|
||||
if updateErr := s.taskStore.WithTx(tx).UpdateStatus(ctx, task.ID, model.ImportTaskStatusFailed, "任务入队失败"); updateErr != nil {
|
||||
return updateErr
|
||||
}
|
||||
task.Status, task.ErrorMessage = model.ImportTaskStatusFailed, "任务入队失败"
|
||||
return s.writeInvalidateTaskAudit(ctx, tx, task, before, invalidateTaskState(task), constants.AuditResultFailed, "enqueue_failed", strconv.Itoa(errors.CodeTaskQueueError), "订单套餐失效任务入队失败")
|
||||
})
|
||||
if secondaryErr != nil {
|
||||
auditfailure.RecordSecondaryWriteFailure(constants.AuditActionOrderPackageInvalidateTaskCreated, task.TaskNo, "", task.TaskNo, strconv.Itoa(errors.CodeTaskQueueError), secondaryErr)
|
||||
}
|
||||
}
|
||||
|
||||
return s.toResponse(task), nil
|
||||
|
||||
Reference in New Issue
Block a user