Skip to content

Commit

Permalink
fix: Properly attribute events when workspace switches on new launch
Browse files Browse the repository at this point in the history
  • Loading branch information
einsteinx2 committed Sep 4, 2024
1 parent 0c8da18 commit b7ba48b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 10 deletions.
4 changes: 2 additions & 2 deletions mParticle-Apple-SDK/Include/mParticle.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ Defaults to false. Prevents the eventsHost above from overwriting the alias endp
(Provided to accomodate certain advanced use cases. Most integrations of the SDK will not require modifying this property.)
*/
@property (nonatomic, strong, readwrite) MPNetworkOptions *networkOptions;
@property (nonatomic, strong, readwrite, nullable) MPNetworkOptions *networkOptions;

/**
Consent state.
Expand Down Expand Up @@ -572,7 +572,7 @@ Defaults to false. Prevents the eventsHost above from overwriting the alias endp
Allows you to proxy SDK traffic by overriding the default network endpoints and certificates used by the SDK.
@see MParticleOptions
*/
@property (nonatomic, readonly) MPNetworkOptions *networkOptions;
@property (nonatomic, readonly, nullable) MPNetworkOptions *networkOptions;

#if TARGET_OS_IOS == 1
/**
Expand Down
6 changes: 4 additions & 2 deletions mParticle-Apple-SDK/MPBackendController.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
@class MPCommerceEvent;
@class MPConsentState;
@class MParticleSession;
@class MPUploadSettings;
@class MPNetworkOptions;

@protocol MPBackendControllerDelegate;

Expand Down Expand Up @@ -97,14 +99,14 @@ extern const NSInteger kInvalidKey;
- (void)setUserAttribute:(nonnull NSString *)key values:(nullable NSArray<NSString *> *)values timestamp:(nonnull NSDate *)timestamp completionHandler:(void (^ _Nullable)(NSString * _Nonnull key, NSArray<NSString *> * _Nullable values, MPExecStatus execStatus))completionHandler;
- (void)removeUserAttribute:(nonnull NSString *)key timestamp:(nonnull NSDate *)timestamp completionHandler:(void (^ _Nullable)(NSString * _Nullable key, id _Nullable value, MPExecStatus execStatus))completionHandler;
- (void)setUserIdentity:(nullable NSString *)identityString identityType:(MPUserIdentity)identityType timestamp:(nonnull NSDate *)timestamp completionHandler:(void (^ _Nonnull)(NSString * _Nullable identityString, MPUserIdentity identityType, MPExecStatus execStatus))completionHandler;
- (void)startWithKey:(nonnull NSString *)apiKey secret:(nonnull NSString *)secret firstRun:(BOOL)firstRun installationType:(MPInstallationType)installationType proxyAppDelegate:(BOOL)proxyAppDelegate startKitsAsync:(BOOL)startKitsAsync consentState:(MPConsentState *_Nullable)consentState completionHandler:(dispatch_block_t _Nonnull)completionHandler;
- (void)startWithKey:(nonnull NSString *)apiKey secret:(nonnull NSString *)secret networkOptions:(nullable MPNetworkOptions *)networkOptions firstRun:(BOOL)firstRun installationType:(MPInstallationType)installationType proxyAppDelegate:(BOOL)proxyAppDelegate startKitsAsync:(BOOL)startKitsAsync consentState:(MPConsentState *_Nullable)consentState completionHandler:(dispatch_block_t _Nonnull)completionHandler;
- (void)unproxyOriginalAppDelegate;
- (void)saveMessage:(nonnull MPMessage *)message updateSession:(BOOL)updateSession;
- (void)skipNextUpload;
- (MPExecStatus)waitForKitsAndUploadWithCompletionHandler:(void (^ _Nullable)(void))completionHandler;
- (nonnull NSMutableDictionary<NSString *, id> *)userAttributesForUserId:(nonnull NSNumber *)userId;
- (nonnull NSMutableArray<NSDictionary<NSString *, id> *> *)userIdentitiesForUserId:(nonnull NSNumber *)userId;
- (void)prepareBatchesForUpload;
- (void)prepareBatchesForUpload:(nonnull MPUploadSettings *)uploadSettings;

#if TARGET_OS_IOS == 1
#ifndef MPARTICLE_LOCATION_DISABLE
Expand Down
25 changes: 21 additions & 4 deletions mParticle-Apple-SDK/MPBackendController.m
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ - (void)skipNextUpload {
skipNextUpload = YES;
}

- (void)prepareBatchesForUpload {
- (void)prepareBatchesForUpload:(MPUploadSettings *)uploadSettings {
MPPersistenceController *persistence = [MParticle sharedInstance].persistenceController;

//Fetch all stored messages (1)
Expand All @@ -687,7 +687,7 @@ - (void)prepareBatchesForUpload {
uploadInterval:self.uploadInterval
dataPlanId:nullableDataPlanId
dataPlanVersion:nullableDataPlanVersion
uploadSettings:[MPUploadSettings currentUploadSettings]];
uploadSettings:uploadSettings];
[uploadBuilder withUserAttributes:[self userAttributesForUserId:mpid] deletedUserAttributes:self.deletedUserAttributes];
[uploadBuilder withUserIdentities:[self userIdentitiesForUserId:mpid]];
[uploadBuilder build:^(MPUpload *upload) {
Expand All @@ -712,7 +712,7 @@ - (void)prepareBatchesForUpload {

- (void)uploadBatchesWithCompletionHandler:(void(^)(BOOL success))completionHandler {
// Prepare upload records
[self prepareBatchesForUpload];
[self prepareBatchesForUpload:[MPUploadSettings currentUploadSettings]];

const void (^completionHandlerCopy)(BOOL) = [completionHandler copy];
MPPersistenceController *persistence = [MParticle sharedInstance].persistenceController;
Expand Down Expand Up @@ -1500,7 +1500,7 @@ - (MPExecStatus)setSessionAttribute:(MPSession *)session key:(NSString *)key val
return MPExecStatusSuccess;
}

- (void)startWithKey:(NSString *)apiKey secret:(NSString *)secret firstRun:(BOOL)firstRun installationType:(MPInstallationType)installationType proxyAppDelegate:(BOOL)proxyAppDelegate startKitsAsync:(BOOL)startKitsAsync consentState:(MPConsentState *)consentState completionHandler:(dispatch_block_t)completionHandler {
- (void)startWithKey:(NSString *)apiKey secret:(NSString *)secret networkOptions:(nullable MPNetworkOptions *)networkOptions firstRun:(BOOL)firstRun installationType:(MPInstallationType)installationType proxyAppDelegate:(BOOL)proxyAppDelegate startKitsAsync:(BOOL)startKitsAsync consentState:(MPConsentState *)consentState completionHandler:(dispatch_block_t)completionHandler {
[MPListenerController.sharedInstance onAPICalled:_cmd parameter1:apiKey parameter2:secret parameter3:@(firstRun) parameter4:consentState];

if (![MPStateMachine isAppExtension]) {
Expand Down Expand Up @@ -1536,6 +1536,23 @@ - (void)startWithKey:(NSString *)apiKey secret:(NSString *)secret firstRun:(BOOL
dispatch_async([MParticle messageQueue], ^{
[MParticle sharedInstance].persistenceController = [[MPPersistenceController alloc] init];

// Check if we've switched workspaces on startup
MPUploadSettings *lastUploadSettings = [[MPIUserDefaults standardUserDefaults] lastUploadSettings];
if (![lastUploadSettings.apiKey isEqualToString:apiKey]) {
// Different workspace, so batch previous messages under old upload settings before starting
[self prepareBatchesForUpload:lastUploadSettings];

// Delete the stored upload settings
[[MPIUserDefaults standardUserDefaults] setLastUploadSettings:nil];

// Delete the cached config
[MPResponseConfig deleteConfig];
}

// Cache the upload settings in case we switch workspaces on startup
MPUploadSettings *uploadSettings = [MPUploadSettings currentUploadSettings];
[[MPIUserDefaults standardUserDefaults] setLastUploadSettings:uploadSettings];

// Restore cached config if exists
[MPResponseConfig restore];

Expand Down
1 change: 1 addition & 0 deletions mParticle-Apple-SDK/MPIConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ extern NSString * _Nonnull const kMPUserAgentValueUserDefaultsKey;
extern NSString * _Nonnull const kMPFirstSeenUser;
extern NSString * _Nonnull const kMPLastSeenUser;
extern NSString * _Nonnull const kMPAppForePreviousForegroundTime;
extern NSString * _Nonnull const kMPLastUploadSettingsUserDefaultsKey;

// Remote configuration
extern NSString * _Nonnull const kMPRemoteConfigExceptionHandlingModeKey;
Expand Down
1 change: 1 addition & 0 deletions mParticle-Apple-SDK/MPIConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
NSString *const kMPFirstSeenUser = @"fsu";
NSString *const kMPLastSeenUser = @"lsu";
NSString *const kMPAppForePreviousForegroundTime = @"pft";
NSString *const kMPLastUploadSettingsUserDefaultsKey = @"lastUploadSettings";

// Remote configuration
NSString *const kMPRemoteConfigExceptionHandlingModeKey = @"cue";
Expand Down
3 changes: 3 additions & 0 deletions mParticle-Apple-SDK/Utils/MPIUserDefaults.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>

@class MPKitConfiguration;
@class MPUploadSettings;

@interface MPIUserDefaults : NSObject

Expand Down Expand Up @@ -29,6 +30,8 @@
- (BOOL)isConfigurationParametersOutdated;
- (void)setSideloadedKitsCount:(NSUInteger)sideloadedKitsCount;
- (NSUInteger)sideloadedKitsCount;
- (void)setLastUploadSettings:(nullable MPUploadSettings *)lastUploadSettings;
- (nullable MPUploadSettings *)lastUploadSettings;

+ (NSString *_Nullable)stringFromDeviceToken:(NSData *_Nonnull)deviceToken;

Expand Down
30 changes: 30 additions & 0 deletions mParticle-Apple-SDK/Utils/MPIUserDefaults.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#import "MPStateMachine.h"
#import "MPKitContainer.h"
#import "MParticleSwift.h"
#import "MPUpload.h"

@interface MParticle ()

Expand Down Expand Up @@ -434,6 +435,35 @@ - (NSUInteger)sideloadedKitsCount {
return [[[NSUserDefaults standardUserDefaults] objectForKey:MPSideloadedKitsCountUserDefaultsKey] intValue];
}

- (void)setLastUploadSettings:(nullable MPUploadSettings *)lastUploadSettings {
if (!lastUploadSettings) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kMPLastUploadSettingsUserDefaultsKey];
return;
}

@try {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:lastUploadSettings];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:kMPLastUploadSettingsUserDefaultsKey];
} @catch(NSException *exception) {
MPILogError(@"Error serializing last upload settings: %@: %@", exception.name, exception.reason);
[self setLastUploadSettings:nil];
}
}

- (nullable MPUploadSettings *)lastUploadSettings {
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kMPLastUploadSettingsUserDefaultsKey];
if (data) {
@try {
MPUploadSettings *uploadSettings = [NSKeyedUnarchiver unarchiveObjectWithData:data];
return uploadSettings;
} @catch(NSException *exception) {
MPILogError(@"Error deserializing last upload settings: %@: %@", exception.name, exception.reason);
[self setLastUploadSettings:nil];
}
}
return nil;
}

#pragma mark Objective-C Literals
- (id)objectForKeyedSubscript:(NSString *const)key {
if ([key isEqualToString:@"mpid"]) {
Expand Down
6 changes: 4 additions & 2 deletions mParticle-Apple-SDK/mParticle.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#import "MPDataPlanFilter.h"
#import "MPResponseConfig.h"
#import "MParticleSwift.h"
#import "MPUpload.h"

#if TARGET_OS_IOS == 1
#ifndef MPARTICLE_LOCATION_DISABLE
Expand Down Expand Up @@ -74,7 +75,7 @@ @interface MParticle() <MPBackendControllerDelegate
@property (nonatomic, strong, nullable) MPKitActivity *kitActivity;
@property (nonatomic) BOOL initialized;
@property (nonatomic, strong, nonnull) NSMutableArray *kitsInitializedBlocks;
@property (nonatomic, readwrite) MPNetworkOptions *networkOptions;
@property (nonatomic, readwrite, nullable) MPNetworkOptions *networkOptions;
@property (nonatomic, strong, nullable) NSArray<NSDictionary *> *deferredKitConfiguration;
@property (nonatomic, strong) MParticleWebView *webView;
@property (nonatomic, strong, nullable) NSString *dataPlanId;
Expand Down Expand Up @@ -613,6 +614,7 @@ - (void)startWithOptions:(MParticleOptions *)options {

[self.backendController startWithKey:apiKey
secret:secret
networkOptions:options.networkOptions
firstRun:firstRun
installationType:installationType
proxyAppDelegate:proxyAppDelegate
Expand Down Expand Up @@ -765,7 +767,7 @@ - (void)switchWorkspaceWithOptions:(MParticleOptions *)options {

// Batch any remaining messages into upload records
[MParticle executeOnMessage:^{
[self.backendController prepareBatchesForUpload];
[self.backendController prepareBatchesForUpload:[MPUploadSettings currentUploadSettings]];
finishReset();
}];
} else {
Expand Down

0 comments on commit b7ba48b

Please sign in to comment.