From ca9682edd8679cc6f66c0a13281394ec777ac2eb Mon Sep 17 00:00:00 2001 From: Vishal Gupta Date: Fri, 6 Dec 2024 13:13:26 +0530 Subject: [PATCH 1/2] refactor: catch OutOfMemoryError in RudderCloudModeManager --- .../sdk/core/RudderCloudModeManager.java | 62 ++++++++++--------- .../android/sdk/core/util/Utils.java | 9 +++ 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java b/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java index 02503735..97cd73b1 100644 --- a/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java +++ b/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java @@ -44,39 +44,39 @@ public void run() { final ArrayList 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()); - cleanUpEvents(messageIds); - 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); } - } else { - 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()); @@ -107,6 +107,10 @@ 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("CloudModeManager: cloudModeProcessor: Out of memory error occurred while trying to send events to Data plane URL " + config.getDataPlaneUrl()); + // sleeping the thread for 1s to avoid continuous loop after OOM. + Utils.sleep(1000); } } } diff --git a/core/src/main/java/com/rudderstack/android/sdk/core/util/Utils.java b/core/src/main/java/com/rudderstack/android/sdk/core/util/Utils.java index 124be401..a4e9a165 100644 --- a/core/src/main/java/com/rudderstack/android/sdk/core/util/Utils.java +++ b/core/src/main/java/com/rudderstack/android/sdk/core/util/Utils.java @@ -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(); + } + } } From b8f9b1bf7c46bad5939c0ba41d10ce794b801863 Mon Sep 17 00:00:00 2001 From: Vishal Gupta Date: Fri, 6 Dec 2024 15:59:31 +0530 Subject: [PATCH 2/2] refactor: change log message for out of memory error --- .../rudderstack/android/sdk/core/RudderCloudModeManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java b/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java index 97cd73b1..3378d606 100644 --- a/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java +++ b/core/src/main/java/com/rudderstack/android/sdk/core/RudderCloudModeManager.java @@ -108,7 +108,7 @@ public void run() { 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("CloudModeManager: cloudModeProcessor: Out of memory error occurred while trying to send events to Data plane URL " + config.getDataPlaneUrl()); + 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); }