Skip to content

Commit

Permalink
Use Vitest worker import for event beacon in player
Browse files Browse the repository at this point in the history
  • Loading branch information
enjikaka committed Jan 22, 2024
1 parent e9130f4 commit 735c7ce
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 159 deletions.
16 changes: 3 additions & 13 deletions packages/player/src/internal/beacon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,8 @@ import { credentialsProviderStore } from '../index';
import { trueTime } from '../true-time';

import type { CommitData, PrematureEvents } from './types';
/**
* Generates a Web Worker from a function.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
export function workerize(method: Function) {
const functionBody = `(${method.toString()})();`;
const workerBlob = new Blob([functionBody], { type: 'text/javascript' });

return URL.createObjectURL(workerBlob);
}
// @ts-expect-error Vite Worker import style
import BeaconWorker from './worker?worker&inline';

export let worker: Worker;

Expand All @@ -38,9 +30,7 @@ async function handleWorkerMessage(
*/
export async function start() {
if (!worker) {
const { beacon } = await import('./worker');

worker = new Worker(workerize(beacon));
worker = new BeaconWorker();

worker.addEventListener('message', event => {
handleWorkerMessage(event);
Expand Down
290 changes: 144 additions & 146 deletions packages/player/src/internal/beacon/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,168 +34,166 @@ type Sessions = {
userId: number;
};

export function beacon() {
let queue: Array<BeaconEvent> = [];
let accessToken: string | undefined;
let clientId: string | undefined;
let clientPlatform: string | undefined;
let eventUrl: string | undefined;
const userSessions = new Map<string, Sessions>();

function generateGUID(): string {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/restrict-plus-operands
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(
c ^
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
).toString(16),
);
let queue: Array<BeaconEvent> = [];
let accessToken: string | undefined;
let clientId: string | undefined;
let clientPlatform: string | undefined;
let eventUrl: string | undefined;
const userSessions = new Map<string, Sessions>();

function generateGUID(): string {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/restrict-plus-operands
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(
c ^
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
).toString(16),
);
}

async function fetchUserSession(apiUrl: string, _accessToken: string) {
// If accessToken is still the same, the clientId and userId we use and store is still the same.
if (userSessions.has(_accessToken)) {
return userSessions.get(_accessToken);
}

async function fetchUserSession(apiUrl: string, _accessToken: string) {
// If accessToken is still the same, the clientId and userId we use and store is still the same.
if (userSessions.has(_accessToken)) {
return userSessions.get(_accessToken);
}
// Clear any old sessions
userSessions.clear();

// Clear any old sessions
userSessions.clear();
const response = await fetch(apiUrl + '/sessions', {
headers: new Headers({
Authorization: 'Bearer ' + _accessToken,
}),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - It is a thing.
importance: 'low',
});

const response = await fetch(apiUrl + '/sessions', {
headers: new Headers({
Authorization: 'Bearer ' + _accessToken,
}),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - It is a thing.
importance: 'low',
});
// eslint-disable-next-line require-atomic-updates
const session = (await response.json()) as Sessions;

// eslint-disable-next-line require-atomic-updates
const session = (await response.json()) as Sessions;
userSessions.set(_accessToken, session);

userSessions.set(_accessToken, session);
return session;
}

return session;
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
setInterval(async () => {
if (queue.length > 0 && accessToken && eventUrl) {
const batch: Batch = {
batchId: generateGUID(),
events: [...queue],
};

// eslint-disable-next-line @typescript-eslint/no-misused-promises
setInterval(async () => {
if (queue.length > 0 && accessToken && eventUrl) {
const batch: Batch = {
batchId: generateGUID(),
events: [...queue],
};

try {
const headers = new Headers();

if (accessToken) {
headers.append('authorization', 'Bearer ' + accessToken);
}

if (clientId) {
headers.append('x-tidal-token', clientId);
}

// headers.append('x-requested-with', 'player-sdk');
headers.append('content-type', 'application/json; boundary=player-sdk');

const response = await fetch(eventUrl, {
body: JSON.stringify(batch),
headers,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - It is a thing.
importance: 'low',
method: 'POST',
});
try {
const headers = new Headers();

if (accessToken) {
headers.append('authorization', 'Bearer ' + accessToken);
}

if (response.ok) {
queue.forEach(event => {
if ('streamingSessionId' in event.payload) {
postMessage({
command: 'cleanUp',
eventName: event.name,
streamingSessionId: event.payload.streamingSessionId,
});
} else {
// progress event is handled before send due to streamingSessionId missing here.
}
});
// eslint-disable-next-line require-atomic-updates
queue = [];
} else {
throw new Error('Response not ok');
}
} catch (e) {
console.warn(e);
if (clientId) {
headers.append('x-tidal-token', clientId);
}

// headers.append('x-requested-with', 'player-sdk');
headers.append('content-type', 'application/json; boundary=player-sdk');

const response = await fetch(eventUrl, {
body: JSON.stringify(batch),
headers,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - It is a thing.
importance: 'low',
method: 'POST',
});

if (response.ok) {
queue.forEach(event => {
if ('streamingSessionId' in event.payload) {
postMessage({
command: 'cleanUp',
eventName: event.name,
streamingSessionId: event.payload.streamingSessionId,
});
} else {
// progress event is handled before send due to streamingSessionId missing here.
}
});
// eslint-disable-next-line require-atomic-updates
queue = [];
} else {
throw new Error('Response not ok');
}
} catch (e) {
console.warn(e);
}
}, 15000);
}
}, 15000);

onmessage = async e => {
const data = JSON.parse((e as MessageEvent<string>).data) as CommitData;
onmessage = async e => {
const data = JSON.parse((e as MessageEvent<string>).data) as CommitData;

eventUrl = data.eventUrl;
const userSession = await fetchUserSession(data.apiUrl, data.accessToken);
eventUrl = data.eventUrl;
const userSession = await fetchUserSession(data.apiUrl, data.accessToken);

if (data.accessToken) {
accessToken = data.accessToken;
}
if (data.accessToken) {
accessToken = data.accessToken;
}

if (!accessToken) {
// eslint-disable-next-line no-console
console.trace(
'An accessToken is missing. Make sure to send at least one commit-payload with it defined, we cannot send events unless we have an access token.',
);
}
if (!accessToken) {
// eslint-disable-next-line no-console
console.trace(
'An accessToken is missing. Make sure to send at least one commit-payload with it defined, we cannot send events unless we have an access token.',
);
}

if (data.clientId) {
clientId = data.clientId;
}
if (data.clientId) {
clientId = data.clientId;
}

if (data.clientPlatform) {
clientPlatform = data.clientPlatform;
}
if (data.clientPlatform) {
clientPlatform = data.clientPlatform;
}

// Ensured to be awaited and undefined filtered out before we get to the worker
const events = data.events as Array<PrematureEvents>;

events.forEach(streamingEvent => {
// streamingSessionId not allowed in the progress event
if (
streamingEvent.name === 'progress' &&
'streamingSessionId' in streamingEvent.payload
) {
postMessage({
command: 'cleanUp',
eventName: streamingEvent.name,
streamingSessionId: streamingEvent.payload.streamingSessionId,
});
delete streamingEvent.payload.streamingSessionId;
}
// Ensured to be awaited and undefined filtered out before we get to the worker
const events = data.events as Array<PrematureEvents>;

events.forEach(streamingEvent => {
// streamingSessionId not allowed in the progress event
if (
streamingEvent.name === 'progress' &&
'streamingSessionId' in streamingEvent.payload
) {
postMessage({
command: 'cleanUp',
eventName: streamingEvent.name,
streamingSessionId: streamingEvent.payload.streamingSessionId,
});
delete streamingEvent.payload.streamingSessionId;
}

const event = {
client: {
platform: clientPlatform,
token: clientId,
version: data.appVersion,
},
group: data.type,
name: streamingEvent.name,
payload: streamingEvent.payload,
ts: data.ts,
user: {
accessToken,
clientId: userSession?.client.id,
id: userSession?.userId,
},
uuid: generateGUID(),
version: data.type === 'playback' ? 1 : 2,
} as BeaconEvent;

queue.push(event);
});
};
}
const event = {
client: {
platform: clientPlatform,
token: clientId,
version: data.appVersion,
},
group: data.type,
name: streamingEvent.name,
payload: streamingEvent.payload,
ts: data.ts,
user: {
accessToken,
clientId: userSession?.client.id,
id: userSession?.userId,
},
uuid: generateGUID(),
version: data.type === 'playback' ? 1 : 2,
} as BeaconEvent;

queue.push(event);
});
};

0 comments on commit 735c7ce

Please sign in to comment.