Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: memory issue crash happening on CloudModeProcessor #539

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
86 changes: 46 additions & 40 deletions Sources/Classes/RSCloudModeManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,50 +38,56 @@ - (void) startCloudModeProcessor {
RSCloudModeManager *strongSelf = weakSelf;
[RSLogger logDebug:@"RSCloudModeManager: CloudModeProcessor: Starting the Cloud Mode Processor"];
int sleepCount = 0;

while (YES) {
[strongSelf->lock lock];
RSNetworkResponse* response = nil;
[strongSelf->dbPersistentManager clearOldEventsWithThreshold: strongSelf->config.dbCountThreshold];
[RSLogger logDebug:@"RSCloudModeManager: CloudModeProcessor: Fetching events to flush to server"];
RSDBMessage* dbMessage = [strongSelf->dbPersistentManager fetchEventsFromDB:(strongSelf->config.flushQueueSize) ForMode:CLOUDMODE];
if ((dbMessage.messages.count >= strongSelf->config.flushQueueSize) || (dbMessage.messages.count > 0 && (sleepCount >= strongSelf->config.sleepTimeout))) {
NSString* payload = [RSCloudModeManager getPayloadFromMessages:dbMessage];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Payload: %@", payload]];
[RSLogger logInfo:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: EventCount: %lu", (unsigned long)dbMessage.messageIds.count]];
[RSMetricsReporter report:SDKMETRICS_CM_EVENT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_MESSAGES} andValue:(float)dbMessage.messages.count];
if (payload != nil) {
response = [strongSelf->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST];
if (response.state == NETWORK_SUCCESS) {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Updating status as CLOUDMODEPROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_SUCCESS forMetricType:COUNT withProperties:nil andValue:(float)dbMessage.messages.count];
[strongSelf->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE];
[strongSelf->dbPersistentManager clearProcessedEventsFromDB];
sleepCount = 0;
[self->backOff reset];
@try {
[strongSelf->lock lock];
RSNetworkResponse* response = nil;
[strongSelf->dbPersistentManager clearOldEventsWithThreshold: strongSelf->config.dbCountThreshold];
[RSLogger logDebug:@"RSCloudModeManager: CloudModeProcessor: Fetching events to flush to server"];
RSDBMessage* dbMessage = [strongSelf->dbPersistentManager fetchEventsFromDB:(strongSelf->config.flushQueueSize) ForMode:CLOUDMODE];
if ((dbMessage.messages.count >= strongSelf->config.flushQueueSize) || (dbMessage.messages.count > 0 && (sleepCount >= strongSelf->config.sleepTimeout))) {
NSString* payload = [RSCloudModeManager getPayloadFromMessages:dbMessage];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Payload: %@", payload]];
[RSLogger logInfo:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: EventCount: %lu", (unsigned long)dbMessage.messageIds.count]];
[RSMetricsReporter report:SDKMETRICS_CM_EVENT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_MESSAGES} andValue:(float)dbMessage.messages.count];
if (payload != nil) {
response = [strongSelf->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST];
if (response.state == NETWORK_SUCCESS) {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Updating status as CLOUDMODEPROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_SUCCESS forMetricType:COUNT withProperties:nil andValue:(float)dbMessage.messages.count];
[strongSelf->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE];
[strongSelf->dbPersistentManager clearProcessedEventsFromDB];
sleepCount = 0;
[self->backOff reset];
}
}
}
[strongSelf->lock unlock];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: cloudModeSleepCount: %d", sleepCount]];
sleepCount += 1;

if(response == nil) {
sleep(1);
} else if (response.state == WRONG_WRITE_KEY) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Wrong WriteKey. Aborting the Cloud Mode Processor"];
break;
} else if (response.state == INVALID_URL) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Invalid Data Plane URL. Aborting the Cloud Mode Processor"];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_ABORT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_DATA_PLANE_URL_INVALID} andValue:1];
break;
} else if (response.state == NETWORK_ERROR) {
int delay = [self->backOff nextDelay];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: %@", [RSUtils secondsToString:delay]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_RETRY forMetricType:COUNT withProperties:nil andValue:1];
sleep(delay);
} else { // To handle the status code RESOURCE_NOT_FOUND(404) & BAD_REQUEST(400)
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: 1s"]];
sleep(1);
}
}
[strongSelf->lock unlock];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: cloudModeSleepCount: %d", sleepCount]];
sleepCount += 1;

if(response == nil) {
sleep(1);
} else if (response.state == WRONG_WRITE_KEY) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Wrong WriteKey. Aborting the Cloud Mode Processor"];
break;
} else if (response.state == INVALID_URL) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Invalid Data Plane URL. Aborting the Cloud Mode Processor"];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_ABORT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_DATA_PLANE_URL_INVALID} andValue:1];
break;
} else if (response.state == NETWORK_ERROR) {
int delay = [self->backOff nextDelay];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: %@", [RSUtils secondsToString:delay]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_RETRY forMetricType:COUNT withProperties:nil andValue:1];
sleep(delay);
} else { // To handle the status code RESOURCE_NOT_FOUND(404) & BAD_REQUEST(400)
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: 1s"]];
@catch (NSException *exception) {
[strongSelf->lock unlock];
[RSLogger logError:[NSString stringWithFormat:@"RSCloudModeManager: CloudModeProcessor: Failed to flush current batch, reason: %@", exception.reason]];
sleep(1);
}
}
Expand Down
37 changes: 23 additions & 14 deletions Sources/Classes/RSDBPersistentManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -491,30 +491,39 @@ -(RSDBMessage*) fetchAllEventsFromDBForMode:(MODES) mode {

- (RSDBMessage *) getEventsFromDB :(NSString*) querySQLString {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDBPersistentManager: getEventsFromDB: fetchEventSql: %@", querySQLString]];

const char* querySQL = [querySQLString UTF8String];
NSMutableArray<NSString *> *messageIds = [[NSMutableArray alloc] init];
NSMutableArray<NSString *> *messages = [[NSMutableArray alloc] init];
NSMutableArray<NSNumber *>* statusList = [[NSMutableArray alloc] init];
NSMutableArray<NSNumber *>* dmProcessedList = [[NSMutableArray alloc] init];
NSMutableArray<NSString *> *messageIds = [NSMutableArray array];
NSMutableArray<NSString *> *messages = [NSMutableArray array];
NSMutableArray<NSNumber *> *statusList = [NSMutableArray array];
NSMutableArray<NSNumber *> *dmProcessedList = [NSMutableArray array];

@synchronized (self) {
void *queryStmt = nil;
sqlite3_stmt *queryStmt = nil;
if ([database prepare_v2:querySQL nBytes:-1 ppStmt:&queryStmt pzTail:NULL] == SQLITE_OK) {
[RSLogger logDebug:@"RSDBPersistentManager: getEventsFromDB: Successfully fetched events from DB"];
while ([database step:queryStmt] == SQLITE_ROW) {
int messageId = [database column_int:queryStmt i:0];
const unsigned char* queryResultCol1 = [database column_text:queryStmt i:1];
NSString *message = [[NSString alloc] initWithUTF8String:(char *)queryResultCol1];
int status = [database column_int:queryStmt i:3];
int dmProcessed = [database column_int:queryStmt i:4];
[messageIds addObject:[[NSString alloc] initWithFormat:@"%d", messageId]];
[messages addObject:message];
[statusList addObject:[NSNumber numberWithInt:status]];
[dmProcessedList addObject:[NSNumber numberWithInt:dmProcessed]];
@autoreleasepool {
int messageId = [database column_int:queryStmt i:0];
const unsigned char* queryResultCol1 = [database column_text:queryStmt i:1];
NSString *message = [[NSString alloc] initWithUTF8String:(char *)queryResultCol1];
int status = [database column_int:queryStmt i:3];
int dmProcessed = [database column_int:queryStmt i:4];

[messageIds addObject:[[NSString alloc] initWithFormat:@"%d", messageId]];
[messages addObject:message];
[statusList addObject:[NSNumber numberWithInt:status]];
[dmProcessedList addObject:[NSNumber numberWithInt:dmProcessed]];
}
}
} else {
[RSLogger logError:@"RSDBPersistentManager: getEventsFromDB: Failed to fetch events from DB"];
}

// Finalize the SQL statement to free resources
if (queryStmt != nil) {
[database finalize:queryStmt];
}
}

RSDBMessage *dbMessage = [[RSDBMessage alloc] init];
Expand Down
Loading