@@ -11,6 +11,7 @@ import (
1111 "net/url"
1212 "os"
1313 "path/filepath"
14+ "strconv"
1415 "strings"
1516 "time"
1617
@@ -193,7 +194,7 @@ func SendAck(ctx context.Context, options AckOptions) AckResult {
193194 result .StatusCode = resp .StatusCode
194195 if resp .StatusCode < 200 || resp .StatusCode >= 300 {
195196 result .Error = remoteRegistrationError (resp .Status , body )
196- if remoteDeliveryStatusRetryable (resp .StatusCode ) && attempt < retries && sleepRemoteDeliveryRetry (ctx , options .RetryInitialDelay , options .RetryMaxDelay , attempt ) {
197+ if remoteDeliveryStatusRetryable (resp .StatusCode ) && attempt < retries && sleepRemoteDeliveryRetryAfter (ctx , resp . Header . Get ( "Retry-After" ), options .RetryInitialDelay , options .RetryMaxDelay , attempt , time . Now () ) {
197198 continue
198199 }
199200 return result
@@ -261,7 +262,7 @@ func SendLeaseRenewal(ctx context.Context, options LeaseRenewOptions) LeaseRenew
261262 result .StatusCode = resp .StatusCode
262263 if resp .StatusCode < 200 || resp .StatusCode >= 300 {
263264 result .Error = remoteRegistrationError (resp .Status , body )
264- if remoteDeliveryStatusRetryable (resp .StatusCode ) && attempt < retries && sleepRemoteDeliveryRetry (ctx , options .RetryInitialDelay , options .RetryMaxDelay , attempt ) {
265+ if remoteDeliveryStatusRetryable (resp .StatusCode ) && attempt < retries && sleepRemoteDeliveryRetryAfter (ctx , resp . Header . Get ( "Retry-After" ), options .RetryInitialDelay , options .RetryMaxDelay , attempt , time . Now () ) {
265266 continue
266267 }
267268 return result
@@ -384,6 +385,27 @@ func remoteDeliveryStatusRetryable(status int) bool {
384385}
385386
386387func sleepRemoteDeliveryRetry (ctx context.Context , initialDelay , maxDelay time.Duration , attempt int ) bool {
388+ return sleepRemoteDeliveryRetryDelay (ctx , remoteDeliveryRetryDelay (initialDelay , maxDelay , attempt ))
389+ }
390+
391+ func sleepRemoteDeliveryRetryAfter (ctx context.Context , retryAfter string , initialDelay , maxDelay time.Duration , attempt int , now time.Time ) bool {
392+ delay := remoteDeliveryRetryDelay (initialDelay , maxDelay , attempt )
393+ if retryDelay , ok := remoteRetryAfterDelay (retryAfter , now ); ok {
394+ delay = retryDelay
395+ if maxDelay <= 0 {
396+ maxDelay = time .Second
397+ }
398+ if delay > maxDelay {
399+ delay = maxDelay
400+ }
401+ if delay < 0 {
402+ delay = 0
403+ }
404+ }
405+ return sleepRemoteDeliveryRetryDelay (ctx , delay )
406+ }
407+
408+ func remoteDeliveryRetryDelay (initialDelay , maxDelay time.Duration , attempt int ) time.Duration {
387409 delay := initialDelay
388410 if delay <= 0 {
389411 delay = 100 * time .Millisecond
@@ -401,6 +423,35 @@ func sleepRemoteDeliveryRetry(ctx context.Context, initialDelay, maxDelay time.D
401423 if delay > maxDelay {
402424 delay = maxDelay
403425 }
426+ return delay
427+ }
428+
429+ func remoteRetryAfterDelay (value string , now time.Time ) (time.Duration , bool ) {
430+ value = strings .TrimSpace (value )
431+ if value == "" {
432+ return 0 , false
433+ }
434+ if seconds , err := strconv .ParseInt (value , 10 , 64 ); err == nil {
435+ if seconds < 0 {
436+ return 0 , false
437+ }
438+ return time .Duration (seconds ) * time .Second , true
439+ }
440+ after , err := http .ParseTime (value )
441+ if err != nil {
442+ return 0 , false
443+ }
444+ if now .IsZero () {
445+ now = time .Now ()
446+ }
447+ delay := after .Sub (now )
448+ if delay < 0 {
449+ delay = 0
450+ }
451+ return delay , true
452+ }
453+
454+ func sleepRemoteDeliveryRetryDelay (ctx context.Context , delay time.Duration ) bool {
404455 timer := time .NewTimer (delay )
405456 defer timer .Stop ()
406457 select {
0 commit comments