@@ -21,6 +21,7 @@ import * as enums from '../../utils/enums';
21
21
import projectConfig from '../project_config' ;
22
22
import AudienceEvaluator from '../audience_evaluator' ;
23
23
import * as stringValidator from '../../utils/string_value_validator' ;
24
+ import { OptimizelyDecideOptions } from '../../shared_types' ;
24
25
25
26
var MODULE_NAME = 'DECISION_SERVICE' ;
26
27
var ERROR_MESSAGES = enums . ERROR_MESSAGES ;
@@ -55,14 +56,15 @@ function DecisionService(options) {
55
56
56
57
/**
57
58
* 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.
64
66
*/
65
- DecisionService . prototype . getVariation = function ( configObj , experimentKey , userId , attributes ) {
67
+ DecisionService . prototype . getVariation = function ( configObj , experimentKey , userId , attributes , options = { } ) {
66
68
// by default, the bucketing ID should be the user ID
67
69
var bucketingId = this . _getBucketingId ( userId , attributes ) ;
68
70
var decideReasons = [ ] ;
@@ -98,26 +100,30 @@ DecisionService.prototype.getVariation = function(configObj, experimentKey, user
98
100
} ;
99
101
}
100
102
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
+ }
121
127
}
122
128
123
129
// Perform regular targeting and bucketing
@@ -174,8 +180,10 @@ DecisionService.prototype.getVariation = function(configObj, experimentKey, user
174
180
) ;
175
181
this . logger . log ( LOG_LEVEL . INFO , userInVariationLogMessage ) ;
176
182
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
+ }
179
187
180
188
return {
181
189
result : variation . key ,
@@ -414,17 +422,18 @@ DecisionService.prototype.__saveUserProfile = function(experiment, variation, us
414
422
* experiment properties (both objects), as well as a decisionSource property.
415
423
* decisionSource indicates whether the decision was due to a rollout or an
416
424
* 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.
424
433
*/
425
- DecisionService . prototype . getVariationForFeature = function ( configObj , feature , userId , attributes ) {
434
+ DecisionService . prototype . getVariationForFeature = function ( configObj , feature , userId , attributes , options = { } ) {
426
435
var decideReasons = [ ] ;
427
- var decisionVariation = this . _getVariationForFeatureExperiment ( configObj , feature , userId , attributes ) ;
436
+ var decisionVariation = this . _getVariationForFeatureExperiment ( configObj , feature , userId , attributes , options ) ;
428
437
decideReasons . push ( ...decisionVariation . reasons ) ;
429
438
var experimentDecision = decisionVariation . result ;
430
439
@@ -457,7 +466,8 @@ DecisionService.prototype.getVariationForFeature = function(configObj, feature,
457
466
} ;
458
467
} ;
459
468
460
- DecisionService . prototype . _getVariationForFeatureExperiment = function ( configObj , feature , userId , attributes ) {
469
+
470
+ DecisionService . prototype . _getVariationForFeatureExperiment = function ( configObj , feature , userId , attributes , options = { } ) {
461
471
var decideReasons = [ ] ;
462
472
var experiment = null ;
463
473
var variationKey = null ;
@@ -468,7 +478,7 @@ DecisionService.prototype._getVariationForFeatureExperiment = function(configObj
468
478
if ( group ) {
469
479
experiment = this . _getExperimentInGroup ( configObj , group , userId ) ;
470
480
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 ) ;
472
482
decideReasons . push ( ...decisionVariation . reasons ) ;
473
483
variationKey = decisionVariation . result ;
474
484
}
@@ -478,7 +488,7 @@ DecisionService.prototype._getVariationForFeatureExperiment = function(configObj
478
488
// with one experiment, so we look at the first experiment ID only
479
489
experiment = projectConfig . getExperimentFromId ( configObj , feature . experimentIds [ 0 ] , this . logger ) ;
480
490
if ( experiment ) {
481
- decisionVariation = this . getVariation ( configObj , experiment . key , userId , attributes ) ;
491
+ decisionVariation = this . getVariation ( configObj , experiment . key , userId , attributes , options ) ;
482
492
decideReasons . push ( ...decisionVariation . reasons ) ;
483
493
variationKey = decisionVariation . result ;
484
494
}
0 commit comments