Skip to content

Commit c987725

Browse files
authored
feat (datafile management): Implement automatic updates, datafile manager options, and stopping datafile manager (#15)
Summary: - Refactor project config management into a ProjectConfigManager class, which uses DatafileManager internally - Update Optimizely to get project config by calling projectConfigManager.getConfig() instead of keeping its own reference to a project config object - Pass through datafileOptions to project config manager (allowing use of autoUpdate and updateInterval) - Add notification center event for new project config - Add an update listener to datafile manager that sends project config update notification - Call this.datafileManager.stop in close method - Add default timeout to onReady method - Update behavior of onReady to reject early when datafile manager emits invalid datafile Test plan: Unit tests Issues: https://optimizely.atlassian.net/browse/OASIS-4385 https://optimizely.atlassian.net/browse/OASIS-4386 https://optimizely.atlassian.net/browse/OASIS-4387
1 parent b53d102 commit c987725

File tree

7 files changed

+833
-578
lines changed

7 files changed

+833
-578
lines changed

packages/optimizely-sdk/lib/core/project_config/index.js

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -600,32 +600,22 @@ module.exports = {
600600
/**
601601
* Try to create a project config object from the given datafile and
602602
* configuration properties.
603-
* If successful, return the project config object, otherwise return null.
603+
* If successful, return the project config object, otherwise throws an error
604604
* @param {Object} config
605605
* @param {Object} config.datafile
606-
* @param {Object} config.errorHandler
607606
* @param {Object} config.jsonSchemaValidator
608607
* @param {Object} config.logger
609608
* @param {Object} config.skipJSONValidation
610-
* @return {Object|null} Project config object if datafile was valid, otherwise null
609+
* @return {Object} Project config object
611610
*/
612611
tryCreatingProjectConfig: function(config) {
613-
var configObj = null;
614-
try {
615-
configValidator.validateDatafile(config.datafile);
616-
if (config.skipJSONValidation === true) {
617-
configObj = module.exports.createProjectConfig(config.datafile);
618-
config.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME));
619-
} else if (!config.jsonSchemaValidator) {
620-
configObj = module.exports.createProjectConfig(config.datafile);
621-
} else if (config.jsonSchemaValidator.validate(projectConfigSchema, config.datafile)) {
622-
configObj = module.exports.createProjectConfig(config.datafile);
623-
config.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME));
624-
}
625-
} catch (ex) {
626-
config.logger.log(LOG_LEVEL.ERROR, ex.message);
627-
config.errorHandler.handleError(ex);
612+
configValidator.validateDatafile(config.datafile);
613+
if (config.skipJSONValidation === true) {
614+
config.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME));
615+
} else if (config.jsonSchemaValidator) {
616+
config.jsonSchemaValidator.validate(projectConfigSchema, config.datafile);
617+
config.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME));
628618
}
629-
return configObj;
630-
}
619+
return module.exports.createProjectConfig(config.datafile);
620+
},
631621
};

packages/optimizely-sdk/lib/core/project_config/index.tests.js

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ var projectConfig = require('./');
1717
var enums = require('../../utils/enums');
1818
var testDatafile = require('../../tests/test_data');
1919
var configValidator = require('../../utils/config_validator');
20+
var logging = require('@optimizely/js-sdk-logging');
21+
22+
var logger = logging.getLogger();
2023

2124
var _ = require('lodash/core');
2225
var fns = require('../../utils/fns');
2326
var chai = require('chai');
2427
var assert = chai.assert;
25-
var logger = require('../../plugins/logger');
28+
var loggerPlugin = require('../../plugins/logger');
2629
var sinon = require('sinon');
2730
var sprintf = require('@optimizely/js-sdk-utils').sprintf;
2831

