Skip to content

Commit

Permalink
feat: made reset and identify api's synchronous to reflect the data i…
Browse files Browse the repository at this point in the history
…mmediately (#284)

* feat: made reset and identify api's synchronous to reflect the data immediately

* chore: updated RSContext Headerfile

* refactor: made rscontext queue private and other classes to use their own queue

* fix: made setConsentData synchronous and few minor changes

* test: added unit tests for RSContext.m

* test: fixed minor issues in unit test cases for RSContext

* fix: made return type as nullable for applicable methods in RSContext.m

* test: fixed issues with nil return type in unit test cases

* chore: minor refactoring and issue fixes

* refactor: optimized the test case for setting consent data

* ci: added workflows for making a beta release

* chore: bumped version to 1.13.0.beta.2

---------

Co-authored-by: Desu Sai Venkat <desusaivenkat@Desus-MacBook-Pro.local>
  • Loading branch information
desusai7 and Desu Sai Venkat committed Mar 27, 2023
1 parent 4838b49 commit 6ff743a
Show file tree
Hide file tree
Showing 18 changed files with 390 additions and 106 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,13 @@

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.13.0.beta.2]

### Features

* Made the Identify and Reset API's Synchronous


### [1.12.1](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.12.0...v1.12.1) (2023-03-21)


Expand Down
10 changes: 5 additions & 5 deletions README.md
Expand Up @@ -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.12.1&color=blue&style=flat">
<img src="https://img.shields.io/static/v1?label=pod&message=v1.13.0.beta.2&color=blue&style=flat">
</a>
</p>

