The problem as it exists today is that in order to do sticky bucketing the userProfileService implements two async methods lookup(userId)
and save(userProfile)
. However the implementation of lookup
is handled synchronously and thus won’t allow any asynchronous lookups when doing any sort of bucketing decision.
There are many good reasons to want to keep the javascript-sdk synchronous. By making all of the activate calls async we will create a large API breaking change that will force all customers to use an async approach to our SDK, this is bad.
Create separate async versions of all bucketing and tracking functions that rely on userProfileService.lookup
and suffix them with WithUserProfileService
activate
->activateWithUserProfileService
getVariation
->getVariationWithUserProfileService
- Etc…
These functions will accept a callback
as the last argument and will call the their synchronous counterparts under the hood.
activateWithUserProfileService
psuedo-code
var userProfileService = {
lookup(userId, cb) {
someAsyncLookup(userId).then(userProfile => {
cb(null, userProfile)
}
},
save(userProfile) {
someSaveCall(userProfile)
}
}
var clientInstance = optimizelySDK.createInstance({
datafile,
userProfileService,
})
client.activateWithUserProfileService(
'checkout_test',
'userId',
{},
function(err, variationKey) {
console.log('got variationKey', variationKey)
}
)
The easiest way to implement this change is to allow a special key experiment_bucket_map
to be passed into attributes
if any of the bucketing functions see this, they will use this as the source of truth for sticky bucketing. This is how the activateWithUserProfileService
function works internally.
Where does sticky bucketing (userProfile service) need to come into play with the SDK
activate
getVariation
isFeatureEnabled
getEnabledFeatures
getFeatureVariableBoolean
getFeatureVariablDouble
getFeatureVariableInteger
getFeatureVariableString
track
- Make activate call asynchronous if there is a userProfile in place
- Allow activate to be passed a fourth argument that is the
experimentBucketMap
- Allow the passing of a special attributes
experimentBucketMap
{
<expId>: {
variation_id: <varId>
}
}
#work