Skip to content

Commit

Permalink
Initial attempt to decouple persistence
Browse files Browse the repository at this point in the history
  • Loading branch information
alexs-mparticle committed Jan 19, 2024
1 parent 8c84e26 commit 09d7944
Show file tree
Hide file tree
Showing 9 changed files with 379 additions and 75 deletions.
5 changes: 5 additions & 0 deletions src/identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ export default function Identity(mpInstance) {
* @return {Object} the user for mpid
*/
getUser: function(mpid) {
// FIXME: This seems to break if persistence is not enabled
var persistence = mpInstance._Persistence.getPersistence();
if (persistence) {
if (
Expand Down Expand Up @@ -1463,15 +1464,19 @@ export default function Identity(mpInstance) {
mpInstance._Store.mpid = identityApiResult.mpid;

if (prevUser) {
// TODO: Replace this with store
mpInstance._Persistence.setLastSeenTime(previousMPID);
}

if (
// TODO: Replace this with store
!mpInstance._Persistence.getFirstSeenTime(
identityApiResult.mpid
)
)
mpidIsNotInCookies = true;

// TODO: Replace this with store
mpInstance._Persistence.setFirstSeenTime(
identityApiResult.mpid
);
Expand Down
4 changes: 2 additions & 2 deletions src/mockBatchCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import ServerModel from './serverModel';
import { SDKEvent, BaseEvent, MParticleWebSDK } from './sdkRuntimeModels';
import { convertEvents } from './sdkToEventsApiConverter';
import * as EventsApi from '@mparticle/event-models';
import { Batch } from '@mparticle/event-models';
import { IMPSideloadedKit} from './sideloadedKit';

const mockFunction = function() {
return null;
Expand Down Expand Up @@ -89,6 +87,8 @@ export default class _BatchValidator {
isDevelopmentMode: false,
onCreateBatch: mockFunction,
},
getDeviceId: mockFunction,
setDeviceId: mockFunction,
},
config: null,
eCommerce: null,
Expand Down
68 changes: 55 additions & 13 deletions src/mp-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ export default function mParticleInstance(instanceName) {
this._instanceName = instanceName;
this._NativeSdkHelpers = new NativeSdkHelpers(this);
this._SessionManager = new SessionManager(this);

// QUESTION: Why can't we just init the store here?
// QUESTION: Should we still initialize if persistence is off?

// debugger;
this._Persistence = new Persistence(this);

this._Helpers = new Helpers(this);
this._Events = new Events(this);
this._CookieSyncManager = new CookieSyncManager(this);
Expand All @@ -84,6 +90,8 @@ export default function mParticleInstance(instanceName) {
this._Identity = new Identity(this);
this.Identity = this._Identity.IdentityAPI;
this.generateHash = this._Helpers.generateHash;

// QUESTION: Why do we not init store here instead of persistence?
this.getDeviceId = this._Persistence.getDeviceId;

if (typeof window !== 'undefined') {
Expand Down Expand Up @@ -143,7 +151,9 @@ export default function mParticleInstance(instanceName) {
*/
this.reset = function(instance) {
try {
instance._Persistence.resetPersistence();
if (instance._Store.SDKConfig.usePersistence) {
instance._Persistence.resetPersistence();
}
if (instance._Store) {
delete instance._Store;
}
Expand All @@ -157,15 +167,21 @@ export default function mParticleInstance(instanceName) {
delete instance._Store;
}
instance._Store = new Store(config, instance);
instance._Store.isLocalStorageAvailable = instance._Persistence.determineLocalStorageAvailability(
window.localStorage
);

if (instance._Store.SDKConfig.usePersistence) {
instance._Store.isLocalStorageAvailable = instance._Persistence.determineLocalStorageAvailability(
window.localStorage
);
instance._Persistence.forwardingStatsBatches.uploadsTable = {};
instance._Persistence.forwardingStatsBatches.forwardingStatsEventQueue = [];
}

instance._Events.stopTracking();
if (!keepPersistence) {

if (!keepPersistence && instance._Store.SDKConfig.usePersistence) {
instance._Persistence.resetPersistence();
}
instance._Persistence.forwardingStatsBatches.uploadsTable = {};
instance._Persistence.forwardingStatsBatches.forwardingStatsEventQueue = [];

instance._preInit = {
readyQueue: [],
pixelConfigurations: [],
Expand Down Expand Up @@ -217,7 +233,9 @@ export default function mParticleInstance(instanceName) {
if (queued) return;

self._Store.SDKConfig.appVersion = version;
self._Persistence.update();
if (self.Store.SDKConfig.usePersistence) {
self._Persistence.update();
}
};
/**
* Sets the device id
Expand All @@ -229,7 +247,12 @@ export default function mParticleInstance(instanceName) {
self.setDeviceId(guid);
}, self);
if (queued) return;
this._Persistence.setDeviceId(guid);

// debugger;
// TODO: Replace this with Store.setDeviceId
if (self.Store.SDKConfig.usePersistence) {
this._Persistence.setDeviceId(guid);
}
};
/**
* Returns a boolean for whether or not the SDKhas been fully initialized
Expand Down Expand Up @@ -1073,7 +1096,9 @@ export default function mParticleInstance(instanceName) {
}

self._Store.sessionAttributes[key] = value;
self._Persistence.update();
if (self._Store.SDKConfig.usePersistence) {
self._Persistence.update();
}

self._Forwarders.applyToForwarders('setSessionAttribute', [
key,
Expand All @@ -1098,7 +1123,9 @@ export default function mParticleInstance(instanceName) {
self._Store.isEnabled = !isOptingOut;

self._Events.logOptOut();
self._Persistence.update();
if (self._Store.SDKConfig.usePersistence) {
self._Persistence.update();
}

if (self._Store.activeForwarders.length) {
self._Store.activeForwarders.forEach(function(forwarder) {
Expand Down Expand Up @@ -1185,7 +1212,9 @@ export default function mParticleInstance(instanceName) {
);
return;
}
self._Persistence.update();
if (self._Store.SDKConfig.usePersistence) {
self._Persistence.update();
}
};
/**
* Get integration attributes for a given integration ID.
Expand Down Expand Up @@ -1333,7 +1362,12 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
// https://go.mparticle.com/work/SQDSDKS-6044
if (!mpInstance._Store.webviewBridgeEnabled) {
// Load any settings/identities/attributes from cookie or localStorage
mpInstance._Persistence.initializeStorage();
// FIXME: if persistence is turned off, device id never gets set
// FIXME: maybe we set device id in _Store and that fixes everything?
// debugger;
if (mpInstance._Store.SDKConfig.usePersistence) {
mpInstance._Persistence.initializeStorage();
}
}

if (mpInstance._Store.webviewBridgeEnabled) {
Expand Down Expand Up @@ -1532,6 +1566,14 @@ function runPreConfigFetchInitialization(mpInstance, apiKey, config) {
Messages.InformationMessages.StartingInitialization
);

if (!mpInstance._Store.SDKConfig.usePersistence) {
mpInstance.Logger.warning(
'usePersistence is set to false in pre-config check. Persistence will not be used'
);

return;
}

// Check to see if localStorage is available before main configuration runs
// since we will need this for the current implementation of user persistence
// TODO: Refactor this when we refactor User Identity Persistence
Expand Down
8 changes: 8 additions & 0 deletions src/persistence.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ var Base64 = Polyfill.Base64,
export default function _Persistence(mpInstance) {
var self = this;

// QUESTION: Should isEnabled be a param on the constructor, or should it read from config?
this.isEnabled = function() {
return mpInstance._Store.SDKConfig.usePersistence;
};

// https://go.mparticle.com/work/SQDSDKS-5022
this.useLocalStorage = function() {
return (
Expand Down Expand Up @@ -1058,6 +1063,9 @@ export default function _Persistence(mpInstance) {
};

this.getPersistence = function() {
if (!this.isEnabled()) {
return null;
}
var persistence = this.useLocalStorage()
? this.getLocalStorage()
: this.getCookie();
Expand Down
1 change: 1 addition & 0 deletions src/sdkRuntimeModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ export interface SDKInitConfig
sessionTimeout?: number;
useNativeSdk?: boolean;
useCookieStorage?: boolean;
usePersistence?: boolean;
v1SecureServiceUrl?: string;
v2SecureServiceUrl?: string;
v3SecureServiceUrl?: string;
Expand Down
84 changes: 57 additions & 27 deletions src/sessionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default function SessionManager(
self.endSession();
self.startNewSession();
} else {
// QUESTION: Should we check for current user if we don't have persistence?
// https://go.mparticle.com/work/SQDSDKS-6045
const persistence: IPersistenceMinified = mpInstance._Persistence.getPersistence();
if (persistence && !persistence.cu) {
Expand Down Expand Up @@ -120,6 +121,7 @@ export default function SessionManager(
};

this.endSession = function(override: boolean): void {
// debugger;
mpInstance.Logger.verbose(
Messages.InformationMessages.StartingEndSession
);
Expand All @@ -129,10 +131,12 @@ export default function SessionManager(
messageType: Types.MessageType.SessionEnd,
});

nullifySession();
mpInstance._Store.nullifySession();
return;
}

// debugger;

if (!mpInstance._Helpers.canLog()) {
// At this moment, an AbandonedEndSession is defined when on of three things occurs:
// - the SDK's store is not enabled because mParticle.setOptOut was called
Expand All @@ -144,33 +148,60 @@ export default function SessionManager(
return;
}

// debugger;

let sessionTimeoutInMilliseconds: number;
let timeSinceLastEventSent: number;

const cookies: IPersistenceMinified = mpInstance._Persistence.getPersistence();
const persistence: IPersistenceMinified = mpInstance._Persistence.getPersistence();

// TODO: https://go.mparticle.com/work/SQDSDKS-5684
if (!cookies) {
return;
}
// debugger;

if (cookies.gs && !cookies.gs.sid) {
// QUESTION: What constitutes ending a session if we don't have persistence?

// If for some reason we do not have a session ID, there is no session to end
if (
!persistence?.gs?.sid &&
!mpInstance._Store.sessionId
) {
mpInstance.Logger.verbose(
Messages.InformationMessages.NoSessionToEnd
);
return;
}

// sessionId is not equal to cookies.sid if cookies.sid is changed in another tab
if (cookies.gs.sid && mpInstance._Store.sessionId !== cookies.gs.sid) {
mpInstance._Store.sessionId = cookies.gs.sid;
// If sessionId exists in persistence and is different than Store, persistence takes precedence
// For example, if persistence changed in a separate browser instance or tab
if (
persistence?.gs &&
persistence?.gs.sid &&
mpInstance._Store.sessionId !== persistence.gs.sid
) {
mpInstance._Store.sessionId = persistence.gs.sid;
}

// debugger;

// Check Store for last time event was sent. If there is a different value in persistence,
// use that and update the Store
// TODO: Check if dateLastEventSent and return early if it does not exist
let timeLastEventSent: number = mpInstance._Store.dateLastEventSent?.getTime();
if (
persistence?.gs &&
persistence?.gs.les &&
timeLastEventSent !== persistence.gs.les
) {
timeLastEventSent = persistence.gs.les;
mpInstance._Store.dateLastEventSent = new Date(persistence.gs.les);
}

if (cookies?.gs?.les) {
// debugger;

if (timeLastEventSent) {
sessionTimeoutInMilliseconds =
mpInstance._Store.SDKConfig.sessionTimeout * 60000;
const newDate: number = new Date().getTime();
timeSinceLastEventSent = newDate - cookies.gs.les;
timeSinceLastEventSent = newDate - timeLastEventSent;

if (timeSinceLastEventSent < sessionTimeoutInMilliseconds) {
self.setSessionTimer();
Expand All @@ -179,8 +210,7 @@ export default function SessionManager(
messageType: Types.MessageType.SessionEnd,
});

mpInstance._Store.sessionStartDate = null;
nullifySession();
mpInstance._Store.nullifySession();
}
}
};
Expand All @@ -190,6 +220,8 @@ export default function SessionManager(
mpInstance._Store.SDKConfig.sessionTimeout * 60000;

mpInstance._Store.globalTimer = window.setTimeout(function() {
// TODO: kill this global timer when ending session
// debugger;
self.endSession();
}, sessionTimeoutInMilliseconds);
};
Expand All @@ -213,20 +245,18 @@ export default function SessionManager(
if (!mpInstance._Store.webviewBridgeEnabled) {
const persistence = mpInstance._Persistence.getPersistence();

if (!mpInstance._Store.sessionId && persistence) {
if (persistence.sid) {
mpInstance._Store.sessionId = persistence.sid;
} else {
self.startNewSession();
}
if (
persistence?.gs &&
persistence?.gs.sid &&
mpInstance._Store.sessionId !== persistence.gs.sid
) {
mpInstance._Store.sessionId = persistence.gs.sid;
}

// TODO: Make this a store method
if (!mpInstance._Store.sessionId) {
self.startNewSession();
}
}
};

function nullifySession(): void {
mpInstance._Store.sessionId = null;
mpInstance._Store.dateLastEventSent = null;
mpInstance._Store.sessionAttributes = {};
mpInstance._Persistence.update();
}
}
Loading

0 comments on commit 09d7944

Please sign in to comment.