@@ -224,7 +227,7 @@ describe('lib/core/project_config', function() {
224227
describe('projectConfig helper methods', function() {
225228
var testData = testDatafile.getTestProjectConfig();
226229
var configObj;
227-
var createdLogger = logger.createLogger({logLevel: LOG_LEVEL.INFO});
230+
var createdLogger = loggerPlugin.createLogger({logLevel: LOG_LEVEL.INFO});
228231

229232
beforeEach(function() {
230233
configObj = projectConfig.createProjectConfig(testData);
@@ -351,7 +354,7 @@ describe('lib/core/project_config', function() {
351354
});
352355

353356
describe('feature management', function() {
354-
var featureManagementLogger = logger.createLogger({logLevel: LOG_LEVEL.INFO});
357+
var featureManagementLogger = loggerPlugin.createLogger({logLevel: LOG_LEVEL.INFO});
355358
beforeEach(function() {
356359
configObj = projectConfig.createProjectConfig(testDatafile.getTestProjectConfigWithFeatures());
357360
sinon.stub(featureManagementLogger, 'log');
@@ -559,7 +562,7 @@ describe('lib/core/project_config', function() {
559562
});
560563

561564
describe('#getForcedVariation', function() {
562-
var createdLogger = logger.createLogger({
565+
var createdLogger = loggerPlugin.createLogger({
563566
logLevel: LOG_LEVEL.INFO,
564567
logToConsole: false,
565568
});
@@ -582,7 +585,7 @@ describe('lib/core/project_config', function() {
582585
});
583586

584587
describe('#setForcedVariation', function() {
585-
var createdLogger = logger.createLogger({
588+
var createdLogger = loggerPlugin.createLogger({
586589
logLevel: LOG_LEVEL.INFO,
587590
logToConsole: false,
588591
});
@@ -730,26 +733,20 @@ describe('lib/core/project_config', function() {
730733
});
731734

732735
describe('#tryCreatingProjectConfig', function() {
733-
var stubErrorHandler;
734736
var stubJsonSchemaValidator;
735-
var stubLogger;
736737
beforeEach(function() {
737-
stubErrorHandler = {
738-
handleError: sinon.stub(),
739-
};
740738
stubJsonSchemaValidator = {
741739
validate: sinon.stub().returns(true),
742740
};
743-
stubLogger = {
744-
log: sinon.stub(),
745-
};
746741
sinon.stub(projectConfig, 'createProjectConfig').returns({});
747742
sinon.stub(configValidator, 'validateDatafile').returns(true);
743+
sinon.spy(logger, 'error');
748744
});
749745

750746
afterEach(function() {
751747
projectConfig.createProjectConfig.restore();
752748
configValidator.validateDatafile.restore();
749+
logger.error.restore();
753750
});
754751

755752
it('returns a project config object created by createProjectConfig when all validation is applied and there are no errors', function() {
@@ -765,61 +762,44 @@ describe('lib/core/project_config', function() {
765762
projectConfig.createProjectConfig.returns(configObj);
766763
var result = projectConfig.tryCreatingProjectConfig({
767764
datafile: { foo: 'bar' },
768-
errorHandler: stubErrorHandler,
769765
jsonSchemaValidator: stubJsonSchemaValidator,
770-
logger: stubLogger,
766+
logger: logger,
771767
skipJSONValidation: false,
772768
});
773769
assert.deepEqual(result, configObj);
774770
});
775771

776-
it('returns null and calls handleError when validateDatafile throws', function() {
772+
it('throws an error when validateDatafile throws', function() {
777773
configValidator.validateDatafile.throws();
778774
stubJsonSchemaValidator.validate.returns(true);
779-
var result = projectConfig.tryCreatingProjectConfig({
780-
datafile: { foo: 'bar' },
781-
errorHandler: stubErrorHandler,
782-
jsonSchemaValidator: stubJsonSchemaValidator,
783-
logger: stubLogger,
784-
skipJSONValidation: false,
775+
assert.throws(function() {
776+
projectConfig.tryCreatingProjectConfig({
777+
datafile: { foo: 'bar' },
778+
jsonSchemaValidator: stubJsonSchemaValidator,
779+
logger: logger,
780+
skipJSONValidation: false,
781+
});
785782
});
786-
assert.strictEqual(result, null);
787-
sinon.assert.calledOnce(stubErrorHandler.handleError);
788783
});
789784

790-
it('returns null and calls handleError when jsonSchemaValidator.validate throws', function() {
785+
it('throws an error when jsonSchemaValidator.validate throws', function() {
791786
configValidator.validateDatafile.returns(true);
792787
stubJsonSchemaValidator.validate.throws();
793-
var result = projectConfig.tryCreatingProjectConfig({
794-
datafile: { foo: 'bar' },
795-
errorHandler: stubErrorHandler,
796-
jsonSchemaValidator: stubJsonSchemaValidator,
797-
logger: stubLogger,
798-
skipJSONValidation: false,
799-
});
800-
assert.strictEqual(result, null);
801-
sinon.assert.calledOnce(stubErrorHandler.handleError);
802-
});
803-
804-
it('returns null when jsonSchemaValidator.validate returns false', function() {
805-
configValidator.validateDatafile.returns(true);
806-
stubJsonSchemaValidator.validate.returns(false);
807-
var result = projectConfig.tryCreatingProjectConfig({
808-
datafile: { foo: 'bar' },
809-
errorHandler: stubErrorHandler,
810-
jsonSchemaValidator: stubJsonSchemaValidator,
811-
logger: stubLogger,
812-
skipJSONValidation: false,
788+
assert.throws(function() {
789+
var result = projectConfig.tryCreatingProjectConfig({
790+
datafile: { foo: 'bar' },
791+
jsonSchemaValidator: stubJsonSchemaValidator,
792+
logger: logger,
793+
skipJSONValidation: false,
794+
});
813795
});
814-
assert.strictEqual(result, null);
815796
});
816797

817798
it('does not call jsonSchemaValidator.validate when skipJSONValidation is true', function() {
818799
projectConfig.tryCreatingProjectConfig({
819800
datafile: { foo: 'bar' },
820-
errorHandler: stubErrorHandler,
821801
jsonSchemaValidator: stubJsonSchemaValidator,
822-
logger: stubLogger,
802+
logger: logger,
823803
skipJSONValidation: true,
824804
});
825805
sinon.assert.notCalled(stubJsonSchemaValidator.validate);
@@ -837,11 +817,10 @@ describe('lib/core/project_config', function() {
837817
projectConfig.createProjectConfig.returns(configObj);
838818
var result = projectConfig.tryCreatingProjectConfig({
839819
datafile: { foo: 'bar' },
840-
errorHandler: stubErrorHandler,
841-
logger: stubLogger,
820+
logger: logger,
842821
});
843822
assert.deepEqual(result, configObj);
844-
sinon.assert.notCalled(stubErrorHandler.handleError);
823+
sinon.assert.notCalled(logger.error);
845824
});
846825
});
847826
});

0 commit comments

Comments
 (0)