From c3ed790b50f8a9f8812357c25e0baa32884e759a Mon Sep 17 00:00:00 2001 From: Abhishek Pandey <64667840+1abhishekpandey@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:05:26 +0530 Subject: [PATCH 1/4] chore: update pr_reviewer and assignees to @rudderlabs/sdk-ios (#518) --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/workflows/draft-new-release-v2.yml | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index e0eecd98..f3391c4f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -3,7 +3,7 @@ name: Bug report about: Create a report to help us improve title: "BUG : " labels: bug, open source -assignees: pallabmaiti +assignees: "@rudderlabs/sdk-ios" --- **Describe the bug** diff --git a/.github/workflows/draft-new-release-v2.yml b/.github/workflows/draft-new-release-v2.yml index a1ca6853..03fa7c53 100644 --- a/.github/workflows/draft-new-release-v2.yml +++ b/.github/workflows/draft-new-release-v2.yml @@ -1,7 +1,6 @@ name: Draft new release(v2) -on: - workflow_dispatch +on: workflow_dispatch jobs: draft-new-release: @@ -18,7 +17,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 16 - + # In order to make a commit, we need to initialize a user. # You may choose to write something less generic here if you want, it doesn't matter functionality wise. - name: Initialize mandatory git config @@ -39,7 +38,7 @@ jobs: git fetch --tags origin git merge origin/master-v2 current_version=$(jq -r .version package.json) - + npx standard-version --skip.commit --skip.tag --skip.changelog new_version=$(jq -r .version package.json) git reset --hard @@ -53,7 +52,7 @@ jobs: echo "New release branch name is $branch_name" git checkout -b "$branch_name" git push --set-upstream origin "$branch_name" - + echo "source_branch_name=$source_branch_name" >> $GITHUB_OUTPUT echo "branch_name=$branch_name" >> $GITHUB_OUTPUT echo "new_version=$new_version" >> $GITHUB_OUTPUT @@ -84,8 +83,8 @@ jobs: uses: repo-sync/pull-request@v2 with: source_branch: ${{ steps.create-release.outputs.branch_name }} - destination_branch: 'master-v2' + destination_branch: "master-v2" github_token: ${{ secrets.PAT }} pr_title: "chore(release): pulling ${{ steps.create-release.outputs.branch_name }} into master" pr_body: ":crown: *An automated PR*\n\n${{ steps.finish-release.outputs.commit_summary }}" - pr_reviewer: 'pallabmaiti' + pr_reviewer: "@rudderlabs/sdk-ios" From 8bf2900710f06e6c9f268bd6fa4e405bcaa417ed Mon Sep 17 00:00:00 2001 From: Satheesh Kannan <satheeshkannan.ios@gmail.com> Date: Mon, 5 Aug 2024 13:13:07 +0530 Subject: [PATCH 2/4] feat: implement exponential retry mechanism for handling network errors (#525) * chore: update podfile.lock * feat: implement exponential retry mechanism for handling network errors * feat: implement exponential retry mechanism for handling network errors * chore: address the sonarcloud issue This fix fill eliminate the possibility of returning null pointer/ null reference * chore: address the sonarcloud issue This fix will eliminate the implicit conversion loses integer precision issue * chore: address the sonarcloud issue * chore: address the sonarcloud issue This fix fill eliminate the possibility of returning null pointer/ null reference * chore: address the sonarcloud issue This fix fill eliminate the possibility of returning null pointer/ null reference * chore: address the sonarcloud issue * chore: code optimization * chore: address the PR comments --- Podfile.lock | 4 +- Rudder.xcodeproj/project.pbxproj | 16 +++++ Sources/Classes/Headers/Public/RSConstants.h | 3 + .../Headers/Public/RSExponentialBackOff.h | 40 ++++++++++++ Sources/Classes/Headers/Public/RSUtils.h | 1 + Sources/Classes/RSCloudModeManager.m | 23 ++++--- Sources/Classes/RSConstants.m | 3 + Sources/Classes/RSExponentialBackOff.m | 62 +++++++++++++++++++ Sources/Classes/RSUtils.m | 10 ++- 9 files changed, 151 insertions(+), 11 deletions(-) create mode 100644 Sources/Classes/Headers/Public/RSExponentialBackOff.h create mode 100644 Sources/Classes/RSExponentialBackOff.m diff --git a/Podfile.lock b/Podfile.lock index da14c407..71fe3795 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -3,7 +3,7 @@ PODS: - RSCrashReporter (= 1.0.1) - RudderKit (= 1.4.0) - RSCrashReporter (1.0.1) - - Rudder (1.26.3): + - Rudder (1.27.0): - MetricsReporter (= 1.2.1) - RudderKit (1.4.0) - SQLCipher (4.5.4): @@ -33,7 +33,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: MetricsReporter: 99596ee5003c69949ed2f50acc34aee83c42f843 RSCrashReporter: 6b8376ac729b0289ebe0908553e5f56d8171f313 - Rudder: 23456f79749849870e18c45bd250d6e2229a7147 + Rudder: 3cfcd9e6c5359cd6d49f411101ed9b894e3b64bd RudderKit: d9d6997696e1642b753d8bdf94e57af643a68f03 SQLCipher: 905b145f65f349f26da9e60a19901ad24adcd381 diff --git a/Rudder.xcodeproj/project.pbxproj b/Rudder.xcodeproj/project.pbxproj index b6714eee..50068218 100644 --- a/Rudder.xcodeproj/project.pbxproj +++ b/Rudder.xcodeproj/project.pbxproj @@ -10,6 +10,12 @@ 06CABC332630C6B00097BEFF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06CABC322630C6B00097BEFF /* Foundation.framework */; }; 06CABC352630C6D30097BEFF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06CABC2E2630C6660097BEFF /* UIKit.framework */; }; 2FA4A3E2DF0696E8D68B640A /* Pods_Rudder_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F631D98DB26309EFE5E0A24 /* Pods_Rudder_watchOS.framework */; }; + 535778972C4F8E0000E8CE9B /* RSExponentialBackOff.m in Sources */ = {isa = PBXBuildFile; fileRef = 535778962C4F8E0000E8CE9B /* RSExponentialBackOff.m */; }; + 535778982C4F8E0000E8CE9B /* RSExponentialBackOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 535778952C4F8E0000E8CE9B /* RSExponentialBackOff.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 535778992C4F8E0000E8CE9B /* RSExponentialBackOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 535778952C4F8E0000E8CE9B /* RSExponentialBackOff.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5357789A2C4F8E0000E8CE9B /* RSExponentialBackOff.m in Sources */ = {isa = PBXBuildFile; fileRef = 535778962C4F8E0000E8CE9B /* RSExponentialBackOff.m */; }; + 5357789B2C4F8E0000E8CE9B /* RSExponentialBackOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 535778952C4F8E0000E8CE9B /* RSExponentialBackOff.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5357789C2C4F8E0000E8CE9B /* RSExponentialBackOff.m in Sources */ = {isa = PBXBuildFile; fileRef = 535778962C4F8E0000E8CE9B /* RSExponentialBackOff.m */; }; 5C11F10C96D80DF73DBED732 /* Pods_Rudder_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 447958A767B9B6F9BB3AC36A /* Pods_Rudder_iOS.framework */; }; 60DF93A1FA405B16F4D273AB /* Pods_RudderTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F00C6B89DB926A1271D979A /* Pods_RudderTests_iOS.framework */; }; 7275AF62B3887AFD09CF49CF /* Pods_RudderTests_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E0F163A9A54245F87BB53E /* Pods_RudderTests_watchOS.framework */; }; @@ -762,6 +768,8 @@ 3C44A9E8F4B06BD7D1881CC6 /* Pods-RudderTests-watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-watchOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS.debug.xcconfig"; sourceTree = "<group>"; }; 3F00C6B89DB926A1271D979A /* Pods_RudderTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 447958A767B9B6F9BB3AC36A /* Pods_Rudder_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 535778952C4F8E0000E8CE9B /* RSExponentialBackOff.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RSExponentialBackOff.h; sourceTree = "<group>"; }; + 535778962C4F8E0000E8CE9B /* RSExponentialBackOff.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSExponentialBackOff.m; sourceTree = "<group>"; }; 767A0EEE9A76F43CF631573B /* Pods-Rudder-watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-watchOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-watchOS/Pods-Rudder-watchOS.debug.xcconfig"; sourceTree = "<group>"; }; 83C9949585CD3C274CCE6A27 /* Pods-Rudder-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-iOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-iOS/Pods-Rudder-iOS.release.xcconfig"; sourceTree = "<group>"; }; 9B4BB7D91351507AD413A9B4 /* Pods-Rudder-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-tvOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-tvOS/Pods-Rudder-tvOS.release.xcconfig"; sourceTree = "<group>"; }; @@ -1198,6 +1206,7 @@ F6B4B53529C8237D00344864 /* RSBackGroundModeManager.m */, ED7DFD8F298C091800ED5A8E /* RSClient.m */, F6B4B53929C8237D00344864 /* RSCloudModeManager.m */, + 535778962C4F8E0000E8CE9B /* RSExponentialBackOff.m */, ED7DFD89298C091800ED5A8E /* RSConfig.m */, ED7DFDCE298C091800ED5A8E /* RSConfigBuilder.m */, ED8DB01D298E206900907EC4 /* RSConsentFilterHandler.m */, @@ -1261,6 +1270,7 @@ F6B4B51E29C8236100344864 /* RSBackGroundModeManager.h */, ED7DFDB9298C091800ED5A8E /* RSClient.h */, F6B4B51D29C8236100344864 /* RSCloudModeManager.h */, + 535778952C4F8E0000E8CE9B /* RSExponentialBackOff.h */, ED7DFDB4298C091800ED5A8E /* RSConfig.h */, ED7DFDA5298C091800ED5A8E /* RSConfigBuilder.h */, ED7DFDAD298C091800ED5A8E /* RSConsentFilter.h */, @@ -1555,6 +1565,7 @@ ED7DFE70298C091800ED5A8E /* RSServerDestination.h in Headers */, ED7DFED9298C091800ED5A8E /* RSProductClickedEvent.h in Headers */, ED7DFE82298C091800ED5A8E /* RSECommerceCartBuilder.h in Headers */, + 535778982C4F8E0000E8CE9B /* RSExponentialBackOff.h in Headers */, ED99908E2A6926E000031B06 /* RSMetricsReporter.h in Headers */, ED7DFE58298C091800ED5A8E /* RSPreferenceManager.h in Headers */, ED7DFEB7298C091800ED5A8E /* RSPaymentInfoEnteredEvent.h in Headers */, @@ -1673,6 +1684,7 @@ ED998E682A69003600031B06 /* RSECommerceCartBuilder.h in Headers */, ED99908F2A6926E000031B06 /* RSMetricsReporter.h in Headers */, ED998E692A69003600031B06 /* RSPreferenceManager.h in Headers */, + 535778992C4F8E0000E8CE9B /* RSExponentialBackOff.h in Headers */, ED998E6A2A69003600031B06 /* RSPaymentInfoEnteredEvent.h in Headers */, ED998E6B2A69003600031B06 /* RSCartSharedEvent.h in Headers */, ED998E6C2A69003600031B06 /* RSECommerceEvents.h in Headers */, @@ -1791,6 +1803,7 @@ ED998F382A69024E00031B06 /* RSECommerceCartBuilder.h in Headers */, ED9990902A6926E000031B06 /* RSMetricsReporter.h in Headers */, ED998F392A69024E00031B06 /* RSPreferenceManager.h in Headers */, + 5357789B2C4F8E0000E8CE9B /* RSExponentialBackOff.h in Headers */, ED998F3A2A69024E00031B06 /* RSPaymentInfoEnteredEvent.h in Headers */, ED998F3B2A69024E00031B06 /* RSCartSharedEvent.h in Headers */, ED998F3C2A69024E00031B06 /* RSECommerceEvents.h in Headers */, @@ -2378,6 +2391,7 @@ ED7DFE8F298C091800ED5A8E /* RSECommerceSortBuilder.m in Sources */, ED7DFE3F298C091800ED5A8E /* RSServerDestination.m in Sources */, ED7DFEB6298C091800ED5A8E /* RSOrderRefundedEvent.m in Sources */, + 535778972C4F8E0000E8CE9B /* RSExponentialBackOff.m in Sources */, F64116022B68EC4B0015CB42 /* RSDefaultsPersistence.m in Sources */, ED7DFEC2298C091800ED5A8E /* RSCouponEnteredEvent.m in Sources */, ED7DFE3E298C091800ED5A8E /* RSApp.m in Sources */, @@ -2488,6 +2502,7 @@ ED998EEF2A69003600031B06 /* WKInterfaceController+RSScreen.m in Sources */, ED998EF02A69003600031B06 /* RSECommerceSortBuilder.m in Sources */, ED998EF12A69003600031B06 /* RSServerDestination.m in Sources */, + 5357789A2C4F8E0000E8CE9B /* RSExponentialBackOff.m in Sources */, F64116032B68EC4B0015CB42 /* RSDefaultsPersistence.m in Sources */, ED998EF22A69003600031B06 /* RSOrderRefundedEvent.m in Sources */, ED998EF32A69003600031B06 /* RSCouponEnteredEvent.m in Sources */, @@ -2598,6 +2613,7 @@ ED998FBF2A69024E00031B06 /* WKInterfaceController+RSScreen.m in Sources */, ED998FC02A69024E00031B06 /* RSECommerceSortBuilder.m in Sources */, ED998FC12A69024E00031B06 /* RSServerDestination.m in Sources */, + 5357789C2C4F8E0000E8CE9B /* RSExponentialBackOff.m in Sources */, F64116042B68EC4B0015CB42 /* RSDefaultsPersistence.m in Sources */, ED998FC22A69024E00031B06 /* RSOrderRefundedEvent.m in Sources */, ED998FC32A69024E00031B06 /* RSCouponEnteredEvent.m in Sources */, diff --git a/Sources/Classes/Headers/Public/RSConstants.h b/Sources/Classes/Headers/Public/RSConstants.h index 614d87c0..c290ad45 100644 --- a/Sources/Classes/Headers/Public/RSConstants.h +++ b/Sources/Classes/Headers/Public/RSConstants.h @@ -64,6 +64,9 @@ extern int const RSATTRestricted; extern int const RSATTDenied; extern int const RSATTAuthorize; +extern int const RSExponentialBackOff_InitialDelay; +extern int const RSExponentialBackOff_MinimumDelay; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Classes/Headers/Public/RSExponentialBackOff.h b/Sources/Classes/Headers/Public/RSExponentialBackOff.h new file mode 100644 index 00000000..f34daf73 --- /dev/null +++ b/Sources/Classes/Headers/Public/RSExponentialBackOff.h @@ -0,0 +1,40 @@ +// +// RSExponentialBackOff.h +// Rudder +// +// Created by Satheesh Kannan on 23/07/24. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN +/*! + @brief This class implements an exponential backoff strategy with jitter for handling retries. + + @discussion It allows for configurable maximum delay and includes methods to calculate the next delay with jitter and reset the backoff attempts. When the calculated delay reaches or exceeds the maximum delay limit, the backoff resets and starts again from beginning. + */ +@interface RSExponentialBackOff : NSObject + +/** + * Init function that accepts the maximum delay value in seconds. + * + * @param seconds Value for maximum delay property + * @return A new instance for this class + */ +- (instancetype)initWithMaximumDelay:(int)seconds; + +/** + * Function will calculate the next delay value in seconds + * + * @return Next delay value in seconds + */ +- (int)nextDelay; + +/** + * Function will resets the attempts. + */ +- (void)reset; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Classes/Headers/Public/RSUtils.h b/Sources/Classes/Headers/Public/RSUtils.h index d2ef1c73..174a3f47 100644 --- a/Sources/Classes/Headers/Public/RSUtils.h +++ b/Sources/Classes/Headers/Public/RSUtils.h @@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL) isValidIDFA:(NSString*)idfa; + (BOOL) isSpecialFloatingNumber:(NSNumber *)number; +(NSArray*) extractParamFromURL: (NSURL*) deepLinkURL; ++ (NSString *)secondsToString:(int) delay; extern unsigned int MAX_EVENT_SIZE; extern unsigned int MAX_BATCH_SIZE; diff --git a/Sources/Classes/RSCloudModeManager.m b/Sources/Classes/RSCloudModeManager.m index 0072f065..7d50929f 100644 --- a/Sources/Classes/RSCloudModeManager.m +++ b/Sources/Classes/RSCloudModeManager.m @@ -12,9 +12,12 @@ #import "RSNetworkManager.h" #import "RSNetworkResponse.h" #import "RSMetricsReporter.h" +#import "RSExponentialBackOff.h" +#import "RSConstants.h" -@implementation RSCloudModeManager - +@implementation RSCloudModeManager { + RSExponentialBackOff *backOff; +} - (instancetype)initWithConfig:(RSConfig *) config andDBPersistentManager:(RSDBPersistentManager *) dbPersistentManager andNetworkManager:(RSNetworkManager *) networkManager andLock: (NSLock *) lock { self = [super init]; @@ -24,6 +27,7 @@ - (instancetype)initWithConfig:(RSConfig *) config andDBPersistentManager:(RSDBP self->config = config; self->lock = lock; self->cloud_mode_processor_queue = dispatch_queue_create("com.rudder.RSCloudModeManager", NULL); + self->backOff = [[RSExponentialBackOff alloc] initWithMaximumDelay:RSExponentialBackOff_MinimumDelay]; } return self; } @@ -54,14 +58,16 @@ - (void) startCloudModeProcessor { [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) { - usleep(1000000); + sleep(1); } else if (response.state == WRONG_WRITE_KEY) { [RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Wrong WriteKey. Aborting the Cloud Mode Processor"]; break; @@ -69,11 +75,14 @@ - (void) startCloudModeProcessor { [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) { - [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: %d s", abs(sleepCount - strongSelf->config.sleepTimeout)]]; + } 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]; - usleep(abs(sleepCount - strongSelf->config.sleepTimeout) * 1000000); + 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); } } }); diff --git a/Sources/Classes/RSConstants.m b/Sources/Classes/RSConstants.m index 865b7338..fabdde0e 100644 --- a/Sources/Classes/RSConstants.m +++ b/Sources/Classes/RSConstants.m @@ -39,4 +39,7 @@ @implementation RSConstants int const RSATTDenied = 2; int const RSATTAuthorize = 3; +int const RSExponentialBackOff_MinimumDelay = 5 * 60; //in seconds.. +int const RSExponentialBackOff_InitialDelay = 3; //in seconds.. + @end diff --git a/Sources/Classes/RSExponentialBackOff.m b/Sources/Classes/RSExponentialBackOff.m new file mode 100644 index 00000000..3ab0615d --- /dev/null +++ b/Sources/Classes/RSExponentialBackOff.m @@ -0,0 +1,62 @@ +// +// RSExponentialBackOff.m +// Rudder +// +// Created by Satheesh Kannan on 23/07/24. +// + +#import "RSExponentialBackOff.h" +#import "RSConstants.h" +#pragma mark - RSExponentialBackOff + +@interface RSExponentialBackOff() +@property (nonatomic, assign) int attempt; +@property (nonatomic, assign) int maximumDelay; +@property (nonatomic, assign) int initialDelay; +@end + +@implementation RSExponentialBackOff + +/** + * Init function that accepts the maximum delay value in seconds. + */ +- (instancetype)initWithMaximumDelay:(int) seconds { + self = [super init]; + if (self) { + _maximumDelay = seconds; + _attempt = 0; + _initialDelay = RSExponentialBackOff_InitialDelay; + } + + return self; +} + +/** + * Function will calculate the next delay value in seconds + */ +- (int)nextDelay { + int delay = _initialDelay * (int)pow(2, _attempt); + _attempt = _attempt + 1; + + int jitter = arc4random_uniform((delay + 1)); + + int exponentialDelay = delay + jitter; + exponentialDelay = MIN(exponentialDelay, _maximumDelay); + + if (exponentialDelay == _maximumDelay) { + [self reset]; + } + + return exponentialDelay; +} + +/** + * Function will resets the attempts. + */ +- (void)reset { + _attempt = 0; +} + +@end + + diff --git a/Sources/Classes/RSUtils.m b/Sources/Classes/RSUtils.m index 927fb1c7..9b847abb 100644 --- a/Sources/Classes/RSUtils.m +++ b/Sources/Classes/RSUtils.m @@ -284,11 +284,17 @@ +(NSArray*) extractParamFromURL: (NSURL*) deepLinkURL{ // Get the query items queryItems = components.queryItems; - } - return queryItems; + return queryItems != nil ? queryItems : [NSArray array]; } unsigned int MAX_EVENT_SIZE = 32 * 1024; // 32 KB unsigned int MAX_BATCH_SIZE = 500 * 1024; // 500 KB ++ (NSString *)secondsToString:(int) delay { + int min = delay / 60; + int sec = delay % 60; + NSString *finalString = min > 0 ? [NSString stringWithFormat:@"%dm, %ds", min, sec] : [NSString stringWithFormat:@"%ds", sec]; + return finalString; +} + @end From b52251b8b5afeef8994a9f711c634b429659ac26 Mon Sep 17 00:00:00 2001 From: Satheesh Kannan <satheeshkannan.ios@gmail.com> Date: Wed, 7 Aug 2024 11:12:53 +0530 Subject: [PATCH 3/4] fix: set anonymousId in traits when second Identify event is made (#526) --- Sources/Classes/RSContext.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Classes/RSContext.m b/Sources/Classes/RSContext.m index 84262f4e..97590bb9 100644 --- a/Sources/Classes/RSContext.m +++ b/Sources/Classes/RSContext.m @@ -128,6 +128,7 @@ - (void) updateTraits:(RSTraits *)traits { if(existingId!=nil && userId!=nil && ![existingId isEqual:userId]) { self->_traits = [[traits dict] mutableCopy]; + self->_traits[@"anonymousId"] = [self->preferenceManager getAnonymousId]; [self resetExternalIds]; return; } From 27153f90086f3eb903ed7cea960d2074d1131ab1 Mon Sep 17 00:00:00 2001 From: GitHub actions <noreply@github.com> Date: Wed, 7 Aug 2024 06:13:05 +0000 Subject: [PATCH 4/4] chore(release): 1.28.0 --- CHANGELOG.md | 12 ++++++++++++ README.md | 10 +++++----- Sources/Classes/Headers/RSVersion.h | 2 +- package.json | 2 +- sonar-project.properties | 2 +- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25cbb92c..dd568587 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ 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.28.0](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.27.0...v1.28.0) (2024-08-07) + + +### Features + +* implement exponential retry mechanism for handling network errors ([#525](https://github.com/rudderlabs/rudder-sdk-ios/issues/525)) ([8bf2900](https://github.com/rudderlabs/rudder-sdk-ios/commit/8bf2900710f06e6c9f268bd6fa4e405bcaa417ed)) + + +### Bug Fixes + +* set anonymousId in traits when second Identify event is made ([#526](https://github.com/rudderlabs/rudder-sdk-ios/issues/526)) ([b52251b](https://github.com/rudderlabs/rudder-sdk-ios/commit/b52251b8b5afeef8994a9f711c634b429659ac26)) + ## [1.27.0](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.26.2...v1.27.0) (2024-06-13) diff --git a/README.md b/README.md index c16c9a73..9c7f1532 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ <p align="center"> <a href="https://cocoapods.org/pods/Rudder"> - <img src="https://img.shields.io/static/v1?label=pod&message=v1.27.0&color=blue&style=flat"> + <img src="https://img.shields.io/static/v1?label=pod&message=v1.28.0&color=blue&style=flat"> </a> </p> @@ -39,7 +39,7 @@ The iOS SDK is available through [**CocoaPods**](https://cocoapods.org), [**Cart To install the SDK, simply add the following line to your Podfile: ```xcode -pod 'Rudder', '1.27.0' +pod 'Rudder', '1.28.0' ``` ### Carthage @@ -47,7 +47,7 @@ pod 'Rudder', '1.27.0' For Carthage support, add the following line to your `Cartfile`: ```xcode -github "rudderlabs/rudder-sdk-ios" "v1.27.0" +github "rudderlabs/rudder-sdk-ios" "v1.28.0" ``` > Remember to include the following code in all `.m` and `.h` files where you want to refer to or use the RudderStack SDK classes, as shown: @@ -71,7 +71,7 @@ You can also add the RudderStack iOS SDK via Swift Package Mangaer, via one of t * Enter the package repository (`git@github.com:rudderlabs/rudder-sdk-ios.git`) in the search bar. -* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.27.0` as the value, as shown: +* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.28.0` as the value, as shown: ![Setting dependency](https://user-images.githubusercontent.com/59817155/145574696-8c849749-13e0-40d5-aacb-3fccb5c8e67d.png) @@ -99,7 +99,7 @@ let package = Package( ], dependencies: [ // Dependencies declare other packages that this package depends on. - .package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.27.0") + .package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.28.0") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/Classes/Headers/RSVersion.h b/Sources/Classes/Headers/RSVersion.h index 45eb7ac8..115cb937 100644 --- a/Sources/Classes/Headers/RSVersion.h +++ b/Sources/Classes/Headers/RSVersion.h @@ -8,6 +8,6 @@ #ifndef RSVersion_h #define RSVersion_h -NSString *const SDK_VERSION = @"1.27.0"; +NSString *const SDK_VERSION = @"1.28.0"; #endif /* RSVersion_h */ diff --git a/package.json b/package.json index c93d0153..27819ea4 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,4 @@ { - "version": "1.27.0", + "version": "1.28.0", "description": "Rudder is a platform for collecting, storing and routing customer event data to dozens of tools" } diff --git a/sonar-project.properties b/sonar-project.properties index d5c51e54..d0345e8c 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.qualitygate.wait=false sonar.projectKey=rudderlabs_rudder-sdk-ios sonar.organization=rudderlabs sonar.projectName=RudderStack iOS SDK -sonar.projectVersion=1.27.0 +sonar.projectVersion=1.28.0 # C/C++/Objective-C related details # sonar.cfamily.compile-commands=compile_commands.json