Skip to content

Commit 7868f2d

Browse files
authored
add request id as parameter to every request (#255)
1 parent 939bc66 commit 7868f2d

File tree

4 files changed

+164
-15
lines changed

4 files changed

+164
-15
lines changed

AndroidSDKCore/src/main/java/com/leanplum/Leanplum.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import com.leanplum.utils.SharedPreferencesUtil;
5656

5757
import org.json.JSONArray;
58+
import org.json.JSONException;
5859
import org.json.JSONObject;
5960

6061
import java.util.ArrayList;
@@ -706,7 +707,6 @@ public void response(List<Map<String, Object>> requests, JSONObject response, in
706707

707708
private static void handleApiResponse(JSONObject response, List<Map<String, Object>> requests,
708709
final Request request, int countOfUnsentRequests) {
709-
boolean hasStartResponse = false;
710710
JSONObject lastStartResponse = null;
711711

712712
// Find and handle the last start response.
@@ -718,23 +718,12 @@ private static void handleApiResponse(JSONObject response, List<Map<String, Obje
718718
request.setDataBaseIndex(request.getDataBaseIndex() - countOfUnsentRequests);
719719
return;
720720
}
721-
722-
final int responseCount = Request.numResponses(response);
723-
for (int i = requests.size() - 1; i >= 0; i--) {
724-
Map<String, Object> currentRequest = requests.get(i);
725-
if (Constants.Methods.START.equals(currentRequest.get(Constants.Params.ACTION))) {
726-
if (i < responseCount) {
727-
lastStartResponse = Request.getResponseAt(response, i);
728-
}
729-
hasStartResponse = true;
730-
break;
731-
}
732-
}
721+
lastStartResponse = parseLastStartResponse(response, requests);
733722
} catch (Throwable t) {
734723
Util.handleException(t);
735724
}
736725

737-
if (hasStartResponse) {
726+
if (lastStartResponse != null) {
738727
if (!LeanplumInternal.hasStarted()) {
739728
// Set start response to null.
740729
request.onApiResponse(null);
@@ -743,6 +732,29 @@ private static void handleApiResponse(JSONObject response, List<Map<String, Obje
743732
}
744733
}
745734

735+
@VisibleForTesting
736+
public static JSONObject parseLastStartResponse(JSONObject response, List<Map<String, Object>> requests) {
737+
final int responseCount = Request.numResponses(response);
738+
for (int i = requests.size() - 1; i >= 0; i--) {
739+
Map<String, Object> currentRequest = requests.get(i);
740+
if (Constants.Methods.START.equals(currentRequest.get(Constants.Params.ACTION))) {
741+
if (currentRequest.containsKey(Request.REQUEST_ID_KEY)) {
742+
for (int j = Request.numResponses(response) - 1; j >= 0; j--) {
743+
JSONObject currentResponse = Request.getResponseAt(response, j);
744+
if (currentRequest.get(Request.REQUEST_ID_KEY)
745+
.equals(currentResponse.optString(Request.REQUEST_ID_KEY))) {
746+
return currentResponse;
747+
}
748+
}
749+
}
750+
if (i < responseCount) {
751+
return Request.getResponseAt(response, i);
752+
}
753+
}
754+
}
755+
return null;
756+
}
757+
746758
private static void handleStartResponse(final JSONObject response) {
747759
Util.executeAsyncTask(false, new AsyncTask<Void, Void, Void>() {
748760
@Override

AndroidSDKCore/src/main/java/com/leanplum/internal/Request.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import android.os.AsyncTask;
2727
import android.os.Build;
2828
import android.support.annotation.NonNull;
29+
import android.support.annotation.VisibleForTesting;
2930
import android.text.TextUtils;
3031

3132
import com.leanplum.Leanplum;
@@ -56,6 +57,8 @@
5657
* @author Andrew First
5758
*/
5859
public class Request {
60+
public static final String REQUEST_ID_KEY = "reqId";
61+
5962
private static final long DEVELOPMENT_MIN_DELAY_MS = 100;
6063
private static final long DEVELOPMENT_MAX_DELAY_MS = 5000;
6164
private static final long PRODUCTION_DELAY = 60000;
@@ -91,6 +94,7 @@ public class Request {
9194
private ErrorCallback error;
9295
private boolean sent;
9396
private long dataBaseIndex;
97+
private String requestId;
9498

9599
private static ApiResponseCallback apiResponse;
96100

@@ -215,6 +219,7 @@ public Request(String httpMethod, String apiMethod, Map<String, Object> params)
215219
OsHandler.getInstance();
216220
dataBaseIndex = -1;
217221
this.requestSequenceRecorder = requestSequenceRecorder;
222+
this.requestId = UUID.randomUUID().toString();
218223
}
219224

220225
public static Request get(String apiMethod, Map<String, Object> params) {
@@ -243,14 +248,16 @@ public void onApiResponse(ApiResponseCallback apiResponse) {
243248
Request.apiResponse = apiResponse;
244249
}
245250

246-
private Map<String, Object> createArgsDictionary() {
251+
@VisibleForTesting
252+
public Map<String, Object> createArgsDictionary() {
247253
Map<String, Object> args = new HashMap<>();
248254
args.put(Constants.Params.DEVICE_ID, deviceId);
249255
args.put(Constants.Params.USER_ID, userId);
250256
args.put(Constants.Params.ACTION, apiMethod);
251257
args.put(Constants.Params.SDK_VERSION, Constants.LEANPLUM_VERSION);
252258
args.put(Constants.Params.DEV_MODE, Boolean.toString(Constants.isDevelopmentModeEnabled));
253259
args.put(Constants.Params.TIME, Double.toString(new Date().getTime() / 1000.0));
260+
args.put(Request.REQUEST_ID_KEY, requestId);
254261
if (token != null) {
255262
args.put(Constants.Params.TOKEN, token);
256263
}

AndroidSDKTests/src/test/java/com/leanplum/LeanplumTest.java

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import java.util.Arrays;
6060
import java.util.HashMap;
6161
import java.util.HashSet;
62+
import java.util.Iterator;
6263
import java.util.List;
6364
import java.util.Locale;
6465
import java.util.Map;
@@ -1333,4 +1334,125 @@ public void testParseFeatureFlags() throws JSONException {
13331334
Set<String> parsedFeatureFlags = Leanplum.parseFeatureFlags(response);
13341335
assertEquals(new HashSet<>(Arrays.asList("test")), parsedFeatureFlags);
13351336
}
1337+
1338+
/**
1339+
* Responses without uuid should be matched on index.
1340+
*/
1341+
@Test
1342+
public void testParseLastStartResponseWithoutUUID() {
1343+
final String index = "index";
1344+
1345+
List<Map<String, Object>> requests = new ArrayList<>(startRequestsWithCount(2));
1346+
requests.addAll(trackRequestsWithCount(2));
1347+
requests.addAll(startRequestsWithCount(3));
1348+
requests.addAll(trackRequestsWithCount(3));
1349+
requests.addAll(startRequestsWithCount(4));
1350+
1351+
List<JSONObject> responsesList = new ArrayList<>();
1352+
for (int i=0;i < 15; i ++) {
1353+
Map<String, Object> responseMap = new HashMap<>();
1354+
responseMap.put(index, Integer.toString(i));
1355+
responsesList.add(new JSONObject(responseMap));
1356+
}
1357+
1358+
Map<String, Object> responsesMap = new HashMap<>();
1359+
responsesMap.put("response", new JSONArray(responsesList));
1360+
JSONObject response = new JSONObject(responsesMap);
1361+
1362+
JSONObject lastStartResponse = Leanplum.parseLastStartResponse(response, requests);
1363+
assertNotNull(lastStartResponse);
1364+
lastStartResponse.optString(index).equals("13");
1365+
}
1366+
1367+
/**
1368+
* Empty response should return null for parseLastStartResponse
1369+
*/
1370+
@Test
1371+
public void testParseLastStartResponseEmpty() {
1372+
JSONObject response = new JSONObject();
1373+
List<Map<String, Object>> requests = new ArrayList<>();
1374+
1375+
JSONObject lastStartResponse = Leanplum.parseLastStartResponse(response, requests);
1376+
assertNull(lastStartResponse);
1377+
}
1378+
1379+
/**
1380+
* Single response should return response for parseLastStartResponse
1381+
*/
1382+
@Test
1383+
public void testParseLastStartResponseGivenSingleStartShouldReturnResponse() throws JSONException {
1384+
List<Map<String, Object>> requests = startRequestsWithCount(1);
1385+
1386+
List<JSONObject> responsesList = startResponsesWithCount(1);
1387+
1388+
Map<String, Object> responsesMap = new HashMap<>();
1389+
responsesMap.put("response", new JSONArray(responsesList));
1390+
JSONObject response = new JSONObject(responsesMap);
1391+
1392+
1393+
JSONObject lastStartResponse = Leanplum.parseLastStartResponse(response, requests);
1394+
assertNotNull(lastStartResponse);
1395+
lastStartResponse.optString("uuid").equals("start-uuid-0");
1396+
}
1397+
1398+
/**
1399+
* Multiple responses should return correct response for parseLastStartResponse
1400+
*/
1401+
@Test
1402+
public void testParseLastStartResponseGivenMultipleStartShouldReturnResponse() throws JSONException {
1403+
List<Map<String, Object>> requests = new ArrayList<>(startRequestsWithCount(2));
1404+
requests.addAll(trackRequestsWithCount(2));
1405+
requests.addAll(startRequestsWithCount(3));
1406+
requests.addAll(trackRequestsWithCount(3));
1407+
requests.addAll(startRequestsWithCount(4));
1408+
1409+
List<JSONObject> responsesList = startResponsesWithCount(2);
1410+
responsesList.addAll(trackResponsesWithCount(3));
1411+
responsesList.addAll(startResponsesWithCount(4));
1412+
responsesList.addAll(trackResponsesWithCount(3));
1413+
1414+
Map<String, Object> responsesMap = new HashMap<>();
1415+
responsesMap.put("response", new JSONArray(responsesList));
1416+
JSONObject response = new JSONObject(responsesMap);
1417+
1418+
JSONObject lastStartResponse = Leanplum.parseLastStartResponse(response, requests);
1419+
assertNotNull(lastStartResponse);
1420+
lastStartResponse.optString("uuid").equals("start-uuid-3");
1421+
}
1422+
1423+
private List<Map<String, Object>> startRequestsWithCount(int n) {
1424+
return requestsWithCountAndPrefix(n, "start"); }
1425+
1426+
private List<Map<String, Object>> trackRequestsWithCount(int n) {
1427+
return requestsWithCountAndPrefix(n, "track");
1428+
}
1429+
1430+
private List<Map<String, Object>> requestsWithCountAndPrefix(int n, String prefix) {
1431+
List<Map<String, Object>> requests = new ArrayList<>();
1432+
for (int i=0;i < n; i ++) {
1433+
Map<String, Object> request = new HashMap<>();
1434+
request.put(Request.REQUEST_ID_KEY, prefix + "-uuid-" + Integer.toString(i));
1435+
request.put(Constants.Params.ACTION, Constants.Methods.START);
1436+
requests.add(request);
1437+
}
1438+
return requests;
1439+
}
1440+
1441+
private List<JSONObject> startResponsesWithCount(int n) {
1442+
return responsesWithCountAndPrefix(n, "start");
1443+
}
1444+
1445+
private List<JSONObject> trackResponsesWithCount(int n) {
1446+
return responsesWithCountAndPrefix(n, "track");
1447+
}
1448+
1449+
private List<JSONObject> responsesWithCountAndPrefix(int n, String prefix) {
1450+
List<JSONObject> responsesList = new ArrayList<>();
1451+
for (int i=0;i < n; i ++) {
1452+
Map<String, Object> responseMap = new HashMap<>();
1453+
responseMap.put(Request.REQUEST_ID_KEY, prefix + "-uuid-" + Integer.toString(i));
1454+
responsesList.add(new JSONObject(responseMap));
1455+
}
1456+
return responsesList;
1457+
}
13361458
}

AndroidSDKTests/src/test/java/com/leanplum/internal/RequestTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ public void setUp() {
7171
Leanplum.setApplicationContext(context);
7272
}
7373

74+
/** Test that request include a generated request id **/
75+
@Test
76+
public void testCreateArgsDictionaryShouldIncludeRequestId() {
77+
Request request = new Request(POST, Constants.Methods.START, null);
78+
Map<String, Object> args = request.createArgsDictionary();
79+
assertTrue(args.containsKey(Request.REQUEST_ID_KEY));
80+
}
81+
7482
/** Test that read writes happened sequentially when calling sendNow(). */
7583
@Test
7684
public void shouldWriteRequestAndSendInSequence() throws InterruptedException {

0 commit comments

Comments
 (0)