Files
junhong_cmp_fiber/internal/service/iot_card/gateway_integration.go
break 5e552d99bc 收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展
Confidence: medium
Scope-risk: broad
Directive: 后续修改需保持审计事件与业务事务边界一致
Tested: git diff --cached --check
Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
2026-08-05 14:30:54 +08:00

118 lines
3.8 KiB
Go

package iot_card
import (
"context"
"strconv"
"time"
"github.com/google/uuid"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/integrationlog"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
"github.com/break/junhong_cmp_fiber/pkg/constants"
pkgerrors "github.com/break/junhong_cmp_fiber/pkg/errors"
)
type gatewayAttempt struct {
log *model.IntegrationLog
startedAt time.Time
}
func (s *Service) startGatewayCardAttempt(ctx context.Context, card *model.IotCard, operation, scene, seriesKey string, attempt int) (*gatewayAttempt, error) {
if s == nil || s.speedTierIntegration == nil {
return nil, pkgerrors.New(pkgerrors.CodeInvalidStatus, "Gateway Integration Log 接缝未配置")
}
resourceID := strconv.FormatUint(uint64(card.ID), 10)
triggerSource := auditcontext.From(ctx).Source
if triggerSource == "" {
triggerSource = "service"
}
triggerScene := scene
triggerSeries := uuid.NewSHA1(uuid.NameSpaceOID, []byte("gateway-card:"+seriesKey+":"+operation)).String()
requestID := requestIDFromContext(ctx)
var requestIDPtr *string
if requestID != "" {
requestIDPtr = &requestID
}
log, err := s.speedTierIntegration.Start(ctx, integrationlog.Attempt{
Provider: constants.IntegrationProviderGateway, Direction: constants.IntegrationDirectionOutbound,
Operation: operation, ExternalID: &card.ICCID,
ResourceType: constants.AssetTypeIotCard, ResourceID: &resourceID, ResourceKey: &card.ICCID,
TriggerSource: &triggerSource, TriggerScene: &triggerScene, TriggerSeries: &triggerSeries,
Attempt: attempt, RequestID: requestIDPtr, CorrelationID: requestIDPtr,
RequestSummary: map[string]any{"iot_card_id": card.ID, "iccid": card.ICCID},
})
if err != nil {
return nil, err
}
return &gatewayAttempt{log: log, startedAt: time.Now()}, nil
}
func (s *Service) completeGatewayCardAttempt(ctx context.Context, attempt *gatewayAttempt, callErr error, stateChanged bool) error {
if attempt == nil || attempt.log == nil {
return nil
}
completion := integrationlog.Completion{
Result: constants.IntegrationResultSuccess, DurationMS: time.Since(attempt.startedAt).Milliseconds(),
StateChanged: stateChanged, ResponseSummary: map[string]any{"result": "success"},
}
if callErr != nil {
completion.Result = constants.IntegrationResultFailed
completion.SafeProviderMessage = "Gateway 请求失败"
completion.ResponseSummary = map[string]any{"result": "failed"}
if isGatewayTimeout(callErr) {
completion.Result = constants.IntegrationResultUnknown
completion.SafeProviderMessage = "Gateway 请求结果未知"
completion.ResponseSummary = map[string]any{"result": "unknown"}
completion.RecoveryStrategy = constants.GatewayQueryUnknownRecoveryStrategy
}
}
_, err := s.speedTierIntegration.Complete(ctx, attempt.log.IntegrationID, completion)
return err
}
type gatewayCardAttemptObserver struct {
service *Service
card *model.IotCard
operation string
scene string
seriesKey string
nextAttempt int
current *gatewayAttempt
successful *gatewayAttempt
lastCallErr error
recordingErr error
unknown bool
}
func (o *gatewayCardAttemptObserver) BeforeAttempt(ctx context.Context, _ int) error {
o.nextAttempt++
o.lastCallErr = nil
attempt, err := o.service.startGatewayCardAttempt(ctx, o.card, o.operation, o.scene, o.seriesKey, o.nextAttempt)
if err != nil {
o.recordingErr = err
return err
}
o.current = attempt
return nil
}
func (o *gatewayCardAttemptObserver) AfterAttempt(ctx context.Context, _ int, callErr error) error {
o.lastCallErr = callErr
if isGatewayTimeout(callErr) {
o.unknown = true
}
if callErr == nil {
o.successful = o.current
o.current = nil
return nil
}
err := o.service.completeGatewayCardAttempt(ctx, o.current, callErr, false)
o.current = nil
if err != nil {
o.recordingErr = err
}
return err
}