收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -3,8 +3,10 @@ package iot_card_import
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
@@ -23,6 +25,7 @@ type Service struct {
|
||||
carrierStore carrierGetter
|
||||
queueClient *queue.Client
|
||||
assetAudit AssetAuditService
|
||||
auditWriter *audit.Writer
|
||||
}
|
||||
|
||||
type carrierGetter interface {
|
||||
@@ -50,14 +53,19 @@ func New(
|
||||
importTaskStore *postgres.IotCardImportTaskStore,
|
||||
queueClient *queue.Client,
|
||||
assetAudit AssetAuditService,
|
||||
auditWriters ...*audit.Writer,
|
||||
) *Service {
|
||||
return &Service{
|
||||
service := &Service{
|
||||
db: db,
|
||||
importTaskStore: importTaskStore,
|
||||
carrierStore: NewCarrierStore(db),
|
||||
queueClient: queueClient,
|
||||
assetAudit: assetAudit,
|
||||
}
|
||||
if len(auditWriters) > 0 {
|
||||
service.auditWriter = auditWriters[0]
|
||||
}
|
||||
return service
|
||||
}
|
||||
|
||||
type IotCardImportPayload struct {
|
||||
@@ -67,16 +75,12 @@ type IotCardImportPayload struct {
|
||||
func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportIotCardRequest) (*dto.ImportIotCardResponse, error) {
|
||||
userID := middleware.GetUserIDFromContext(ctx)
|
||||
if userID == 0 {
|
||||
appErr := errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
s.logIotCardImportAudit(ctx, newIotCardImportAuditParams(0, "", req, constants.AssetAuditResultDenied, appErr))
|
||||
return nil, appErr
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
|
||||
carrier, err := s.carrierStore.GetByID(ctx, req.CarrierID)
|
||||
if err != nil {
|
||||
appErr := errors.New(errors.CodeInvalidParam, "运营商不存在")
|
||||
s.logIotCardImportAudit(ctx, newIotCardImportAuditParams(0, "", req, constants.AssetAuditResultDenied, appErr))
|
||||
return nil, appErr
|
||||
return nil, errors.New(errors.CodeInvalidParam, "运营商不存在")
|
||||
}
|
||||
|
||||
taskNo := s.importTaskStore.GenerateTaskNo(ctx)
|
||||
@@ -103,9 +107,17 @@ func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportIotCardRe
|
||||
task.Creator = userID
|
||||
task.Updater = userID
|
||||
|
||||
if err := s.importTaskStore.Create(ctx, task); err != nil {
|
||||
if s.auditWriter == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "IoT 卡导入任务统一审计接缝未配置")
|
||||
}
|
||||
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.WithContext(ctx).Create(task).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return s.writeImportTaskAudit(ctx, tx, task, nil, importTaskState(task), constants.AuditResultSuccess, "created", "", "")
|
||||
}); err != nil {
|
||||
appErr := errors.Wrap(errors.CodeInternalError, err, "创建导入任务失败")
|
||||
s.logIotCardImportAudit(ctx, newIotCardImportAuditParams(0, taskNo, req, constants.AssetAuditResultFailed, appErr))
|
||||
s.recordImportTaskAudit(ctx, task, nil, importTaskState(task), constants.AuditResultFailed, "create_failed", errors.CodeDatabaseError, "创建 IoT 卡导入任务失败")
|
||||
return nil, appErr
|
||||
}
|
||||
|
||||
@@ -117,14 +129,23 @@ func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportIotCardRe
|
||||
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeIotCardImport)),
|
||||
)
|
||||
if err != nil {
|
||||
s.importTaskStore.UpdateStatus(ctx, task.ID, model.ImportTaskStatusFailed, "任务入队失败: "+err.Error())
|
||||
secondaryErr := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
before := importTaskState(task)
|
||||
if updateErr := tx.WithContext(ctx).Model(&model.IotCardImportTask{}).Where("id = ?", task.ID).Updates(map[string]any{
|
||||
"status": model.ImportTaskStatusFailed, "error_message": "任务入队失败", "completed_at": time.Now(), "updated_at": time.Now(),
|
||||
}).Error; updateErr != nil {
|
||||
return updateErr
|
||||
}
|
||||
task.Status, task.ErrorMessage = model.ImportTaskStatusFailed, "任务入队失败"
|
||||
return s.writeImportTaskAudit(ctx, tx, task, before, importTaskState(task), constants.AuditResultFailed, "enqueue_failed", strconv.Itoa(errors.CodeTaskQueueError), "IoT 卡导入任务入队失败")
|
||||
})
|
||||
if secondaryErr != nil {
|
||||
s.recordImportTaskAudit(ctx, task, nil, importTaskState(task), constants.AuditResultFailed, "enqueue_audit_failed", errors.CodeTaskQueueError, "IoT 卡导入任务入队失败")
|
||||
}
|
||||
appErr := errors.Wrap(errors.CodeInternalError, err, "任务入队失败")
|
||||
s.logIotCardImportAudit(ctx, newIotCardImportAuditParams(task.ID, taskNo, req, constants.AssetAuditResultFailed, appErr))
|
||||
return nil, appErr
|
||||
}
|
||||
|
||||
s.logIotCardImportAudit(ctx, newIotCardImportAuditParams(task.ID, taskNo, req, constants.AssetAuditResultSuccess, nil))
|
||||
|
||||
return &dto.ImportIotCardResponse{
|
||||
TaskID: task.ID,
|
||||
TaskNo: taskNo,
|
||||
|
||||
Reference in New Issue
Block a user