001package com.box.sdkgen.networking.retries; 002 003import static com.box.sdkgen.internal.utils.UtilsManager.random; 004 005import com.box.sdkgen.networking.fetchoptions.FetchOptions; 006import com.box.sdkgen.networking.fetchresponse.FetchResponse; 007 008public class BoxRetryStrategy implements RetryStrategy { 009 010 public int maxAttempts; 011 012 public double retryRandomizationFactor; 013 014 public double retryBaseInterval; 015 016 public int maxRetriesOnException; 017 018 public BoxRetryStrategy() { 019 this.maxAttempts = 5; 020 this.retryRandomizationFactor = 0.5d; 021 this.retryBaseInterval = 1d; 022 this.maxRetriesOnException = 2; 023 } 024 025 protected BoxRetryStrategy(Builder builder) { 026 this.maxAttempts = builder.maxAttempts; 027 this.retryRandomizationFactor = builder.retryRandomizationFactor; 028 this.retryBaseInterval = builder.retryBaseInterval; 029 this.maxRetriesOnException = builder.maxRetriesOnException; 030 } 031 032 @Override 033 public boolean shouldRetry( 034 FetchOptions fetchOptions, FetchResponse fetchResponse, int attemptNumber) { 035 if (fetchResponse.getStatus() == 0) { 036 return attemptNumber <= this.maxRetriesOnException; 037 } 038 boolean isSuccessful = fetchResponse.getStatus() >= 200 && fetchResponse.getStatus() < 400; 039 String retryAfterHeader = 040 (fetchResponse.getHeaders().containsKey("Retry-After") 041 ? fetchResponse.getHeaders().get("Retry-After") 042 : null); 043 boolean isAcceptedWithRetryAfter = 044 fetchResponse.getStatus() == 202 && !(retryAfterHeader == null); 045 if (attemptNumber >= this.maxAttempts) { 046 return false; 047 } 048 if (isAcceptedWithRetryAfter) { 049 return true; 050 } 051 if (fetchResponse.getStatus() >= 500) { 052 return true; 053 } 054 if (fetchResponse.getStatus() == 429) { 055 return true; 056 } 057 if (fetchResponse.getStatus() == 401 && !(fetchOptions.getAuth() == null)) { 058 fetchOptions.getAuth().refreshToken(fetchOptions.getNetworkSession()); 059 return true; 060 } 061 if (isSuccessful) { 062 return false; 063 } 064 return false; 065 } 066 067 @Override 068 public double retryAfter( 069 FetchOptions fetchOptions, FetchResponse fetchResponse, int attemptNumber) { 070 String retryAfterHeader = 071 (fetchResponse.getHeaders().containsKey("Retry-After") 072 ? fetchResponse.getHeaders().get("Retry-After") 073 : null); 074 if (!(retryAfterHeader == null)) { 075 return Double.parseDouble(retryAfterHeader); 076 } 077 double randomization = 078 random(1 - this.retryRandomizationFactor, 1 + this.retryRandomizationFactor); 079 double exponential = Math.pow(2, attemptNumber); 080 return exponential * this.retryBaseInterval * randomization; 081 } 082 083 public int getMaxAttempts() { 084 return maxAttempts; 085 } 086 087 public double getRetryRandomizationFactor() { 088 return retryRandomizationFactor; 089 } 090 091 public double getRetryBaseInterval() { 092 return retryBaseInterval; 093 } 094 095 public int getMaxRetriesOnException() { 096 return maxRetriesOnException; 097 } 098 099 public static class Builder { 100 101 protected Integer maxAttempts; 102 103 protected Double retryRandomizationFactor; 104 105 protected Double retryBaseInterval; 106 107 protected Integer maxRetriesOnException; 108 109 public Builder() {} 110 111 public Builder maxAttempts(int maxAttempts) { 112 this.maxAttempts = maxAttempts; 113 return this; 114 } 115 116 public Builder retryRandomizationFactor(double retryRandomizationFactor) { 117 this.retryRandomizationFactor = retryRandomizationFactor; 118 return this; 119 } 120 121 public Builder retryBaseInterval(double retryBaseInterval) { 122 this.retryBaseInterval = retryBaseInterval; 123 return this; 124 } 125 126 public Builder maxRetriesOnException(int maxRetriesOnException) { 127 this.maxRetriesOnException = maxRetriesOnException; 128 return this; 129 } 130 131 public BoxRetryStrategy build() { 132 if (this.maxAttempts == null) { 133 this.maxAttempts = 5; 134 } 135 if (this.retryRandomizationFactor == null) { 136 this.retryRandomizationFactor = 0.5d; 137 } 138 if (this.retryBaseInterval == null) { 139 this.retryBaseInterval = 1d; 140 } 141 if (this.maxRetriesOnException == null) { 142 this.maxRetriesOnException = 2; 143 } 144 return new BoxRetryStrategy(this); 145 } 146 } 147}