Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run project config parse inside web worker #794

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,33 @@
import { tryCreatingProjectConfig } from '.';

const messageListener = (e: MessageEvent<{ type: string; payload: { datafile: string | object } }>) => {
if (e.data.type === 'START_PARSE_DATAFILE') {
const { configObj, error } = tryCreatingProjectConfig({
datafile: e.data.payload.datafile,
logger: {
log: (...args) => {
console.log(...args);
},
},
});

if (error) {
postMessage({
type: 'DATAFILE_PARSE_ERROR',
payload: {
error: error.message,
parsedDatafile: null
}
})
} else {
postMessage({
type: 'DATAFILE_PARSE_SUCCESS',
payload: {
parsedDatafile: configObj
}
})
}
}
};

addEventListener('message', messageListener);
Expand Up @@ -18,11 +18,7 @@ import { sprintf } from '../../utils/fns';

import { ERROR_MESSAGES } from '../../utils/enums';
import { createOptimizelyConfig } from '../optimizely_config';
import {
OnReadyResult,
OptimizelyConfig,
DatafileManager,
} from '../../shared_types';
import { OnReadyResult, OptimizelyConfig, DatafileManager } from '../../shared_types';
import { ProjectConfig, toDatafile, tryCreatingProjectConfig } from '../project_config';

const logger = getLogger();
Expand All @@ -31,12 +27,13 @@ const MODULE_NAME = 'PROJECT_CONFIG_MANAGER';
interface ProjectConfigManagerConfig {
// TODO[OASIS-6649]: Don't use object type
// eslint-disable-next-line @typescript-eslint/ban-types
datafile?: string | object,
datafile?: string | object;
jsonSchemaValidator?: {
validate(jsonObject: unknown): boolean,
validate(jsonObject: unknown): boolean;
};
sdkKey?: string,
datafileManager?: DatafileManager
sdkKey?: string;
datafileManager?: DatafileManager;
useWebWorker?: boolean;
}

/**
Expand Down Expand Up @@ -74,7 +71,9 @@ export class ProjectConfigManager {
this.jsonSchemaValidator = config.jsonSchemaValidator;

if (!config.datafile && !config.sdkKey) {
const datafileAndSdkKeyMissingError = new Error(sprintf(ERROR_MESSAGES.DATAFILE_AND_SDK_KEY_MISSING, MODULE_NAME));
const datafileAndSdkKeyMissingError = new Error(
sprintf(ERROR_MESSAGES.DATAFILE_AND_SDK_KEY_MISSING, MODULE_NAME)
);
this.readyPromise = Promise.resolve({
success: false,
reason: getErrorMessage(datafileAndSdkKeyMissingError),
Expand All @@ -85,10 +84,14 @@ export class ProjectConfigManager {

let handleNewDatafileException = null;
if (config.datafile) {
handleNewDatafileException = this.handleNewDatafile(config.datafile);
if (config.useWebWorker) {
this.readyPromise = this.handleDatafileInWebWorker(config.datafile);
} else {
handleNewDatafileException = this.handleNewDatafile(config.datafile);
}
}

if (config.sdkKey && config.datafileManager) {
if (config.sdkKey && config.datafileManager) {
this.datafileManager = config.datafileManager;
this.datafileManager.start();
this.readyPromise = this.datafileManager
Expand All @@ -105,7 +108,7 @@ export class ProjectConfigManager {
reason: getErrorMessage(handleNewDatafileException, 'Invalid datafile'),
});
}
} catch (ex: any) {
} catch (ex) {
logger.error(ex);
this.readyPromise = Promise.resolve({
success: false,
Expand Down Expand Up @@ -137,7 +140,7 @@ export class ProjectConfigManager {
return {
success: false,
reason: getErrorMessage(null, 'Datafile manager is not provided'),
}
};
}

/**
Expand Down Expand Up @@ -180,7 +183,7 @@ export class ProjectConfigManager {
const { configObj, error } = tryCreatingProjectConfig({
datafile: newDatafile,
jsonSchemaValidator: this.jsonSchemaValidator,
logger: logger
logger: logger,
});

if (error) {
Expand All @@ -197,6 +200,41 @@ export class ProjectConfigManager {
return error;
}

private async handleDatafileInWebWorker(newDatafile: string | object): Promise<OnReadyResult> {
const workerCode = '';
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be handled by some loader inside rollup; like this one: https://www.npmjs.com/package/rollup-plugin-web-worker-loader

const workerBlob = new Blob([workerCode]);
const workerUrl = URL.createObjectURL(workerBlob);
const worker = new Worker(workerUrl);

return new Promise((resolve, reject) => {
worker.onmessage = (
e: MessageEvent<{ type: string; payload: { parsedDatafile: ProjectConfig | null; error?: string } }>
) => {
if (e.data.type === 'DATAFILE_PARSE_SUCCESS') {
this.configObj = e.data.payload.parsedDatafile;

resolve({
success: true,
});
}

if (e.data.type === 'DATAFILE_PARSE_ERROR') {
reject({
success: false,
reason: e.data.payload.error,
});
}
};

worker.postMessage({
type: 'START_PARSE_DATAFILE',
payload: {
datafile: newDatafile,
},
});
});
}

/**
* Returns the current project config object, or null if no project config object
* is available
Expand Down Expand Up @@ -248,7 +286,7 @@ export class ProjectConfigManager {
* @param {Function} listener
* @return {Function}
*/
onUpdate(listener: (config: ProjectConfig) => void): (() => void) {
onUpdate(listener: (config: ProjectConfig) => void): () => void {
this.updateListeners.push(listener);
return () => {
const index = this.updateListeners.indexOf(listener);
Expand Down