@@ -21,6 +21,7 @@ import * as enums from '../../utils/enums';
2121import projectConfig from '../project_config' ;
2222import AudienceEvaluator from '../audience_evaluator' ;
2323import * as stringValidator from '../../utils/string_value_validator' ;
24+ import { OptimizelyDecideOptions } from '../../shared_types' ;
2425
2526var MODULE_NAME = 'DECISION_SERVICE' ;
2627var ERROR_MESSAGES = enums . ERROR_MESSAGES ;
@@ -55,14 +56,15 @@ function DecisionService(options) {
5556
5657/**
5758 * Gets variation where visitor will be bucketed.
58- * @param {Object } configObj The parsed project configuration object
59- * @param {string } experimentKey
60- * @param {string } userId
61- * @param {Object } attributes
62- * @return {Object } DecisionResonse DecisionResonse containing the variation the user is bucketed into
63- * and the decide reasons.
59+ * @param {Object } configObj The parsed project configuration object
60+ * @param {string } experimentKey
61+ * @param {string } userId
62+ * @param {Object } attributes
63+ * @param {[key: string]: boolean } options Optional map of decide options
64+ * @return {Object } DecisionResonse DecisionResonse containing the variation the user is bucketed into
65+ * and the decide reasons.
6466 */
65- DecisionService . prototype . getVariation = function ( configObj , experimentKey , userId , attributes ) {
67+ DecisionService . prototype . getVariation = function ( configObj , experimentKey , userId , attributes , options = { } ) {
6668 // by default, the bucketing ID should be the user ID
6769 var bucketingId = this . _getBucketingId ( userId , attributes ) ;
6870 var decideReasons = [ ] ;
@@ -98,26 +100,30 @@ DecisionService.prototype.getVariation = function(configObj, experimentKey, user
98100 } ;
99101 }
100102
101- // check for sticky bucketing
102- var experimentBucketMap = this . __resolveExperimentBucketMap ( userId , attributes ) ;
103- variation = this . __getStoredVariation ( configObj , experiment , userId , experimentBucketMap ) ;
104- if ( variation ) {
105- var returningStoredVariationMessage = sprintf (
106- LOG_MESSAGES . RETURNING_STORED_VARIATION ,
107- MODULE_NAME ,
108- variation . key ,
109- experimentKey ,
110- userId
111- ) ;
112- this . logger . log (
113- LOG_LEVEL . INFO ,
114- returningStoredVariationMessage
115- ) ;
116- decideReasons . push ( returningStoredVariationMessage ) ;
117- return {
118- result : variation . key ,
119- reasons : decideReasons ,
120- } ;
103+ var shouldIgnoreUPS = options [ OptimizelyDecideOptions . IGNORE_USER_PROFILE_SERVICE ] ;
104+
105+ // check for sticky bucketing if decide options do not include shouldIgnoreUPS
106+ if ( ! shouldIgnoreUPS ) {
107+ var experimentBucketMap = this . __resolveExperimentBucketMap ( userId , attributes ) ;
108+ variation = this . __getStoredVariation ( configObj , experiment , userId , experimentBucketMap ) ;
109+ if ( variation ) {
110+ var returningStoredVariationMessage = sprintf (
111+ LOG_MESSAGES . RETURNING_STORED_VARIATION ,
112+ MODULE_NAME ,
113+ variation . key ,
114+ experimentKey ,
115+ userId
116+ ) ;
117+ this . logger . log (
118+ LOG_LEVEL . INFO ,
119+ returningStoredVariationMessage
120+ ) ;
121+ decideReasons . push ( returningStoredVariationMessage ) ;
122+ return {
123+ result : variation . key ,
124+ reasons : decideReasons ,
125+ } ;
126+ }
121127 }
122128
123129 // Perform regular targeting and bucketing
@@ -174,8 +180,10 @@ DecisionService.prototype.getVariation = function(configObj, experimentKey, user
174180 ) ;
175181 this . logger . log ( LOG_LEVEL . INFO , userInVariationLogMessage ) ;
176182 decideReasons . push ( userInVariationLogMessage ) ;
177- // persist bucketing
178- this . __saveUserProfile ( experiment , variation , userId , experimentBucketMap ) ;
183+ // persist bucketing if decide options do not include shouldIgnoreUPS
184+ if ( ! shouldIgnoreUPS ) {
185+ this . __saveUserProfile ( experiment , variation , userId , experimentBucketMap ) ;
186+ }
179187
180188 return {
181189 result : variation . key ,
@@ -414,17 +422,18 @@ DecisionService.prototype.__saveUserProfile = function(experiment, variation, us
414422 * experiment properties (both objects), as well as a decisionSource property.
415423 * decisionSource indicates whether the decision was due to a rollout or an
416424 * experiment.
417- * @param {Object } configObj The parsed project configuration object
418- * @param {Object } feature A feature flag object from project configuration
419- * @param {String } userId A string identifying the user, for bucketing
420- * @param {Object } attributes Optional user attributes
421- * @return {Object } DecisionResponse DecisionResponse containing an object with experiment, variation, and decisionSource
422- * properties and decide reasons. If the user was not bucketed into a variation, the variation
423- * property in decision object is null.
425+ * @param {Object } configObj The parsed project configuration object
426+ * @param {Object } feature A feature flag object from project configuration
427+ * @param {String } userId A string identifying the user, for bucketing
428+ * @param {Object } attributes Optional user attributes
429+ * @param {[key: string]: boolean } options Map of decide options
430+ * @return {Object } DecisionResponse DecisionResponse containing an object with experiment, variation, and decisionSource
431+ * properties and decide reasons. If the user was not bucketed into a variation, the variation
432+ * property in decision object is null.
424433 */
425- DecisionService . prototype . getVariationForFeature = function ( configObj , feature , userId , attributes ) {
434+ DecisionService . prototype . getVariationForFeature = function ( configObj , feature , userId , attributes , options = { } ) {
426435 var decideReasons = [ ] ;
427- var decisionVariation = this . _getVariationForFeatureExperiment ( configObj , feature , userId , attributes ) ;
436+ var decisionVariation = this . _getVariationForFeatureExperiment ( configObj , feature , userId , attributes , options ) ;
428437 decideReasons . push ( ...decisionVariation . reasons ) ;
429438 var experimentDecision = decisionVariation . result ;
430439
@@ -457,7 +466,8 @@ DecisionService.prototype.getVariationForFeature = function(configObj, feature,
457466 } ;
458467} ;
459468
460- DecisionService . prototype . _getVariationForFeatureExperiment = function ( configObj , feature , userId , attributes ) {
469+
470+ DecisionService . prototype . _getVariationForFeatureExperiment = function ( configObj , feature , userId , attributes , options = { } ) {
461471 var decideReasons = [ ] ;
462472 var experiment = null ;
463473 var variationKey = null ;
@@ -468,7 +478,7 @@ DecisionService.prototype._getVariationForFeatureExperiment = function(configObj
468478 if ( group ) {
469479 experiment = this . _getExperimentInGroup ( configObj , group , userId ) ;
470480 if ( experiment && feature . experimentIds . indexOf ( experiment . id ) !== - 1 ) {
471- decisionVariation = this . getVariation ( configObj , experiment . key , userId , attributes ) ;
481+ decisionVariation = this . getVariation ( configObj , experiment . key , userId , attributes , options ) ;
472482 decideReasons . push ( ...decisionVariation . reasons ) ;
473483 variationKey = decisionVariation . result ;
474484 }
@@ -478,7 +488,7 @@ DecisionService.prototype._getVariationForFeatureExperiment = function(configObj
478488 // with one experiment, so we look at the first experiment ID only
479489 experiment = projectConfig . getExperimentFromId ( configObj , feature . experimentIds [ 0 ] , this . logger ) ;
480490 if ( experiment ) {
481- decisionVariation = this . getVariation ( configObj , experiment . key , userId , attributes ) ;
491+ decisionVariation = this . getVariation ( configObj , experiment . key , userId , attributes , options ) ;
482492 decideReasons . push ( ...decisionVariation . reasons ) ;
483493 variationKey = decisionVariation . result ;
484494 }
0 commit comments