From b90fd91e04a439e846539f760e36d0d22d497f12 Mon Sep 17 00:00:00 2001 From: Mauricio Araujo Date: Mon, 6 May 2024 11:50:19 -0400 Subject: [PATCH] Add ingest event limit (#4607) --- internal/billing/metronome.go | 51 ++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/internal/billing/metronome.go b/internal/billing/metronome.go index 7b2356c92e..27bc595f4f 100644 --- a/internal/billing/metronome.go +++ b/internal/billing/metronome.go @@ -23,6 +23,7 @@ const ( defaultRewardAmountCents = 1000 defaultPaidAmountCents = 0 maxReferralRewards = 10 + maxIngestEventLimit = 100 ) // MetronomeClient is the client used to call the Metronome API @@ -366,31 +367,45 @@ func (m MetronomeClient) IngestEvents(ctx context.Context, events []types.Billin path := "ingest" - var currentAttempts int - for currentAttempts < defaultMaxRetries { - statusCode, err := m.do(http.MethodPost, path, events, nil) - // Check errors that are not from error http codes - if statusCode == 0 && err != nil { - return telemetry.Error(ctx, span, err, "failed to ingest billing events") + for i := 0; i < len(events); i += maxIngestEventLimit { + end := i + maxIngestEventLimit + if end > len(events) { + end = len(events) } - if statusCode == http.StatusForbidden || statusCode == http.StatusUnauthorized { - return telemetry.Error(ctx, span, err, "unauthorized") + batch := events[i:end] + + // Retry each batch to make sure all events are ingested + var currentAttempts int + for currentAttempts < defaultMaxRetries { + statusCode, err := m.do(http.MethodPost, path, batch, nil) + // Check errors that are not from error http codes + if statusCode == 0 && err != nil { + return telemetry.Error(ctx, span, err, "failed to ingest billing events") + } + + if statusCode == http.StatusForbidden || statusCode == http.StatusUnauthorized { + return telemetry.Error(ctx, span, err, "unauthorized") + } + + // 400 responses should not be retried + if statusCode == http.StatusBadRequest { + return telemetry.Error(ctx, span, err, "malformed billing events") + } + + // Any other status code can be safely retried + if statusCode == http.StatusOK { + break + } + currentAttempts++ } - // 400 responses should not be retried - if statusCode == http.StatusBadRequest { - return telemetry.Error(ctx, span, err, "malformed billing events") + if currentAttempts == defaultMaxRetries { + return telemetry.Error(ctx, span, err, "max number of retry attempts reached with no success") } - - // Any other status code can be safely retried - if statusCode == 200 { - return nil - } - currentAttempts++ } - return telemetry.Error(ctx, span, err, "max number of retry attempts reached with no success") + return nil } func (m MetronomeClient) listBillableMetricIDs(ctx context.Context, customerID uuid.UUID) (billableMetrics []types.BillableMetric, err error) {