Skip to content

Commit

Permalink
Merge pull request #490 from rudderlabs/release/1.26.0
Browse files Browse the repository at this point in the history
chore(release): pulling release/1.26.0 into master
  • Loading branch information
1abhishekpandey authored Dec 9, 2024
2 parents d217056 + 6575233 commit 8085d05
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 52 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [1.26.0](https://github.com/rudderlabs/rudder-sdk-android/compare/v1.25.0...v1.26.0) (2024-12-09)


### Features

* add alias api with previousId support ([#485](https://github.com/rudderlabs/rudder-sdk-android/issues/485)) ([179c262](https://github.com/rudderlabs/rudder-sdk-android/commit/179c26276d9c875d9ebeec6d8ed8d3c105bc805a))


### Bug Fixes

* catch OutOfMemoryError in RudderCloudModeManager ([#487](https://github.com/rudderlabs/rudder-sdk-android/issues/487)) ([0b3759e](https://github.com/rudderlabs/rudder-sdk-android/commit/0b3759e66ab93894932d0b20f14d848d50030d81))
* handle invalid json issue ([#486](https://github.com/rudderlabs/rudder-sdk-android/issues/486)) ([4579fc2](https://github.com/rudderlabs/rudder-sdk-android/commit/4579fc2e936957ece459e6541c290a2bc2a9c6ac))

### [1.25.1](https://github.com/rudderlabs/rudder-sdk-android/compare/v1.25.0...v1.25.1) (2024-10-14)


Expand Down
32 changes: 20 additions & 12 deletions core/src/main/java/com/rudderstack/android/sdk/core/FlushUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import static com.rudderstack.android.sdk.core.RudderNetworkManager.Result;
import static com.rudderstack.android.sdk.core.util.Utils.getBatch;
import static com.rudderstack.android.sdk.core.util.Utils.getNumberOfBatches;
import androidx.annotation.Nullable;

import android.text.TextUtils;

Expand Down Expand Up @@ -88,6 +89,7 @@ static boolean flushToServer(int flushQueueSize, String dataPlaneUrl, DBPersiste

} else {
lastErrorMessage = ReportManager.LABEL_TYPE_PAYLOAD_NULL;
dbManager.markCloudModeDone(batchMessageIds);
}
RudderLogger.logWarn(String.format(Locale.US, "EventRepository: flush: Failed to send batch %d/%d retrying again, %d retries left", i, numberOfBatches, retries));
}
Expand Down Expand Up @@ -132,6 +134,7 @@ private static void reportBatchesAndMessages(int numberOfBatches, int messagesSi
* of deserialization and forming the payload object and creating the json string
* again from the object
* */
@Nullable
static String getPayloadFromMessages(List<Integer> messageIds, List<String> messages) {
if (messageIds.isEmpty() || messages.isEmpty()) {
RudderLogger.logWarn("FlushUtils: getPayloadFromMessages: Payload Construction failed: no messages to send");
Expand Down Expand Up @@ -159,22 +162,27 @@ static String getPayloadFromMessages(List<Integer> messageIds, List<String> mess
String message = messages.get(index);
// strip last ending object character
message = message.substring(0, message.length() - 1);
// add sentAt time stamp
message = String.format("%s,\"sentAt\":\"%s\"},", message, sentAtTimestamp);
// add message size to batch size
messageSize = Utils.getUTF8Length(message);
totalBatchSize += messageSize;
// check batch size
if (totalBatchSize >= Utils.MAX_BATCH_SIZE) {
RudderLogger.logDebug(String.format(Locale.US, "FlushUtils: getPayloadFromMessages: MAX_BATCH_SIZE reached at index: %d | Total: %d", index, totalBatchSize));
incrementDiscardedCounter(1, Collections.singletonMap(LABEL_TYPE, ReportManager.LABEL_TYPE_BATCH_SIZE_INVALID));
break;
// Handle Invalid Message whose length is 0
if (!message.isEmpty()) {
// add sentAt time stamp
message = String.format("%s,\"sentAt\":\"%s\"},", message, sentAtTimestamp);
// add message size to batch size
messageSize = Utils.getUTF8Length(message);
totalBatchSize += messageSize;
// check batch size
if (totalBatchSize >= Utils.MAX_BATCH_SIZE) {
RudderLogger.logDebug(String.format(Locale.US, "FlushUtils: getPayloadFromMessages: MAX_BATCH_SIZE reached at index: %d | Total: %d", index, totalBatchSize));
incrementDiscardedCounter(1, Collections.singletonMap(LABEL_TYPE, ReportManager.LABEL_TYPE_BATCH_SIZE_INVALID));
break;
}
// finally add message string to builder
batchMessagesBuilder.append(message);
}
// finally add message string to builder
batchMessagesBuilder.append(message);
// add message to batch ArrayLists
batchMessageIds.add(messageIds.get(index));
}
// If the batchMessagesBuilder is empty, return null
if (batchMessagesBuilder.length() == 0) return null;
if (batchMessagesBuilder.charAt(batchMessagesBuilder.length() - 1) == ',') {
// remove trailing ','
batchMessagesBuilder.deleteCharAt(batchMessagesBuilder.length() - 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,18 +467,21 @@ void alias(@NonNull RudderMessage message) {
* @param newId New userId for the user
*/
public void alias(String newId) {
alias(newId, null);
alias(newId, null, null);
}

public void alias(@NonNull String newId, @Nullable RudderOption option) {
alias(newId, null, option);
}

/**
* Alias call
*
* <b>Segment compatible API</b>
*
* @param newId New userId for the user
* @param previousId Previous userId for the user
* @param option RudderOptions for this event
*/
public void alias(@NonNull String newId, @Nullable RudderOption option) {
public void alias(@NonNull String newId, @Nullable String previousId, @Nullable RudderOption option) {
RudderContext context = getRudderContext();
Map<String, Object> traits = null;
if (context != null) {
Expand All @@ -488,12 +491,16 @@ public void alias(@NonNull String newId, @Nullable RudderOption option) {
return;
String prevUserId = null;

if (traits.containsKey("userId")) {
prevUserId = (String) traits.get("userId");
} else if (traits.containsKey("id")) {
prevUserId = (String) traits.get("id");
if (previousId != null) {
prevUserId = previousId;
} else {
prevUserId = RudderContext.getAnonymousId();
if (traits.containsKey("userId")) {
prevUserId = (String) traits.get("userId");
} else if (traits.containsKey("id")) {
prevUserId = (String) traits.get("id");
} else {
prevUserId = RudderContext.getAnonymousId();
}
}

traits.put("userId", newId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,38 +44,39 @@ public void run() {
final ArrayList<String> messages = new ArrayList<>();
final ExponentialBackOff exponentialBackOff = new ExponentialBackOff(5 * 60); // 5 minutes
while (true) {
// clear lists for reuse
messageIds.clear();
messages.clear();
result = null;
maintainDBThreshold();
long sleepCount = Utils.getSleepDurationInSecond(upTimeInMillis, Utils.getUpTimeInMillis());
RudderLogger.logDebug("CloudModeManager: cloudModeProcessor: Fetching events to flush to server");
synchronized (MessageUploadLock.UPLOAD_LOCK) {
dbManager.fetchCloudModeEventsFromDB(messageIds, messages, config.getFlushQueueSize());
if (messages.size() >= config.getFlushQueueSize() || (!messages.isEmpty() && sleepCount >= config.getSleepTimeOut())) {
// form payload JSON form the list of messages
String payload = FlushUtils.getPayloadFromMessages(messageIds, messages);
RudderLogger.logDebug(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: payload: %s", payload));
RudderLogger.logInfo(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: %d", messageIds.size()));
if (payload != null) {
result = networkManager.sendNetworkRequest(payload, addEndPoint(dataResidencyManager.getDataPlaneUrl(), BATCH_ENDPOINT), RequestMethod.POST, true);
RudderLogger.logInfo(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: ServerResponse: %d", result.statusCode));
if (result.status == NetworkResponses.SUCCESS) {
ReportManager.incrementCloudModeUploadSuccessCounter(messageIds.size());
dbManager.markCloudModeDone(messageIds);
dbManager.runGcForEvents();
exponentialBackOff.resetBackOff();
upTimeInMillis = Utils.getUpTimeInMillis();
sleepCount = Utils.getSleepDurationInSecond(upTimeInMillis, Utils.getUpTimeInMillis());
try {
// clear lists for reuse
messageIds.clear();
messages.clear();
result = null;
maintainDBThreshold();
long sleepCount = Utils.getSleepDurationInSecond(upTimeInMillis, Utils.getUpTimeInMillis());
RudderLogger.logDebug("CloudModeManager: cloudModeProcessor: Fetching events to flush to server");
synchronized (MessageUploadLock.UPLOAD_LOCK) {
dbManager.fetchCloudModeEventsFromDB(messageIds, messages, config.getFlushQueueSize());
if (messages.size() >= config.getFlushQueueSize() || (!messages.isEmpty() && sleepCount >= config.getSleepTimeOut())) {
// form payload JSON form the list of messages
String payload = FlushUtils.getPayloadFromMessages(messageIds, messages);
RudderLogger.logDebug(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: payload: %s", payload));
RudderLogger.logInfo(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: %d", messageIds.size()));
if (payload != null) {
result = networkManager.sendNetworkRequest(payload, addEndPoint(dataResidencyManager.getDataPlaneUrl(), BATCH_ENDPOINT), RequestMethod.POST, true);
RudderLogger.logInfo(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: ServerResponse: %d", result.statusCode));
if (result.status == NetworkResponses.SUCCESS) {
ReportManager.incrementCloudModeUploadSuccessCounter(messageIds.size());
cleanUpEvents(messageIds);
exponentialBackOff.resetBackOff();
upTimeInMillis = Utils.getUpTimeInMillis();
sleepCount = Utils.getSleepDurationInSecond(upTimeInMillis, Utils.getUpTimeInMillis());
} else {
incrementCloudModeUploadRetryCounter(1);
}
} else {
incrementCloudModeUploadRetryCounter(1);
cleanUpEvents(messageIds);
}
}
}
}
RudderLogger.logDebug(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: SleepCount: %d", sleepCount));
try {
RudderLogger.logDebug(String.format(Locale.US, "CloudModeManager: cloudModeProcessor: SleepCount: %d", sleepCount));
if (result == null) {
RudderLogger.logDebug("CloudModeManager: cloudModeProcessor: Sleeping for next: " + config.getEventDispatchSleepInterval() + "ms");
Thread.sleep(config.getEventDispatchSleepInterval());
Expand Down Expand Up @@ -106,12 +107,21 @@ public void run() {
ReportManager.reportError(ex);
RudderLogger.logError(String.format("CloudModeManager: cloudModeProcessor: Exception while trying to send events to Data plane URL %s due to %s", config.getDataPlaneUrl(), ex.getLocalizedMessage()));
Thread.currentThread().interrupt();
} catch (OutOfMemoryError e) {
RudderLogger.logError(String.format("CloudModeManager: cloudModeProcessor: Out of memory error: %s occurred while trying to send events to Data plane URL: %s", e.getLocalizedMessage(), config.getDataPlaneUrl()));
// sleeping the thread for 1s to avoid continuous loop after OOM.
Utils.sleep(1000);
}
}
}
}.start();
}

private void cleanUpEvents(List<Integer> messageIds) {
dbManager.markCloudModeDone(messageIds);
dbManager.runGcForEvents();
}

private void deleteEventsWithoutAnonymousId(ArrayList<String> messages, ArrayList<Integer> messageIds) {
List<Integer> eventsToDelete = new ArrayList<>();
for (int i = 0; i < messages.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ private void replayMessageQueue() {
RudderMessage message = RudderGson.deserialize(messages.get(i), RudderMessage.class);
if (message != null) {
processMessage(message, messageIds.get(i), true);
} else {
markDeviceModeTransformationDone(messageIds.get(i));
}
} catch (Exception e) {
ReportManager.reportError(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,13 @@ public static String getTimeInReadableFormat(long timeInMillis) {

return timeInReadableFormat.toString();
}

public static void sleep(long timeInMillis) {
try {
Thread.sleep(timeInMillis);
} catch (InterruptedException ex) {
ReportManager.reportError(ex);
Thread.currentThread().interrupt();
}
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ android.enableJetifier=true
android.enableR8.fullMode=true
kotlin.code.style=official
GROUP=com.rudderstack.android.sdk
VERSION_CODE=33
VERSION_NAME=1.25.1
VERSION_CODE=34
VERSION_NAME=1.26.0
POM_NAME=Rudderstack SDK for android
POM_DESCRIPTION=Rudderstack SDK for android
POM_ARTIFACT_ID=core
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.25.1",
"version": "1.26.0",
"dependencies": {
"properties-reader": "^2.2.0"
}
Expand Down

0 comments on commit 8085d05

Please sign in to comment.