Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions code/edge/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ dependencies {
testImplementation("com.github.adobe:aepsdk-testutils-android:$mavenTestUtilsVersion")

androidTestImplementation("com.github.adobe:aepsdk-testutils-android:$mavenTestUtilsVersion")
androidTestImplementation("com.adobe.marketing.mobile:edgeconsent:$mavenEdgeConsentVersion")
{
androidTestImplementation("com.adobe.marketing.mobile:edgeconsent:$mavenEdgeConsentVersion") {
exclude(group = "com.adobe.marketing.mobile", module = "edge")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
final class EdgeConstants {

static final String EDGE_DATA_STORAGE = "EdgeDataStorage";
static final String EXTENSION_VERSION = "3.0.1";
static final String EXTENSION_VERSION = "3.0.2";
static final String EXTENSION_NAME = "com.adobe.edge";
static final String FRIENDLY_NAME = "Edge";
static final String LOG_TAG = FRIENDLY_NAME;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,20 @@
import com.adobe.marketing.mobile.services.Log;
import com.adobe.marketing.mobile.services.NetworkRequest;
import com.adobe.marketing.mobile.services.Networking;
import com.adobe.marketing.mobile.services.NetworkingConstants;
import com.adobe.marketing.mobile.util.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.json.JSONException;
import org.json.JSONObject;
Expand Down Expand Up @@ -98,14 +100,13 @@ interface ResponseCallback {
private static final String DEFAULT_GENERIC_ERROR_MESSAGE =
"Request to Edge Network failed with an unknown exception";

static final List<Integer> recoverableNetworkErrorCodes = new ArrayList<>(
static final Set<Integer> recoverableNetworkErrorCodes = mergeUnique(
NetworkingConstants.RECOVERABLE_ERROR_CODES,
Arrays.asList(
-1, // returned for SocketTimeoutException
429, // too many requests - The user has sent too many requests in a given amount of time ("rate limiting").
HttpURLConnection.HTTP_CLIENT_TIMEOUT,
HttpURLConnection.HTTP_BAD_GATEWAY,
HttpURLConnection.HTTP_UNAVAILABLE,
HttpURLConnection.HTTP_GATEWAY_TIMEOUT
507, // insufficient storage
HttpURLConnection.HTTP_BAD_GATEWAY
)
);

Expand Down Expand Up @@ -258,9 +259,10 @@ RetryResult doRequest(
private int computeRetryInterval(final HttpConnecting connection) {
String header = connection.getResponsePropertyValue(EdgeConstants.NetworkKeys.HEADER_KEY_RETRY_AFTER);

int retryAfter = EdgeConstants.Defaults.RETRY_INTERVAL_SECONDS;
if (header != null && header.matches("\\d+")) {
try {
return Integer.parseInt(header);
retryAfter = Integer.parseInt(header);
} catch (NumberFormatException e) {
Log.debug(
LOG_TAG,
Expand All @@ -272,7 +274,7 @@ private int computeRetryInterval(final HttpConnecting connection) {
}
}

return EdgeConstants.Defaults.RETRY_INTERVAL_SECONDS;
return retryAfter > 0 ? retryAfter : EdgeConstants.Defaults.RETRY_INTERVAL_SECONDS;
}

/**
Expand Down Expand Up @@ -577,4 +579,11 @@ private String readInputStream(final InputStream inputStream) {
return composeGenericErrorAsJson(e.getMessage());
}
}

private static Set<Integer> mergeUnique(final List<Integer> arr1, final List<Integer> arr2) {
Set<Integer> merged = new HashSet<>();
merged.addAll(arr1);
merged.addAll(arr2);
return merged;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@

import com.adobe.marketing.mobile.services.HttpMethod;
import com.adobe.marketing.mobile.services.NetworkRequest;
import com.adobe.marketing.mobile.services.NetworkingConstants;
import com.adobe.marketing.mobile.util.MockConnection;
import com.adobe.marketing.mobile.util.MockNetworkService;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.json.JSONException;
Expand All @@ -50,6 +54,7 @@ public class EdgeNetworkServiceTest {
private static final String TEST_URL = "https://test.com";
private static final String HEADER_CONTENT_TYPE = "Content-Type";
private static final String HEADER_CONTENT_TYPE_JSON_VALUE = "application/json";
private static final String HEADER_RETRY_AFTER = "Retry-After";
private final Map<String, String> requestHeaders = new HashMap<String, String>() {
{
put("key1", "value1");
Expand Down Expand Up @@ -360,6 +365,65 @@ public void testDoRequest_whenConnection_RecoverableResponseCode_504_ReturnsRetr
testRecoverableNetworkResponse(504, "Gateway Timeout");
}

@Test
public void testDoRequest_whenConnection_RecoverableResponseCode_507_ReturnsRetryYes_AndNoResponseCallback_AndNoErrorCallback() {
testRecoverableNetworkResponse(507, "Insufficient Storage");
}

@Test
public void testDoRequest_whenConnection_RecoverableResponseCodeAndRetryAfter_ReturnsRetryTimeout() {
Set<Integer> recoverableNetworkErrorCodes = new HashSet<>();
recoverableNetworkErrorCodes.addAll(NetworkingConstants.RECOVERABLE_ERROR_CODES);
recoverableNetworkErrorCodes.addAll(Arrays.asList(429, 502, 507, -1));

for (int responseCode : recoverableNetworkErrorCodes) {
testRecoverableWithRetryAfter(responseCode, "30", 30);
}
}

@Test
public void testDoRequest_whenConnection_InvalidRetryAfter_ReturnsDefaultRetryTimeout() {
testRecoverableNetworkResponse(507, "Insufficient Storage");
String[] invalidRetryAfter = { "InvalidRetryAfter", "A", "", "-1", "0", " " };

for (String retryAfter : invalidRetryAfter) {
testRecoverableWithRetryAfter(503, retryAfter, 5); // expecting default timeout
}
}

@Test
public void testDoRequest_whenConnection_ValidRetryAfter_ReturnsCorrectRetryTimeout() {
testRecoverableNetworkResponse(507, "Insufficient Storage");
String[] invalidRetryAfter = { "1", "5", "30", "60", "180", "300" };

for (String retryAfter : invalidRetryAfter) {
testRecoverableWithRetryAfter(503, retryAfter, Integer.parseInt(retryAfter)); // expecting provided timeout
}
}

private void testRecoverableWithRetryAfter(
final int responseCode,
final String retryAfter,
final int expectedRetryAfter
) {
// setup
final String url = "https://test.com";
final String jsonRequest = "{}";
final Map<String, String> headers = new HashMap<>();
headers.put(HEADER_RETRY_AFTER, retryAfter);
MockConnection mockConnection = new MockConnection(responseCode, null, "error", headers);
mockNetworkService.reset();
mockNetworkService.setMockResponseFor(url, mockConnection);
networkService = new EdgeNetworkService(mockNetworkService);

// test
DoRequestResult result = doRequestSync(url, jsonRequest);

// verify
assertEquals(EdgeNetworkService.Retry.YES, result.retryResult.getShouldRetry());
assertEquals(expectedRetryAfter, result.retryResult.getRetryIntervalSeconds());
}

private void testRecoverableNetworkResponse(final int responseCode, final String errorString) {
// setup
final String url = "https://test.com";
Expand Down
2 changes: 1 addition & 1 deletion code/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ org.gradle.configureondemand=false
org.gradle.caching=true

moduleName=edge
moduleVersion=3.0.1
moduleVersion=3.0.2
mavenCoreVersion=3.3.0
mavenEdgeIdentityVersion=3.0.1
mavenEdgeConsentVersion=3.0.0
Expand Down
Loading