Expand Down Expand Up @@ -39,15 +39,15 @@ 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.12.1'
pod 'Rudder', '1.13.0.beta.2'
```

### Carthage

For Carthage support, add the following line to your `Cartfile`:

```xcode
github "rudderlabs/rudder-sdk-ios" "v1.12.1"
github "rudderlabs/rudder-sdk-ios" "v1.13.0.beta.2"
```

> 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:
Expand All @@ -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.12.1` as the value, as shown:
* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.13.0.beta.2` as the value, as shown:

![Setting dependency](https://user-images.githubusercontent.com/59817155/145574696-8c849749-13e0-40d5-aacb-3fccb5c8e67d.png)

Expand Down Expand Up @@ -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.12.1")
.package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.13.0.beta.2")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
4 changes: 4 additions & 0 deletions Rudder.xcodeproj/project.pbxproj
Expand Up @@ -199,6 +199,7 @@
ED8DB01E298E206900907EC4 /* RSConsentFilterHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8DB01D298E206900907EC4 /* RSConsentFilterHandler.m */; };
EDB3393629960F5E00706003 /* multi-dataresidency-eu-true.json in Resources */ = {isa = PBXBuildFile; fileRef = EDB3393429960F5E00706003 /* multi-dataresidency-eu-true.json */; };
EDB3393729960F5E00706003 /* multi-dataresidency-us-true.json in Resources */ = {isa = PBXBuildFile; fileRef = EDB3393529960F5E00706003 /* multi-dataresidency-us-true.json */; };
F64F9D7629BF171D009D963F /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F64F9D7529BF171D009D963F /* ContextTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -419,6 +420,7 @@
EDB3393429960F5E00706003 /* multi-dataresidency-eu-true.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "multi-dataresidency-eu-true.json"; sourceTree = "<group>"; };
EDB3393529960F5E00706003 /* multi-dataresidency-us-true.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "multi-dataresidency-us-true.json"; sourceTree = "<group>"; };
EDEC3CDA29ADEF87007DDE07 /* github-release.config.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "github-release.config.js"; sourceTree = "<group>"; };
F64F9D7529BF171D009D963F /* ContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -479,6 +481,7 @@
ED7DFD80298C061A00ED5A8E /* DataResidencyTests.swift */,
ED04A23E29839DCC0080A88D /* EventRepositoryTests.swift */,
ED20F4F52996083B00F3FD0E /* TestUtils.swift */,
F64F9D7529BF171D009D963F /* ContextTests.swift */,
);
path = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -1067,6 +1070,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F64F9D7629BF171D009D963F /* ContextTests.swift in Sources */,
ED7DFD81298C061A00ED5A8E /* DataResidencyTests.swift in Sources */,
ED04A247298424040080A88D /* ConserFilterHandlerTests.swift in Sources */,
ED04A23F29839DCC0080A88D /* EventRepositoryTests.swift in Sources */,
Expand Down
14 changes: 7 additions & 7 deletions Sources/Classes/Headers/Public/RSContext.h
Expand Up @@ -44,21 +44,21 @@ extern int const RSATTAuthorize;
@property (nonatomic, readwrite) BOOL sessionStart;
@property (nonatomic, readwrite) NSMutableArray<NSMutableDictionary<NSString*, NSObject*>*> *externalIds;

+ (dispatch_queue_t)getQueue;
- (NSDictionary<NSString *, NSObject *>*)dict;
- (NSDictionary<NSString*, NSObject *>*)dict;
- (void)resetTraits;
- (void)updateTraits:(RSTraits *_Nullable) traits;
- (void)persistTraits;
- (void)updateTraits:(RSTraits* _Nullable)traits;
- (void)persistTraitsOnQueue;
- (void)updateTraitsDict:(NSMutableDictionary<NSString*, NSObject*>*)traitsDict;
- (void)updateTraitsAnonymousId;
- (void)putDeviceToken:(NSString*)deviceToken;
- (void)putAdvertisementId:(NSString *_Nonnull)idfa;
- (void)putAppTrackingConsent:(int)att;
- (void)updateExternalIds:(NSMutableArray *__nullable)externalIds;
- (void)resetExternalIds;
- (void)updateExternalIds:(NSMutableArray* __nullable)externalIds;
- (void)resetExternalIdsOnQueue;
- (void)persistExternalIds;
- (NSArray<NSDictionary<NSString*, NSObject*>*>* __nullable)getExternalIds;
- (void)setSessionData:(RSUserSession *)userSession;
- (void)setConsentData:(NSArray <NSString *> *)deniedConsentIds;
- (void)setConsentData:(NSArray <NSString*>*)deniedConsentIds;

@end

Expand Down
2 changes: 1 addition & 1 deletion Sources/Classes/Headers/Public/RSEventRepository.h
Expand Up @@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
BOOL isSDKEnabled;
NSLock* lock;
dispatch_source_t source;
dispatch_queue_t queue;
dispatch_queue_t repositoryQueue;
RSClient *client;
}

Expand Down
4 changes: 3 additions & 1 deletion Sources/Classes/Headers/Public/RSOption.h
Expand Up @@ -11,7 +11,9 @@
NS_ASSUME_NONNULL_BEGIN

@protocol RSIntegrationFactory;
@interface RSOption : NSObject
@interface RSOption : NSObject {
dispatch_queue_t optionsQueue;
}

@property (nonatomic, strong) NSMutableArray<NSMutableDictionary<NSString*, NSObject*>*>* externalIds;
@property (nonatomic, strong) NSMutableDictionary<NSString*, NSObject*>* integrations;
Expand Down
2 changes: 2 additions & 0 deletions Sources/Classes/Headers/Public/RSPreferenceManager.h
Expand Up @@ -35,6 +35,7 @@ extern NSString *const RSSessionAutoTrackStatus;

- (void) saveTraits: (NSString* __nonnull) traits;
- (NSString* __nonnull) getTraits;
- (void) clearTraits;

- (void) saveBuildVersionCode:(NSString* __nonnull)versionCode;
- (NSString* __nullable) getBuildVersionCode;
Expand All @@ -54,6 +55,7 @@ extern NSString *const RSSessionAutoTrackStatus;

- (NSString* __nullable) getAnonymousId;
- (void) saveAnonymousId: (NSString* __nullable) anonymousId;
- (void) clearAnonymousId;

- (BOOL) getOptStatus;
- (void) saveOptStatus: (BOOL) optStatus;
Expand Down
2 changes: 1 addition & 1 deletion Sources/Classes/Headers/RSVersion.h
Expand Up @@ -8,6 +8,6 @@
#ifndef RSVersion_h
#define RSVersion_h

NSString *const SDK_VERSION = @"1.12.1";
NSString *const SDK_VERSION = @"1.13.0.beta.2";

#endif /* RSVersion_h */
116 changes: 62 additions & 54 deletions Sources/Classes/RSContext.m
Expand Up @@ -37,43 +37,36 @@ - (instancetype)init {
_timezone = [[NSTimeZone localTimeZone] name];
_externalIds = nil;

dispatch_sync(queue, ^{
NSString *traitsJson = [preferenceManager getTraits];
if (traitsJson == nil) {
// no persisted traits, create new and persist
[self createAndPersistTraits];

NSString *traitsJson = [preferenceManager getTraits];
if (traitsJson == nil) {
// no persisted traits, create new and persist
[self createAndPersistTraits];
} else {
NSError *error;
NSDictionary *traitsDict = [NSJSONSerialization JSONObjectWithData:[traitsJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];
if (error == nil) {
_traits = [traitsDict mutableCopy];
} else {
NSError *error;
NSDictionary *traitsDict = [NSJSONSerialization JSONObjectWithData:[traitsJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];
if (error == nil) {
_traits = [traitsDict mutableCopy];
} else {
// persisted traits persing error. initiate blank
[self createAndPersistTraits];
}
// persisted traits persing error. initiate blank
[self createAndPersistTraits];
}
// get saved external Ids from prefs
NSString *externalIdJson = [preferenceManager getExternalIds];
if (externalIdJson != nil) {
NSError *error;
NSDictionary *externalIdDict = [NSJSONSerialization JSONObjectWithData:[externalIdJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];
if (error == nil) {
_externalIds = [externalIdDict mutableCopy];
}
}

// get saved external Ids from prefs
NSString *externalIdJson = [preferenceManager getExternalIds];
if (externalIdJson != nil) {
NSError *error;
NSDictionary *externalIdDict = [NSJSONSerialization JSONObjectWithData:[externalIdJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];
if (error == nil) {
_externalIds = [externalIdDict mutableCopy];
}
});
}

}
return self;
}

+ (dispatch_queue_t) getQueue {
if (queue == nil) {
queue = dispatch_queue_create("com.rudder.RSContext", NULL);
}
return queue;
}

- (void) createAndPersistTraits {
RSTraits* traits = [[RSTraits alloc] init];
traits.anonymousId = [preferenceManager getAnonymousId];
Expand All @@ -83,60 +76,63 @@ - (void) createAndPersistTraits {
}

- (void) resetTraits {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
RSTraits* traits = [[RSTraits alloc] init];
traits.anonymousId = [self->preferenceManager getAnonymousId];
[self->_traits removeAllObjects];
[self->_traits setValuesForKeysWithDictionary:[traits dict]];
});
}

- (void)updateTraits:(RSTraits *)traits {
dispatch_async(queue, ^{
- (void) updateTraits:(RSTraits *)traits {
dispatch_sync(queue, ^{
NSString* existingId = (NSString*)[self->_traits objectForKey:@"userId"];
NSString* userId = (NSString*) traits.userId;

if(existingId!=nil && userId!=nil && ![existingId isEqual:userId])
{
self->_traits = [[traits dict]mutableCopy];
self->_traits = [[traits dict] mutableCopy];
[self resetExternalIds];
return;
}
[self->_traits setValuesForKeysWithDictionary:[traits dict]];
});
}
}

-(void) persistTraits {
dispatch_async(queue, ^{
NSData *traitsJsonData = [NSJSONSerialization dataWithJSONObject:[RSUtils serializeDict:self->_traits] options:0 error:nil];
NSString *traitsString = [[NSString alloc] initWithData:traitsJsonData encoding:NSUTF8StringEncoding];

[self->preferenceManager saveTraits:traitsString];
- (void) persistTraitsOnQueue {
dispatch_sync(queue, ^{
[self persistTraits];
});
}

-(void) persistTraits {
NSData *traitsJsonData = [NSJSONSerialization dataWithJSONObject:[RSUtils serializeDict:self->_traits] options:0 error:nil];
NSString *traitsString = [[NSString alloc] initWithData:traitsJsonData encoding:NSUTF8StringEncoding];
[self->preferenceManager saveTraits:traitsString];
}

- (void)updateTraitsDict:(NSMutableDictionary<NSString *, NSObject *> *)traitsDict {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
self->_traits = traitsDict;
});
}

- (void)updateTraitsAnonymousId {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
self->_traits[@"anonymousId"] = [self->preferenceManager getAnonymousId];
});
}

- (void)putDeviceToken:(NSString *)deviceToken {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
self->_device.token = deviceToken;
});
}

- (void)putAdvertisementId:(NSString *_Nonnull)idfa {
// This isn't ideal. We're doing this because we can't actually check if IDFA is enabled on
// the customer device. Apple docs and tests show that if it is disabled, one gets back all 0's.
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
if( idfa != nil && [idfa length] != 0) {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"IDFA: %@", idfa]];
BOOL adTrackingEnabled = (![idfa isEqualToString:@"00000000-0000-0000-0000-000000000000"]);
Expand All @@ -150,7 +146,7 @@ - (void)putAdvertisementId:(NSString *_Nonnull)idfa {
}

- (void)updateExternalIds:(NSMutableArray *)externalIds {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
if(self->_externalIds == nil)
{
self->_externalIds = [[NSMutableArray alloc] init];
Expand Down Expand Up @@ -178,7 +174,7 @@ - (void)updateExternalIds:(NSMutableArray *)externalIds {
}

- (void)persistExternalIds {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
if (self->_externalIds != nil) {
// update persistence storage
NSData *externalIdJsonData = [NSJSONSerialization dataWithJSONObject:[RSUtils serializeArray:[self->_externalIds copy]] options:0 error:nil];
Expand All @@ -188,15 +184,27 @@ - (void)persistExternalIds {
});
}

- (void)resetExternalIds {
dispatch_async(queue, ^{
self->_externalIds = nil;
[self->preferenceManager clearExternalIds];
- (NSArray<NSDictionary<NSString*, NSObject*>*>* __nullable) getExternalIds {
__block NSArray<NSDictionary<NSString*, NSObject*>*>* externalIdsCopy = nil;
dispatch_sync(queue, ^{
externalIdsCopy = [self->_externalIds copy];
});
return externalIdsCopy;
}

- (void) resetExternalIdsOnQueue {
dispatch_sync(queue, ^{
[self resetExternalIds];
});
}

- (void)resetExternalIds {
self->_externalIds = nil;
[self->preferenceManager clearExternalIds];
}

- (void)putAppTrackingConsent:(int)att {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
if (att < RSATTNotDetermined) {
self->_device.attTrackingStatus = RSATTNotDetermined;
} else if (att > RSATTAuthorize) {
Expand All @@ -208,7 +216,7 @@ - (void)putAppTrackingConsent:(int)att {
}

- (void) setSessionData:(RSUserSession *) userSession {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
if ([userSession getSessionId] != nil) {
self->_sessionId = [userSession getSessionId];
if([userSession getSessionStart]) {
Expand All @@ -220,7 +228,7 @@ - (void) setSessionData:(RSUserSession *) userSession {
}

- (void)setConsentData:(NSArray <NSString *> *)deniedConsentIds {
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
self->consentManagement = @{@"deniedConsentIds": deniedConsentIds};
});
}
Expand Down

0 comments on commit 6ff743a

Please sign in to comment.