Skip to content

Commit

Permalink
fix: ensure batch array in the request payload is never empty
Browse files Browse the repository at this point in the history
  • Loading branch information
1abhishekpandey committed Sep 14, 2023
1 parent 360fb0d commit 3d2b853
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 21 deletions.
6 changes: 3 additions & 3 deletions Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PODS:
- MetricsReporter (1.0.0):
- RudderKit
- Rudder (1.18.0):
- Rudder (1.19.2):
- MetricsReporter (= 1.0.0)
- RudderKit (1.4.0)

Expand All @@ -21,9 +21,9 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
MetricsReporter: 97a54d0af909edc6804823a008b63bd568a42a35
Rudder: b69a0927438a1ac3df3fc78dd3bbbf5dc0f2a851
Rudder: 26a9b6756628cb953f3151d835104ac9f5635861
RudderKit: d9d6997696e1642b753d8bdf94e57af643a68f03

PODFILE CHECKSUM: b034e86bf17deec5b99fbeb0c76c2114b2eed1aa

COCOAPODS: 1.12.0
COCOAPODS: 1.11.3
2 changes: 2 additions & 0 deletions Sources/Classes/Headers/Public/RSUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString* _Nullable) getDeviceId;
+ (BOOL)isFileExists:(NSString *)fileName;
+ (BOOL)removeFile:(NSString *)fileName;
+ (BOOL) isDBMessageEmpty:(RSDBMessage*)dbMessage;
+ (BOOL) isEmptyString:(NSString *)value;

extern unsigned int MAX_EVENT_SIZE;
extern unsigned int MAX_BATCH_SIZE;
Expand Down
29 changes: 21 additions & 8 deletions Sources/Classes/RSCloudModeManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ - (void) startCloudModeProcessor {
[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];
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 getCSVString: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;
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 getCSVString: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;
}
}
}
[strongSelf->lock unlock];
Expand All @@ -78,6 +80,10 @@ - (void) startCloudModeProcessor {
}

+ (NSString*) getPayloadFromMessages: (RSDBMessage*)dbMessage{
if ([RSUtils isDBMessageEmpty:dbMessage]) {
[RSLogger logDebug:@"Payload construction aborted because the dbMessage is empty."];
return nil;
}
NSMutableArray<NSString *>* messages = dbMessage.messages;
NSMutableArray<NSString *>* messageIds = dbMessage.messageIds;
NSMutableArray<NSString *> *batchMessageIds = [[NSMutableArray alloc] init];
Expand All @@ -90,6 +96,7 @@ + (NSString*) getPayloadFromMessages: (RSDBMessage*)dbMessage{
[json appendFormat:@"\"sentAt\":\"%@\",", sentAt];
[json appendString:@"\"batch\":["];
unsigned int totalBatchSize = [RSUtils getUTF8Length:json] + 2; // we add 2 characters at the end
NSMutableString* batchMessage = [[NSMutableString alloc] init];
for (int index = 0; index < messages.count; index++) {
NSMutableString* message = [[NSMutableString alloc] initWithString:messages[index]];
long length = message.length;
Expand All @@ -103,9 +110,15 @@ + (NSString*) getPayloadFromMessages: (RSDBMessage*)dbMessage{
[RSMetricsReporter report:SDKMETRICS_EVENTS_DISCARDED forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_BATCH_SIZE_INVALID} andValue:1];
break;
}
[json appendString:message];
[batchMessage appendString:message];
[batchMessageIds addObject:messageIds[index]];
}
// When empty batch is sent to the server it trigger Invalid JSON error. Hence it is necessary to ensure that batch is not empty.
if ([RSUtils isEmptyString:batchMessage]) {
[RSLogger logDebug:@"Payload construction aborted because the batch message is empty."];
return nil;
}
[json appendString:batchMessage];
if([json characterAtIndex:[json length]-1] == ',') {
// remove trailing ','
[json deleteCharactersInRange:NSMakeRange([json length]-1, 1)];
Expand Down
22 changes: 12 additions & 10 deletions Sources/Classes/RSFlushManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,18 @@ - (void)flushSync {
batchDBMessage.messageIds = messageIds;
batchDBMessage.messages = messages;
NSString* payload = [RSCloudModeManager getPayloadFromMessages:batchDBMessage];
RSNetworkResponse* response = [self->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST];
if( response.state == NETWORK_SUCCESS){
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSFlushUtils: flushSync: Successfully sent batch %d/%d", i, numberOfBatches]];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSFlushUtils: flushSync: Clearing events of batch %d from DB", i]];
[self->dbPersistentManager updateEventsWithIds:batchDBMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE];
[self->dbPersistentManager clearProcessedEventsFromDB];
[_dbMessage.messages removeObjectsInArray:messages];
[_dbMessage.messageIds removeObjectsInArray:messageIds];
lastBatchFailed = NO;
break;
if (payload != nil) {
RSNetworkResponse* response = [self->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST];
if( response.state == NETWORK_SUCCESS){
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSFlushUtils: flushSync: Successfully sent batch %d/%d", i, numberOfBatches]];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSFlushUtils: flushSync: Clearing events of batch %d from DB", i]];
[self->dbPersistentManager updateEventsWithIds:batchDBMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE];
[self->dbPersistentManager clearProcessedEventsFromDB];
[_dbMessage.messages removeObjectsInArray:messages];
[_dbMessage.messageIds removeObjectsInArray:messageIds];
lastBatchFailed = NO;
break;
}
}
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSFlushUtils: flushSync: Failed to send %d/%d, retrying again, %d retries left", i, numberOfBatches, retries]];
}
Expand Down
8 changes: 8 additions & 0 deletions Sources/Classes/RSUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ + (BOOL) isApplicationUpdated {
return (previousVersion && ![previousVersion isEqualToString:currentVersion]);
}

+ (BOOL) isDBMessageEmpty:(RSDBMessage*)dbMessage {
return ([dbMessage.messages count] == 0 || [dbMessage.messageIds count] == 0);
}

+ (BOOL) isEmptyString:(NSString*)value {
return (value == nil || value.length == 0);
}

unsigned int MAX_EVENT_SIZE = 32 * 1024; // 32 KB
unsigned int MAX_BATCH_SIZE = 500 * 1024; // 500 KB

Expand Down

0 comments on commit 3d2b853

Please sign in to comment.