Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 09d9433

Browse files
mfahadahmedaliabbasrizvi
authored andcommitted
feat(api): Decision Notification Listener for isFeatureEnabled and getEnabledFeatures APIs. (optimizely#245)
1 parent b9a9fd0 commit 09d9433

File tree

5 files changed

+377
-36
lines changed

5 files changed

+377
-36
lines changed

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,7 @@ DecisionService.prototype.getVariationForFeature = function(feature, userId, att
303303
}
304304

305305
this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key));
306-
307-
return {
308-
experiment: null,
309-
variation: null,
310-
decisionSource: null,
311-
};
306+
return rolloutDecision;
312307
};
313308

314309
DecisionService.prototype._getVariationForFeatureExperiment = function(feature, userId, attributes) {

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -843,12 +843,12 @@ describe('lib/core/decision_service', function() {
843843
getVariationStub.returns(null);
844844
});
845845

846-
it('returns a decision with no variation', function() {
846+
it('returns a decision with no variation and source rollout', function() {
847847
var decision = decisionServiceInstance.getVariationForFeature(feature, 'user1');
848848
var expectedDecision = {
849849
experiment: null,
850850
variation: null,
851-
decisionSource: null,
851+
decisionSource: DECISION_SOURCES.ROLLOUT,
852852
};
853853
assert.deepEqual(decision, expectedDecision);
854854
sinon.assert.calledWithExactly(mockLogger.log, LOG_LEVEL.DEBUG, 'DECISION_SERVICE: User user1 is not in any experiment on the feature test_feature_for_experiment.');
@@ -915,12 +915,12 @@ describe('lib/core/decision_service', function() {
915915
getVariationStub.returns(null);
916916
});
917917

918-
it('returns a decision with no experiment and no variation', function() {
918+
it('returns a decision with no experiment, no variation and source rollout', function() {
919919
var decision = decisionServiceInstance.getVariationForFeature(feature, 'user1');
920920
var expectedDecision = {
921921
experiment: null,
922922
variation: null,
923-
decisionSource: null,
923+
decisionSource: DECISION_SOURCES.ROLLOUT,
924924
};
925925
assert.deepEqual(decision, expectedDecision);
926926
sinon.assert.calledWithExactly(mockLogger.log, LOG_LEVEL.DEBUG, 'DECISION_SERVICE: User user1 is not in any experiment on the feature feature_with_group.');
@@ -932,7 +932,7 @@ describe('lib/core/decision_service', function() {
932932
var expectedDecision = {
933933
experiment: null,
934934
variation: null,
935-
decisionSource: null,
935+
decisionSource: DECISION_SOURCES.ROLLOUT,
936936
};
937937
assert.deepEqual(decision, expectedDecision);
938938
sinon.assert.calledWithExactly(mockLogger.log, LOG_LEVEL.DEBUG, 'DECISION_SERVICE: User user1 is not in any experiment on the feature feature_exp_no_traffic.');
@@ -946,12 +946,12 @@ describe('lib/core/decision_service', function() {
946946
bucketUserIntoExperimentStub.returns(null);
947947
});
948948

949-
it('returns a decision with no experiment and no variation', function() {
949+
it('returns a decision with no experiment, no variation and source rollout', function() {
950950
var decision = decisionServiceInstance.getVariationForFeature(feature, 'user1');
951951
var expectedDecision = {
952952
experiment: null,
953953
variation: null,
954-
decisionSource: null,
954+
decisionSource: DECISION_SOURCES.ROLLOUT,
955955
};
956956
assert.deepEqual(decision, expectedDecision);
957957
sinon.assert.calledWithExactly(mockLogger.log, LOG_LEVEL.DEBUG, 'DECISION_SERVICE: User user1 is not in any experiment on the feature feature_with_group.');
@@ -1168,12 +1168,12 @@ describe('lib/core/decision_service', function() {
11681168
bucketStub.returns(null);
11691169
});
11701170

1171-
it('returns a decision with no variation and no experiment', function() {
1171+
it('returns a decision with no variation, no experiment and source rollout', function() {
11721172
var decision = decisionServiceInstance.getVariationForFeature(feature, 'user1');
11731173
var expectedDecision = {
11741174
experiment: null,
11751175
variation: null,
1176-
decisionSource: null,
1176+
decisionSource: DECISION_SOURCES.ROLLOUT,
11771177
};
11781178
assert.deepEqual(decision, expectedDecision);
11791179
sinon.assert.calledWithExactly(mockLogger.log, LOG_LEVEL.DEBUG, 'DECISION_SERVICE: User user1 does not meet conditions for targeting rule 1.');
@@ -1378,12 +1378,12 @@ describe('lib/core/decision_service', function() {
13781378
feature = configObj.featureKeyMap.unused_flag;
13791379
});
13801380

1381-
it('returns a decision with no variation and no experiment', function() {
1381+
it('returns a decision with no variation, no experiment and source rollout', function() {
13821382
var decision = decisionServiceInstance.getVariationForFeature(feature, 'user1');
13831383
var expectedDecision = {
13841384
experiment: null,
13851385
variation: null,
1386-
decisionSource: null,
1386+
decisionSource: DECISION_SOURCES.ROLLOUT,
13871387
};
13881388
var expectedDecision = assert.deepEqual(decision, expectedDecision);
13891389
sinon.assert.calledWithExactly(mockLogger.log, LOG_LEVEL.DEBUG, 'DECISION_SERVICE: Feature unused_flag is not attached to any experiments.');

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

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -502,26 +502,46 @@ Optimizely.prototype.isFeatureEnabled = function(featureKey, userId, attributes)
502502
return false;
503503
}
504504

505+
var featureEnabled = false;
506+
var experimentKey = null;
507+
var variationKey = null;
505508
var decision = this.decisionService.getVariationForFeature(feature, userId, attributes);
506509
var variation = decision.variation;
510+
507511
if (!!variation) {
512+
featureEnabled = variation.featureEnabled;
508513
if (decision.decisionSource === DECISION_SOURCES.EXPERIMENT) {
514+
experimentKey = decision.experiment.key;
515+
variationKey = decision.variation.key;
509516
// got a variation from the exp, so we track the impression
510517
this._sendImpressionEvent(decision.experiment.key, decision.variation.key, userId, attributes);
511518
}
512-
if (variation.featureEnabled === true) {
513-
this.logger.log(
514-
LOG_LEVEL.INFO,
515-
sprintf(LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId)
516-
);
517-
return true;
518-
}
519519
}
520-
this.logger.log(
521-
LOG_LEVEL.INFO,
522-
sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId)
520+
521+
if (featureEnabled === true) {
522+
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId));
523+
} else {
524+
this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId));
525+
featureEnabled = false;
526+
}
527+
528+
this.notificationCenter.sendNotifications(
529+
enums.NOTIFICATION_TYPES.DECISION,
530+
{
531+
type: DECISION_INFO_TYPES.FEATURE,
532+
userId: userId,
533+
attributes: attributes || {},
534+
decisionInfo: {
535+
featureKey: featureKey,
536+
featureEnabled: featureEnabled,
537+
source: decision.decisionSource,
538+
sourceExperimentKey: experimentKey,
539+
sourceVariationKey: variationKey,
540+
}
541+
}
523542
);
524-
return false;
543+
544+
return featureEnabled;
525545
} catch (e) {
526546
this.logger.log(LOG_LEVEL.ERROR, e.message);
527547
this.errorHandler.handleError(e);

0 commit comments

Comments
 (0)