Skip to content

feat(api): OnDecision Notification Listener #240

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

Closed
wants to merge 10 commits into from
20 changes: 10 additions & 10 deletions packages/optimizely-sdk/lib/core/decision_service/index.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -729,22 +729,22 @@ describe('lib/core/decision_service', function() {
'variables': [
{
'id': '4792309476491264',
'value': '10'
'value': '40'
Copy link
Contributor

Choose a reason for hiding this comment

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

If we are making any change in the existing datafile, please add comments in the PR, why we changed it. Otherwise difficult for reviewers

Copy link
Contributor

Choose a reason for hiding this comment

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

same for all where you changed true, Buy me Later

},
{
'id': '5073784453201920',
'value': 'false'
'value': 'true'
},
{
'id': '5636734406623232',
'value': 'Buy me'
'value': 'Buy me Later'
},
{
'id': '6199684360044544',
'value': '50.55'
'value': '99.99'
}
],
'featureEnabled': true,
'featureEnabled': false,
'key': 'control'
}
],
Expand All @@ -760,22 +760,22 @@ describe('lib/core/decision_service', function() {
'variables': [
{
'id': '4792309476491264',
'value': '10'
'value': '40'
},
{
'id': '5073784453201920',
'value': 'false'
'value': 'true'
},
{
'id': '5636734406623232',
'value': 'Buy me'
'value': 'Buy me Later'
},
{
'id': '6199684360044544',
'value': '50.55'
'value': '99.99'
}
],
'featureEnabled': true,
'featureEnabled': false,
'key': 'control'
},
variation: {
Expand Down
89 changes: 77 additions & 12 deletions packages/optimizely-sdk/lib/optimizely/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var LOG_MESSAGES = enums.LOG_MESSAGES;
var MODULE_NAME = 'OPTIMIZELY';
var DECISION_SOURCES = enums.DECISION_SOURCES;
var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES;
var DECISION_INFO_TYPES = enums.DECISION_INFO_TYPES;
Copy link
Contributor

Choose a reason for hiding this comment

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

@jordangarcia shouldn't it be DECISION_TYPES?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think DECISION_INFO_TYPES is fine. It was confusing before when it was DECISION_NOTIFICATION_TYPES


/**
* The Optimizely class
Expand Down Expand Up @@ -304,7 +305,21 @@ Optimizely.prototype.getVariation = function(experimentKey, userId, attributes)
return null;
}

return this.decisionService.getVariation(experimentKey, userId, attributes);
var variationKey = this.decisionService.getVariation(experimentKey, userId, attributes);
this.notificationCenter.sendNotifications(
enums.NOTIFICATION_TYPES.ON_DECISION,
{
type: DECISION_INFO_TYPES.EXPERIMENT,
userId: userId,
attributes: attributes,
decisionInfo: {
experimentKey: experimentKey,
variationKey: variationKey,
}
}
);

return variationKey;
} catch (ex) {
this.logger.log(LOG_LEVEL.ERROR, ex.message);
this.errorHandler.handleError(ex);
Expand Down Expand Up @@ -463,20 +478,43 @@ Optimizely.prototype.isFeatureEnabled = function (featureKey, userId, attributes
return false;
}

var featureEnabled = false;
var decision = this.decisionService.getVariationForFeature(feature, userId, attributes);
var variation = decision.variation;

if (!!variation) {
featureEnabled = variation.featureEnabled;
if (decision.decisionSource === DECISION_SOURCES.EXPERIMENT) {
// got a variation from the exp, so we track the impression
this._sendImpressionEvent(decision.experiment.key, decision.variation.key, userId, attributes);
}
if (variation.featureEnabled === true) {
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId));
return true;
}
}
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId));
return false;

if (!featureEnabled) {
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId));
featureEnabled = false;
} else {
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId));
}

var decisionSource = decision.decisionSource || DECISION_SOURCES.ROLLOUT;
var experimentKey = decisionSource === DECISION_SOURCES.EXPERIMENT ? decision.experiment.key : null;
this.notificationCenter.sendNotifications(
enums.NOTIFICATION_TYPES.ON_DECISION,
{
type: DECISION_INFO_TYPES.FEATURE,
userId: userId,
attributes: attributes,
decisionInfo: {
featureKey: featureKey,
featureEnabled: featureEnabled,
source: decisionSource,
sourceExperimentKey: experimentKey
}
}
);

return featureEnabled;
} catch (e) {
this.logger.log(LOG_LEVEL.ERROR, e.message);
this.errorHandler.handleError(e);
Expand Down Expand Up @@ -563,17 +601,44 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK
return null;
}

var featureEnabled = false;
var variableValue = variable.defaultValue;
var decision = this.decisionService.getVariationForFeature(featureFlag, userId, attributes);
var variableValue;

if (decision.variation !== null) {
variableValue = projectConfig.getVariableValueForVariation(this.configObj, variable, decision.variation, this.logger);
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId));
featureEnabled = decision.variation.featureEnabled;
if (featureEnabled) {
variableValue = projectConfig.getVariableValueForVariation(this.configObj, variable, decision.variation, this.logger);
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId));
} else {
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, featureFlag.key, userId, variableKey));
}
} else {
variableValue = variable.defaultValue;
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, variableKey, featureFlag.key));
}

return projectConfig.getTypeCastValue(variableValue, variableType, this.logger);
var decisionSource = decision.decisionSource || DECISION_SOURCES.ROLLOUT;
var experimentKey = decisionSource === DECISION_SOURCES.EXPERIMENT ? decision.experiment.key : null;
var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger);

this.notificationCenter.sendNotifications(
enums.NOTIFICATION_TYPES.ON_DECISION,
{
type: DECISION_INFO_TYPES.FEATURE_VARIABLE,
userId: userId,
attributes: attributes,
decisionInfo: {
featureKey: featureKey,
featureEnabled: featureEnabled,
variableKey: variableKey,
variableValue: typeCastedValue,
variableType: variableType,
source: decisionSource,
sourceExperimentKey: experimentKey
}
}
);
return typeCastedValue;
};

/**
Expand Down
Loading