package rabbitmq import ( "context" "encoding/json" "errors" "time" mq "git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/library/rabbitmq" "git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/model" "git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/service/trafficusage" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" ) var trafficUsagePublish = mq.PublishBytesWithHeaders var trafficUsagePublishDelayed = mq.PublishDelayedBytesWithHeaders func validateTrafficUsageIdentity(simKey *model.SimKey, card model.TrafficUsageSimCard) error { if simKey == nil || card.Iccid == "" || simKey.ICCID != card.Iccid { return &trafficusage.Failure{Cause: gerror.New("invalid traffic usage card identity"), Permanent: true} } return nil } func trafficUsageFailureSnapshot(err error, usage **float64) bool { var failure *trafficusage.Failure if errors.As(err, &failure) { if failure.UsageMb != nil { *usage = failure.UsageMb } return failure.Permanent } return false } func publishTrafficUsageFailure(ctx context.Context, queue string, message any, attempt int, permanent bool) error { ctx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() body, err := json.Marshal(message) if err != nil { return err } if permanent || attempt >= 10 { g.Log().Errorf(ctx, "traffic usage retry exhausted or invalid, queue:%s, attempt:%d, payload:%s", queue, attempt, body) err = trafficUsagePublish(ctx, queue+".dlq", body, nil) return waitTrafficUsagePublishFailure(ctx, err) } delay := 30 * time.Second if attempt >= 3 { delay = 2 * time.Minute } if attempt >= 6 { delay = 5 * time.Minute } err = trafficUsagePublishDelayed(ctx, queue+".delay."+delay.String(), queue, delay, body, nil) return waitTrafficUsagePublishFailure(ctx, err) } func waitTrafficUsagePublishFailure(ctx context.Context, err error) error { if err != nil { select { case <-ctx.Done(): case <-time.After(time.Second): } } return err }