收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -8,7 +8,9 @@ import (
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
notificationinfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/notification"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
@@ -53,19 +55,24 @@ type deliveryRequest struct {
|
||||
|
||||
// DeliveryService 校验接收人并幂等生成站内通知。
|
||||
type DeliveryService struct {
|
||||
repository *notificationinfra.Repository
|
||||
registry *notificationinfra.Registry
|
||||
resolver DynamicRecipientResolver
|
||||
logger *zap.Logger
|
||||
now func() time.Time
|
||||
repository *notificationinfra.Repository
|
||||
registry *notificationinfra.Registry
|
||||
resolver DynamicRecipientResolver
|
||||
logger *zap.Logger
|
||||
auditWriter *audit.Writer
|
||||
now func() time.Time
|
||||
}
|
||||
|
||||
// NewDeliveryService 创建站内通知投递用例。
|
||||
func NewDeliveryService(repository *notificationinfra.Repository, registry *notificationinfra.Registry, resolver DynamicRecipientResolver, logger *zap.Logger) *DeliveryService {
|
||||
func NewDeliveryService(repository *notificationinfra.Repository, registry *notificationinfra.Registry, resolver DynamicRecipientResolver, logger *zap.Logger, auditWriters ...*audit.Writer) *DeliveryService {
|
||||
if logger == nil {
|
||||
logger = zap.NewNop()
|
||||
}
|
||||
return &DeliveryService{repository: repository, registry: registry, resolver: resolver, logger: logger, now: time.Now}
|
||||
service := &DeliveryService{repository: repository, registry: registry, resolver: resolver, logger: logger, now: time.Now}
|
||||
if len(auditWriters) > 0 {
|
||||
service.auditWriter = auditWriters[0]
|
||||
}
|
||||
return service
|
||||
}
|
||||
|
||||
// Consume 消费明确或动态接收人通知事件;所有可恢复错误交给 Asynq 重试策略处理。
|
||||
@@ -150,6 +157,9 @@ func validateDeliveryRequest(request deliveryRequest) error {
|
||||
}
|
||||
|
||||
func (s *DeliveryService) deliver(ctx context.Context, eventID, recipientKind string, recipientIDs []uint, request deliveryRequest) error {
|
||||
if s.auditWriter == nil {
|
||||
return errors.New(errors.CodeInvalidStatus, "通知统一审计接缝未配置")
|
||||
}
|
||||
rendered, err := s.registry.Render(request.notificationType, request.templateData, request.refType, recipientKind)
|
||||
if err != nil {
|
||||
s.logger.Error("站内通知模板校验失败",
|
||||
@@ -182,7 +192,23 @@ func (s *DeliveryService) deliver(ctx context.Context, eventID, recipientKind st
|
||||
RefType: request.refType, RefID: request.refID, RefKey: request.refKey,
|
||||
ExpiresAt: expiresAt, CreatedAt: now,
|
||||
}
|
||||
created, err := s.repository.CreateIdempotent(ctx, notification)
|
||||
created := false
|
||||
err = s.repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var createErr error
|
||||
created, createErr = s.repository.WithTx(tx).CreateIdempotent(ctx, notification)
|
||||
if createErr != nil || !created {
|
||||
return createErr
|
||||
}
|
||||
return s.auditWriter.Append(ctx, tx, audit.AppendInput{
|
||||
EventID: audit.TaskEventID(constants.AuditResourceNotification, notification.ID, "delivered"),
|
||||
ActionCode: constants.AuditActionNotificationDelivered, Summary: "生成站内通知",
|
||||
ScopeType: constants.AuditScopePlatform, Result: constants.AuditResultSuccess,
|
||||
Metadata: map[string]any{"outbox_event_id": eventID},
|
||||
Resources: []audit.ResourceInput{audit.NotificationResource(notification,
|
||||
constants.AuditResourceRelationPrimary, constants.AuditResourceRoleNotificationTarget,
|
||||
nil, map[string]any{"created": true, "is_read": false})},
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "写入站内通知失败")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user