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 }