Skip to content

Commit

Permalink
pulse
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderkirtzel committed May 31, 2024
1 parent 8a5ba6d commit 4df300d
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 67 deletions.
9 changes: 8 additions & 1 deletion packages/clients/walkerjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function Walkerjs(
const state = getState(customConfig);
const instance: WebClient.Instance = {
push: useHooks(push, 'Push', state.hooks),
sessionStart,
sessionStart: sessionStartExport,
client,
...state,
};
Expand Down Expand Up @@ -673,6 +673,13 @@ export function Walkerjs(
return session;
}

function sessionStartExport({
config = {},
...options
}: SessionStartOptions = {}): void | SessionData {
sessionStart({ config: { pulse: true, ...config }, ...options });
}

function setConsent(instance: WebClient.Instance, data: WalkerOS.Consent) {
const { consent, destinations, globals, user } = instance;

Expand Down
37 changes: 33 additions & 4 deletions packages/utils/src/__tests__/web/sessionStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ describe('SessionStorage', () => {
runs: 1,
};

mockStorageRead.mockImplementation((config) => {
return { ...config.data, mock: 'window' };
});

mockStorageRead
.mockReturnValue(JSON.stringify(session))
.mockReturnValueOnce(device);
Expand Down Expand Up @@ -279,4 +275,37 @@ describe('SessionStorage', () => {
runs: 1,
});
});

test('Pulsea', () => {
const start = Date.now();
const session = {
device,
isStart: true,
storage: true,
id: 'sessionId',
start,
referrer: 'org',
updated: start,
isNew: true,
count: 1,
runs: 1,
};

mockStorageRead.mockImplementation((key) => {
if (key == 'elbDeviceId') return device;
return JSON.stringify(session);
});
jest.advanceTimersByTime(1000);

const newSession = sessionStorage({ pulse: true });

expect(newSession).toStrictEqual({
...session,
device,
updated: start + 1000,
isStart: true,
isNew: true,
runs: 1,
});
});
});
137 changes: 75 additions & 62 deletions packages/utils/src/web/session/sessionStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface SessionStorageConfig extends SessionWindowConfig {
sessionStorage?: StorageType;
sessionAge?: number;
length?: number; // Minutes after last update to consider session as expired (default: 30)
pulse?: boolean;
}

export function sessionStorage(config: SessionStorageConfig = {}): SessionData {
Expand All @@ -27,6 +28,7 @@ export function sessionStorage(config: SessionStorageConfig = {}): SessionData {
const sessionKey = config.sessionKey || 'elbSessionId';
const sessionStorage = config.sessionStorage || 'local';
const sessionAge = config.sessionAge || 30; // Session age in minutes
const pulse = 'pulse' in config ? config.pulse : false; // Handle the counting
const windowSession = sessionWindow(config); // Status based on window only
let isStart = !!config.isStart;

Expand All @@ -46,68 +48,79 @@ export function sessionStorage(config: SessionStorageConfig = {}): SessionData {
)(deviceKey, deviceAge, deviceStorage);

// Check for an existing session
const existingSession: SessionData | undefined = tryCatch(
(key: string, storage?: StorageType) => {
const existingSession = JSON.parse(String(storageRead(key, storage)));

// By default it's not a new session anymore
existingSession.isNew = false;

// A new marketing entry
if (windowSession.marketing) {
Object.assign(existingSession, windowSession); // Overwrite existing session with marketing data
isStart = true; // This is a session start
}

// Check if session is still active
if (isStart || existingSession.updated + length * 60 * 1000 < now) {
// Session has expired
delete existingSession.id; // Unset session ID
delete existingSession.referrer; // Unset referrer
existingSession.start = now; // Set new session start
existingSession.count++; // Increase session count
existingSession.runs = 1; // Reset runs
isStart = true; // Mark expired session a as new one
} else {
// Session is still active
existingSession.runs++;
isStart = false;
}

existingSession.isStart = isStart; // Update session status
existingSession.updated = now; // Update session timestamp

return existingSession;
},
() => {
// Something went wrong, start a new session
config.isStart = true;
},
)(sessionKey, sessionStorage);

// Default session data
let session: SessionData = {
isStart: isStart,
storage: true,
id: getId(12),
start: now,
updated: now,
isNew: true,
count: 1,
runs: 1,
};

config.isStart = config.isStart || isStart;

// Eventually update session with id, referrer and marketing parameters
session = Object.assign(
session, // Default session values
windowSession, // Basic session data based on window
existingSession, // (Updated) existing session
{ device }, // Device Id
{ isStart: config.isStart, storage: true }, // Status of the session
config.data, // Given data has the highest priority
);
const existingSession: SessionData =
tryCatch(
(key: string, storage?: StorageType) => {
const existingSession = JSON.parse(String(storageRead(key, storage)));

// Only update session if it's not a pulse check
if (pulse) return existingSession;

// By default it's not a new session anymore
existingSession.isNew = false;

// A new marketing entry
if (windowSession.marketing) {
Object.assign(existingSession, windowSession); // Overwrite existing session with marketing data
isStart = true; // This is a session start
}

// Check if session is still active
if (isStart || existingSession.updated + length * 60 * 1000 < now) {
// Session has expired
delete existingSession.id; // Unset session ID
delete existingSession.referrer; // Unset referrer
existingSession.start = now; // Set new session start
existingSession.count++; // Increase session count
existingSession.runs = 1; // Reset runs
isStart = true; // Mark expired session a as new one
} else {
// Session is still active
existingSession.runs++;
isStart = false;
}

// Update session status
existingSession.isStart = isStart;

return existingSession;
},
() => {
// Something went wrong, start a new session
config.isStart = true;
},
)(sessionKey, sessionStorage) || {};

// Update session timestamp
existingSession.updated = now;

let session: SessionData = existingSession;

if (!pulse) {
// Default session data
session = {
isStart: isStart,
storage: true,
id: getId(12),
start: now,
updated: now,
isNew: true,
count: 1,
runs: 1,
};

config.isStart = config.isStart || isStart;

// Eventually update session with id, referrer and marketing parameters
session = Object.assign(
session, // Default session values
windowSession, // Basic session data based on window
existingSession, // (Updated) existing session
{ device }, // Device Id
{ isStart: config.isStart, storage: true }, // Status of the session
config.data, // Given data has the highest priority
);
}

// Write (updated) session to storage
storageWrite(sessionKey, JSON.stringify(session), sessionAge, sessionStorage);
Expand Down

0 comments on commit 4df300d

Please sign in to comment.