Skip to content

Commit 39e51b9

Browse files
authored
RequestSender refactoring (#421)
* Improve send() and sendNow() methods in RequestSender * Fix unit tests. Use anonymous classes instead of lambdas because of PowerMock * Changed methods naming * Add Request.type, remove Request.sent, fix thread sync issue * Fix unit tests * Remove unnecessary code
1 parent 22f2993 commit 39e51b9

25 files changed

+442
-338
lines changed

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

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@
4848
import com.leanplum.internal.OperationQueue;
4949
import com.leanplum.internal.Registration;
5050
import com.leanplum.internal.Request;
51+
import com.leanplum.internal.Request.RequestType;
5152
import com.leanplum.internal.RequestBuilder;
5253
import com.leanplum.internal.RequestSender;
54+
import com.leanplum.internal.RequestSenderTimer;
5355
import com.leanplum.internal.RequestUtil;
5456
import com.leanplum.internal.Util;
5557
import com.leanplum.internal.Util.DeviceIdInfo;
@@ -71,9 +73,6 @@
7173
import java.util.Map;
7274
import java.util.Set;
7375
import java.util.TimeZone;
74-
import java.util.concurrent.Executors;
75-
import java.util.concurrent.ScheduledExecutorService;
76-
import java.util.concurrent.TimeUnit;
7776

7877
import androidx.annotation.VisibleForTesting;
7978

@@ -111,7 +110,6 @@ public class Leanplum {
111110
private static String customAppVersion = null;
112111
private static boolean userSpecifiedDeviceId;
113112
private static boolean locationCollectionEnabled = true;
114-
private static ScheduledExecutorService heartbeatExecutor = null;
115113
private static Context context;
116114

117115
private static Runnable pushStartCallback;
@@ -733,7 +731,12 @@ private static void startHelper(
733731
Util.initializePreLeanplumInstall(params);
734732

735733
// Issue start API call.
736-
final Request request = RequestBuilder.withStartAction().andParams(params).create();
734+
RequestType requestType = isBackground ? RequestType.DEFAULT : RequestType.IMMEDIATE;
735+
Request request = RequestBuilder
736+
.withStartAction()
737+
.andParams(params)
738+
.andType(requestType)
739+
.create();
737740
request.onResponse(new Request.ResponseCallback() {
738741
@Override
739742
public void response(JSONObject response) {
@@ -748,12 +751,7 @@ public void error(Exception e) {
748751
handleStartResponse(null);
749752
}
750753
});
751-
752-
if (isBackground) {
753-
RequestSender.getInstance().sendEventually(request);
754-
} else {
755-
RequestSender.getInstance().sendIfConnected(request);
756-
}
754+
RequestSender.getInstance().send(request);
757755

758756
LeanplumInternal.triggerStartIssued();
759757
}
@@ -932,7 +930,7 @@ public void run() {
932930
}
933931
}
934932
LeanplumInternal.moveToForeground();
935-
startHeartbeat();
933+
startRequestTimer();
936934
} catch (Throwable t) {
937935
Log.exception(t);
938936
} finally {
@@ -1006,9 +1004,12 @@ public void run() {
10061004
}
10071005

10081006
private static void pauseInternal() {
1009-
Request request = RequestBuilder.withPauseSessionAction().create();
1010-
RequestSender.getInstance().sendIfConnected(request);
1011-
pauseHeartbeat();
1007+
Request request = RequestBuilder
1008+
.withPauseSessionAction()
1009+
.andType(RequestType.IMMEDIATE)
1010+
.create();
1011+
RequestSender.getInstance().send(request);
1012+
stopRequestTimer();
10121013
LeanplumInternal.setIsPaused(true);
10131014
}
10141015

@@ -1041,55 +1042,28 @@ public void run() {
10411042
}
10421043

10431044
private static void resumeInternal() {
1044-
Request request = RequestBuilder.withResumeSessionAction().create();
1045+
Request request = RequestBuilder
1046+
.withResumeSessionAction()
1047+
.andType(RequestType.IMMEDIATE)
1048+
.create();
1049+
RequestSender.getInstance().send(request);
1050+
10451051
if (LeanplumInternal.hasStartedInBackground()) {
10461052
LeanplumInternal.setStartedInBackground(false);
1047-
RequestSender.getInstance().sendIfConnected(request);
10481053
} else {
1049-
RequestSender.getInstance().sendIfDelayed(request);
10501054
LeanplumInternal.maybePerformActions("resume", null,
10511055
LeanplumMessageMatchFilter.LEANPLUM_ACTION_FILTER_ALL, null, null);
10521056
}
1053-
resumeHeartbeat();
1057+
startRequestTimer();
10541058
LeanplumInternal.setIsPaused(false);
10551059
}
10561060

1057-
/**
1058-
* Send a heartbeat every 15 minutes while the app is running.
1059-
*/
1060-
private static void startHeartbeat() {
1061-
synchronized (heartbeatLock) {
1062-
if (heartbeatExecutor == null) {
1063-
createHeartbeatExecutor();
1064-
}
1065-
}
1061+
private static void startRequestTimer() {
1062+
RequestSenderTimer.get().start();
10661063
}
10671064

1068-
private static void pauseHeartbeat() {
1069-
synchronized (heartbeatLock) {
1070-
if (heartbeatExecutor != null) {
1071-
heartbeatExecutor.shutdown();
1072-
heartbeatExecutor = null;
1073-
}
1074-
}
1075-
}
1076-
1077-
private static void resumeHeartbeat() {
1078-
startHeartbeat();
1079-
}
1080-
1081-
private static void createHeartbeatExecutor() {
1082-
heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
1083-
heartbeatExecutor.scheduleAtFixedRate(new Runnable() {
1084-
public void run() {
1085-
try {
1086-
Request request = RequestBuilder.withHeartbeatAction().create();
1087-
RequestSender.getInstance().sendIfDelayed(request);
1088-
} catch (Throwable t) {
1089-
Log.exception(t);
1090-
}
1091-
}
1092-
}, 15, 15, TimeUnit.MINUTES);
1065+
private static void stopRequestTimer() {
1066+
RequestSenderTimer.get().stop();
10931067
}
10941068

10951069
/**
@@ -1122,8 +1096,8 @@ public void run() {
11221096
}
11231097

11241098
private static void stopInternal() {
1125-
Request request = RequestBuilder.withStopAction().create();
1126-
RequestSender.getInstance().sendIfConnected(request);
1099+
Request request = RequestBuilder.withStopAction().andType(RequestType.IMMEDIATE).create();
1100+
RequestSender.getInstance().send(request);
11271101
}
11281102

11291103
/**
@@ -1586,8 +1560,9 @@ public void run() {
15861560
Request request = RequestBuilder
15871561
.withSetDeviceAttributesAction()
15881562
.andParam(Constants.Params.DEVICE_PUSH_TOKEN, registrationId)
1563+
.andType(RequestType.IMMEDIATE)
15891564
.create();
1590-
RequestSender.getInstance().sendIfConnected(request);
1565+
RequestSender.getInstance().send(request);
15911566
} catch (Throwable t) {
15921567
Log.exception(t);
15931568
}
@@ -2063,6 +2038,7 @@ public static void forceContentUpdate(final VariablesChangedCallback callback) {
20632038
.andParam(Constants.Params.INCLUDE_DEFAULTS, Boolean.toString(false))
20642039
.andParam(Constants.Params.INBOX_MESSAGES, LeanplumInbox.getInstance().messagesIds())
20652040
.andParam(Constants.Params.INCLUDE_VARIANT_DEBUG_INFO, LeanplumInternal.getIsVariantDebugInfoEnabled())
2041+
.andType(RequestType.IMMEDIATE)
20662042
.create();
20672043
req.onResponse(new Request.ResponseCallback() {
20682044
@Override
@@ -2098,7 +2074,7 @@ public void error(Exception e) {
20982074
LeanplumInbox.getInstance().triggerInboxSyncedWithStatus(false);
20992075
}
21002076
});
2101-
RequestSender.getInstance().sendIfConnected(req);
2077+
RequestSender.getInstance().send(req);
21022078
} catch (Throwable t) {
21032079
Log.exception(t);
21042080
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@
3434
import com.leanplum.internal.JsonConverter;
3535
import com.leanplum.internal.Log;
3636
import com.leanplum.internal.OperationQueue;
37+
import com.leanplum.internal.Request.RequestType;
3738
import com.leanplum.internal.RequestBuilder;
3839
import com.leanplum.internal.Request;
3940
import com.leanplum.internal.RequestSender;
40-
import com.leanplum.internal.Util;
4141
import com.leanplum.utils.SharedPreferencesUtil;
4242

4343
import org.json.JSONObject;
@@ -351,7 +351,10 @@ void downloadMessages() {
351351
return;
352352
}
353353

354-
Request req = RequestBuilder.withGetInboxMessagesAction().create();
354+
Request req = RequestBuilder
355+
.withGetInboxMessagesAction()
356+
.andType(RequestType.IMMEDIATE)
357+
.create();
355358
req.onResponse(new Request.ResponseCallback() {
356359
@Override
357360
public void response(JSONObject response) {
@@ -421,7 +424,7 @@ public void error(Exception e) {
421424
triggerInboxSyncedWithStatus(false);
422425
}
423426
});
424-
RequestSender.getInstance().sendIfConnected(req);
427+
RequestSender.getInstance().send(req);
425428
}
426429

427430
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void sendAllCounts() {
6363
Map<String, Object> params = makeParams(name, count);
6464
try {
6565
Request request = RequestBuilder.withLogAction().andParams(params).create();
66-
RequestSender.getInstance().sendEventually(request);
66+
RequestSender.getInstance().send(request);
6767
} catch (Throwable t) {
6868
android.util.Log.e("Leanplum", "Unable to send count.", t);
6969
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void addCallbacks(Request request, Request.ResponseCallback responseCallback,
5656
return;
5757
}
5858

59-
callbacks.put(request.requestId(), new LeanplumEventCallbacks(responseCallback, errorCallback));
59+
callbacks.put(request.getRequestId(), new LeanplumEventCallbacks(responseCallback, errorCallback));
6060
}
6161

6262
/**

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public class LeanplumEventDataManager {
6060
private SQLiteDatabase database;
6161
private LeanplumDataBaseManager databaseManager;
6262
private ContentValues contentValues = new ContentValues();
63-
private boolean sendErrorLogs = false;
63+
private boolean hasDatabaseError = false;
6464

6565
private LeanplumEventDataManager() {
6666
try {
@@ -99,7 +99,7 @@ void insertEvent(String event) {
9999
contentValues.put(COLUMN_DATA, event);
100100
try {
101101
database.insert(EVENT_TABLE_NAME, null, contentValues);
102-
sendErrorLogs = false;
102+
hasDatabaseError = false;
103103
} catch (Throwable t) {
104104
handleSQLiteError("Unable to insert event to database.", t);
105105
}
@@ -121,7 +121,7 @@ List<Map<String, Object>> getEvents(int count) {
121121
try {
122122
cursor = database.query(EVENT_TABLE_NAME, new String[] {COLUMN_DATA}, null, null, null,
123123
null, KEY_ROWID + " ASC", "" + count);
124-
sendErrorLogs = false;
124+
hasDatabaseError = false;
125125
while (cursor.moveToNext()) {
126126
Map<String, Object> requestArgs = JsonConverter.mapFromJson(new JSONObject(
127127
cursor.getString(cursor.getColumnIndex(COLUMN_DATA))));
@@ -149,7 +149,7 @@ void deleteEvents(int count) {
149149
try {
150150
database.delete(EVENT_TABLE_NAME, KEY_ROWID + " in (select " + KEY_ROWID + " from " +
151151
EVENT_TABLE_NAME + " ORDER BY " + KEY_ROWID + " ASC LIMIT " + count + ")", null);
152-
sendErrorLogs = false;
152+
hasDatabaseError = false;
153153
} catch (Throwable t) {
154154
handleSQLiteError("Unable to delete events from the table.", t);
155155
}
@@ -167,7 +167,7 @@ long getEventsCount() {
167167
}
168168
try {
169169
count = DatabaseUtils.queryNumEntries(database, EVENT_TABLE_NAME);
170-
sendErrorLogs = false;
170+
hasDatabaseError = false;
171171
} catch (Throwable t) {
172172
handleSQLiteError("Unable to get a number of rows in the table.", t);
173173
}
@@ -177,18 +177,18 @@ long getEventsCount() {
177177
/**
178178
* Whether we are going to send error log or not.
179179
*/
180-
boolean willSendErrorLogs() {
181-
return sendErrorLogs;
180+
boolean hasDatabaseError() {
181+
return hasDatabaseError;
182182
}
183183

184184
/**
185185
* Helper function that logs and sends errors to the server.
186186
*/
187187
private void handleSQLiteError(String log, Throwable t) {
188188
Log.e(log, t);
189-
// Send error log. Using willSendErrorLog to prevent infinte loop.
190-
if (!sendErrorLogs) {
191-
sendErrorLogs = true;
189+
if (!hasDatabaseError) {
190+
hasDatabaseError = true;
191+
// Sending error log. It will be intercepted when requests are sent.
192192
Log.exception(t);
193193
}
194194
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.leanplum.callbacks.ActionCallback;
3434
import com.leanplum.callbacks.StartCallback;
3535
import com.leanplum.callbacks.VariablesChangedCallback;
36+
import com.leanplum.internal.Request.RequestType;
3637
import com.leanplum.models.GeofenceEventType;
3738

3839
import org.json.JSONException;
@@ -345,8 +346,12 @@ public static void trackGeofence(final GeofenceEventType event, double value, St
345346

346347
try {
347348
final Map<String, Object> requestParams = makeTrackArgs(event.getName(), value, info, params, args);
348-
Request request = RequestBuilder.withTrackGeofenceAction().andParams(requestParams).create();
349-
RequestSender.getInstance().sendIfConnected(request);
349+
Request request = RequestBuilder
350+
.withTrackGeofenceAction()
351+
.andParams(requestParams)
352+
.andType(RequestType.IMMEDIATE)
353+
.create();
354+
RequestSender.getInstance().send(request);
350355
} catch (Throwable t) {
351356
Log.exception(t);
352357
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424

2525
import com.leanplum.LeanplumException;
26+
import com.leanplum.internal.Request.RequestType;
2627
import com.leanplum.monitoring.ExceptionHandler;
2728

2829
import java.io.PrintWriter;
@@ -104,6 +105,7 @@ public static void exception(Throwable throwable) {
104105
.andParam(Constants.Params.TYPE, Constants.Values.SDK_LOG)
105106
.andParam(Constants.Params.VERSION_NAME, versionName)
106107
.andParam(Constants.Params.MESSAGE, stringWriter.toString())
108+
.andType(RequestType.IMMEDIATE)
107109
.create();
108110
RequestSender.getInstance().send(request);
109111
} catch (Throwable t2) {
@@ -164,7 +166,7 @@ private static void handleLogMessage(String tag, String msg) {
164166
.andParam(Constants.Params.TYPE, Constants.Values.SDK_LOG)
165167
.andParam(Constants.Params.MESSAGE, tag + msg)
166168
.create();
167-
RequestSender.getInstance().sendEventually(request);
169+
RequestSender.getInstance().send(request);
168170
}
169171
}
170172

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ public boolean addOperationAfterDelay(Runnable operation, long delayMillis) {
144144
return false;
145145
}
146146

147+
/**
148+
* Removes pending operation from OperationQueue.
149+
*/
150+
public void removeOperation(Runnable operation) {
151+
if (operation != null && handler != null) {
152+
handler.removeCallbacks(operation);
153+
}
154+
}
155+
147156
/**
148157
* Remove all pending Operations that are in OperationQueue
149158
*/

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@
2121

2222
package com.leanplum.internal;
2323

24-
import com.leanplum.Leanplum;
2524
import com.leanplum.callbacks.StartCallback;
2625

26+
import com.leanplum.internal.Request.RequestType;
2727
import org.json.JSONObject;
2828

2929
public class Registration {
3030
public static void registerDevice(String email, final StartCallback callback) {
3131
Request request = RequestBuilder
3232
.withRegisterForDevelopmentAction()
3333
.andParam(Constants.Params.EMAIL, email)
34+
.andType(RequestType.IMMEDIATE)
3435
.create();
3536

3637
request.onResponse(new Request.ResponseCallback() {
@@ -59,6 +60,6 @@ public void error(final Exception e) {
5960
OperationQueue.sharedInstance().addUiOperation(callback);
6061
}
6162
});
62-
RequestSender.getInstance().sendIfConnected(request);
63+
RequestSender.getInstance().send(request);
6364
}
6465
}

0 commit comments

Comments
 (0)