@@ -31,13 +31,13 @@ var validOrgPattern = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
3131
3232// Client is an API client for posting deployment records.
3333type Client struct {
34- baseURL string
35- org string
36- httpClient * http.Client
37- retries int
38- apiToken string
39- transport * ghinstallation.Transport
40- rateLimiter * rate.Limiter
34+ baseURL string
35+ org string
36+ httpClient * http.Client
37+ retries int
38+ apiToken string
39+ transport * ghinstallation.Transport
40+ requestThrottler * rate.Limiter
4141
4242 // rateLimitDelay is shared across workers
4343 rateLimitDelayMu sync.Mutex
@@ -75,8 +75,8 @@ func NewClient(baseURL, org string, opts ...ClientOption) (*Client, error) {
7575 Timeout : 5 * time .Second ,
7676 },
7777 retries : 3 ,
78- // 20 req/sec with burst of 50
79- rateLimiter : rate .NewLimiter (rate .Limit (20 ), 50 ),
78+ // 3 req/sec (180 req/min) with burst of 20
79+ requestThrottler : rate .NewLimiter (rate .Limit (3 ), 20 ),
8080 }
8181
8282 for _ , opt := range opts {
@@ -145,10 +145,10 @@ func WithGHApp(id, installID string, pkBytes []byte, pkPath string) ClientOption
145145 }
146146}
147147
148- // WithRateLimiter sets a custom rate limiter for API calls.
149- func WithRateLimiter (rps float64 , burst int ) ClientOption {
148+ // WithRequestThrottler sets a custom rate limiter for API calls.
149+ func WithRequestThrottler (rps float64 , burst int ) ClientOption {
150150 return func (c * Client ) {
151- c .rateLimiter = rate .NewLimiter (rate .Limit (rps ), burst )
151+ c .requestThrottler = rate .NewLimiter (rate .Limit (rps ), burst )
152152 }
153153}
154154
@@ -185,9 +185,9 @@ func (c *Client) PostOne(ctx context.Context, record *DeploymentRecord) error {
185185 return errors .New ("record cannot be nil" )
186186 }
187187
188- // Wait for rate limiter
189- if err := c .rateLimiter .Wait (ctx ); err != nil {
190- return fmt .Errorf ("rate limiter wait failed: %w" , err )
188+ // Wait for request throttler
189+ if err := c .requestThrottler .Wait (ctx ); err != nil {
190+ return fmt .Errorf ("request throttler wait failed: %w" , err )
191191 }
192192
193193 url := fmt .Sprintf ("%s/orgs/%s/artifacts/metadata/deployment-record" , c .baseURL , c .org )
@@ -206,7 +206,7 @@ func (c *Client) PostOne(ctx context.Context, record *DeploymentRecord) error {
206206 return err
207207 }
208208
209- if err = c .waitForSecondaryRateLimit (ctx ); err != nil {
209+ if err = c .waitForServerRateLimit (ctx ); err != nil {
210210 return err
211211 }
212212
@@ -320,9 +320,9 @@ func (c *Client) PostOne(ctx context.Context, record *DeploymentRecord) error {
320320 return fmt .Errorf ("all retries exhausted: %w" , lastErr )
321321}
322322
323- // waitForSecondaryRateLimit blocks until the global secondary rate limit backoff has elapsed.
323+ // waitForServerRateLimit blocks until the global secondary rate limit backoff has elapsed.
324324// All workers sharing this client observe the same deadline.
325- func (c * Client ) waitForSecondaryRateLimit (ctx context.Context ) error {
325+ func (c * Client ) waitForServerRateLimit (ctx context.Context ) error {
326326 c .rateLimitDelayMu .Lock ()
327327 waitUntil := c .rateLimitDelay
328328 c .rateLimitDelayMu .Unlock ()
@@ -332,15 +332,15 @@ func (c *Client) waitForSecondaryRateLimit(ctx context.Context) error {
332332 return nil
333333 }
334334
335- slog .Info ("waiting for secondary rate limit backoff" ,
335+ slog .Info ("waiting for server rate limit backoff" ,
336336 "delay" , delay .Round (time .Millisecond ),
337337 )
338338
339339 select {
340340 case <- time .After (delay ):
341341 return nil
342342 case <- ctx .Done ():
343- return fmt .Errorf ("context cancelled during secondary rate limit wait: %w" , ctx .Err ())
343+ return fmt .Errorf ("context cancelled during server rate limit wait: %w" , ctx .Err ())
344344 }
345345}
346346
@@ -363,6 +363,8 @@ func parseRateLimitDelay(resp *http.Response) time.Duration {
363363 var retryAfterDelay * time.Duration
364364 if ra := resp .Header .Get ("Retry-After" ); ra != "" {
365365 if seconds , err := strconv .Atoi (ra ); err == nil {
366+ // Max Retry-After of 60 seconds
367+ seconds = min (seconds , 60 )
366368 rad := time .Duration (seconds ) * time .Second
367369 retryAfterDelay = & rad
368370 }
0 commit comments