-
Notifications
You must be signed in to change notification settings - Fork 83
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
Use attributes for sticky bucketing #179
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, only requesting changes for missing var
and updating doc comments.
@@ -61,6 +63,7 @@ function DecisionService(options) { | |||
* @return {string|null} the variation the user is bucketed into. | |||
*/ | |||
DecisionService.prototype.getVariation = function(experimentKey, userId, attributes) { | |||
attributes = attributes || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we move down inside __resolveExperimentBucketMap
, or closer to where it's needed?
Leaving it here makes it harder to merge this into the 2.x branch because this change might affect audience evaluation in that branch. I think we want to release this as a 2.x minor version.
if (!this.userProfileService) { | ||
return; | ||
} | ||
|
||
try { | ||
userProfile.experiment_bucket_map[experiment.id] = { | ||
variation_id: variation.id, | ||
newBucketMap = fns.cloneDeep(experimentBucketMap); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need var
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, seems like lint should catch something like this and error hard.
assert.strictEqual(mockLogger.log.args[1][1], 'DECISION_SERVICE: Returning previously activated variation \"variation\" of experiment \"testExperiment\" for user \"decision_service_user\" from user profile.'); | ||
}); | ||
|
||
it('should respect ignore attributes for a different experiment id', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: delete 'respect'?
assert.strictEqual(mockLogger.log.args[1][1], 'DECISION_SERVICE: Returning previously activated variation \"control\" of experiment \"testExperiment\" for user \"decision_service_user\" from user profile.'); | ||
}); | ||
|
||
it('should use attributes when the userProfileLookup returns null', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the title of this test seems like it should be swapped with the title of the following one.
a78d188
to
f607cc3
Compare
@@ -236,20 +246,25 @@ DecisionService.prototype.__getUserProfile = function(userId) { | |||
* @param {Object} experiment | |||
* @param {Object} variation | |||
*/ | |||
DecisionService.prototype.__saveUserProfile = function(userProfile, experiment, variation) { | |||
DecisionService.prototype.__saveUserProfile = function(experiment, variation, userId, experimentBucketMap) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: another doc comment changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikeng13 we should have a compat test for this only targeted at JS SDK
@@ -136,6 +136,7 @@ exports.CONTROL_ATTRIBUTES = { | |||
BOT_FILTERING: '$opt_bot_filtering', | |||
BUCKETING_ID: '$opt_bucketing_id', | |||
USER_AGENT: '$opt_user_agent', | |||
STICKY_BUCKETING_KEY: '$opt_experiment_bucket_map', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit. Alphabetize.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is really a nit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty straightforward! Thanks for doing this.
* @return {Object} the stored variation or null if the user profile does not have one for the given experiment | ||
*/ | ||
DecisionService.prototype.__getStoredVariation = function(experiment, userProfile) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The description of the function is no longer accurate. Not sure it was very accurate in the first place either because it wasn't really "stored"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Want to make sure this extension to the API is actually what we want to do (ref: discussion in doc/slack)
Discussed IRL. I still have reservations because of how it makes something complex (distributed syncing) appear simple, but still require the customer to do that legwork, but if this is what we need to do then we need to do it. My understanding is this isn't required in other SDKs since it's much easier to write blocking I/O.
12a5bf4
to
1b8c5e8
Compare
Use attributes for sticky bucketing
This PR allows customers to pass in
$opt_experiment_bucket_map
toattributes
. This will take priority overuserProfileService.lookup
when making sticky bucketing decisions.Example
This allows sticky bucketing to be achieved without using the
userProfileService
and allows sticky bucketing to be done synchronously. However most implementations the lookup forattributes
will be done synchronously and will still useuserProfileService.save
to persist sticky bucketing information.Example