@@ -14,7 +14,7 @@ import (
1414 "regexp"
1515 "strconv"
1616 "strings"
17- "sync"
17+ "sync/atomic "
1818 "time"
1919
2020 "github.com/bradleyfalzon/ghinstallation/v2"
@@ -39,9 +39,8 @@ type Client struct {
3939 transport * ghinstallation.Transport
4040 requestThrottler * rate.Limiter
4141
42- // rateLimitDelay is shared across workers
43- rateLimitDelayMu sync.Mutex
44- rateLimitDelay time.Time
42+ // rateLimitDeadline is a UnixNano timestamp shared across workers.
43+ rateLimitDeadline atomic.Int64
4544}
4645
4746// NewClient creates a new API client with the given base URL and
@@ -282,6 +281,8 @@ func (c *Client) PostOne(ctx context.Context, record *DeploymentRecord) error {
282281 slog .Warn ("rate limited, retrying" ,
283282 "attempt" , attempt ,
284283 "status_code" , resp .StatusCode ,
284+ "retry-after" , resp .Header .Get ("Retry-After" ),
285+ "x-ratelimit-remaining" , resp .Header .Get ("X-Ratelimit-Remaining" ),
285286 "retry_delay" , retryDelay .Seconds (),
286287 "container_name" , record .Name ,
287288 "resp_msg" , string (respBody ),
@@ -320,14 +321,11 @@ func (c *Client) PostOne(ctx context.Context, record *DeploymentRecord) error {
320321 return fmt .Errorf ("all retries exhausted: %w" , lastErr )
321322}
322323
323- // waitForServerRateLimit blocks until the global secondary rate limit backoff has elapsed.
324+ // waitForServerRateLimit blocks until the global server rate limit backoff has elapsed.
324325// All workers sharing this client observe the same deadline.
325326func (c * Client ) waitForServerRateLimit (ctx context.Context ) error {
326- c .rateLimitDelayMu .Lock ()
327- waitUntil := c .rateLimitDelay
328- c .rateLimitDelayMu .Unlock ()
329-
330- delay := time .Until (waitUntil )
327+ deadline := c .rateLimitDeadline .Load ()
328+ delay := time .Until (time .Unix (0 , deadline ))
331329 if delay <= 0 {
332330 return nil
333331 }
@@ -347,11 +345,15 @@ func (c *Client) waitForServerRateLimit(ctx context.Context) error {
347345// setRetryAfter records a global backoff deadline.
348346// Ensures deadline can only be extended, not shortened.
349347func (c * Client ) setRetryAfter (d time.Duration ) {
350- until := time .Now ().Add (d )
351- c .rateLimitDelayMu .Lock ()
352- defer c .rateLimitDelayMu .Unlock ()
353- if until .After (c .rateLimitDelay ) {
354- c .rateLimitDelay = until
348+ newDeadline := time .Now ().Add (d ).UnixNano ()
349+ for {
350+ current := c .rateLimitDeadline .Load ()
351+ if newDeadline <= current {
352+ return
353+ }
354+ if c .rateLimitDeadline .CompareAndSwap (current , newDeadline ) {
355+ return
356+ }
355357 }
356358}
357359
0 commit comments