Skip to content

fix(aws/recs): shared RateLimiter causes data race under -race in GetAllRecommendations #1268

Description

@cristim

Summary

Client.rateLimiter is a single *RateLimiter shared across all 6 concurrent
goroutines in GetAllRecommendations. Each goroutine calls
fetchRIPageWithRetry (or fetchSPPageWithRetry) which calls
c.rateLimiter.Reset() at the start of every CE call. With 6 goroutines
running simultaneously, two goroutines race on the same Reset() write path.

Discovered during -race run while reviewing PR #842. The race is pre-existing
on main (confirmed: the same failure reproduces before the PR's changes).

Reproduction

cd providers/aws
go test -race ./recommendations/... -run TestGetAllRecommendations

Expected: PASS
Actual: DATA RACE -- RateLimiter.Reset() concurrent write at ratelimiter.go:138

Root cause

feedback_rate_limiter_per_call.md documents this exact pattern:

instantiate a fresh rate limiter per sweep; a shared mutable limiter
causes data races under go test -race

Client.rateLimiter is initialized once in NewClient/NewClientWithAPI
and then shared. The fix is to instantiate a NewRateLimiter() locally
inside fetchRIPageWithRetry and fetchSPPageWithRetry (and any analogous
sweep functions), not in the Client struct, so each concurrent call has its
own limiter state.

Fix sketch

Remove rateLimiter *RateLimiter from Client. In fetchRIPageWithRetry
and fetchSPPageWithRetry, create rl := NewRateLimiter() as a local
variable and use it for the retry loop.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions