Merge pull request #14736 from overleaf/jpa-split-test-optimizations

[web] split test optimizations

GitOrigin-RevId: 97aa6c5aaad7f2dbb2f2fe9da33812857982996a
This commit is contained in:
Jakob Ackermann 2023-09-12 11:54:39 +02:00 committed by Copybot
parent 0f30edf69f
commit d19090e398

View file

@ -17,6 +17,7 @@ const Settings = require('@overleaf/settings')
const DEFAULT_VARIANT = 'default'
const ALPHA_PHASE = 'alpha'
const BETA_PHASE = 'beta'
const CACHE_TOMBSTONE_SPLIT_TEST_NOT_ACTIVE_FOR_USER = null
const DEFAULT_ASSIGNMENT = {
variant: DEFAULT_VARIANT,
analytics: {
@ -224,6 +225,10 @@ async function _getAssignment(
splitTest.name,
currentVersion
)
if (cachedVariant === CACHE_TOMBSTONE_SPLIT_TEST_NOT_ACTIVE_FOR_USER) {
Metrics.inc('split_test_get_assignment_source', 1, { status: 'cache' })
return DEFAULT_ASSIGNMENT
}
if (cachedVariant) {
Metrics.inc('split_test_get_assignment_source', 1, { status: 'cache' })
return _makeAssignment(splitTest, cachedVariant, currentVersion)
@ -238,9 +243,18 @@ async function _getAssignment(
Metrics.inc('split_test_get_assignment_source', 1, { status: 'none' })
}
user = user || (userId && (await _getUser(userId)))
user = user || (userId && (await _getUser(userId, splitTestName)))
const { activeForUser, selectedVariantName, phase, versionNumber } =
await _getAssignmentMetadata(analyticsId, user, splitTest)
if (session) {
_setVariantInSession({
session,
splitTestName,
currentVersion,
selectedVariantName,
activeForUser,
})
}
if (activeForUser) {
const assignmentConfig = {
user,
@ -329,7 +343,7 @@ async function _updateVariantAssignment({
}
// if the user is logged in
if (userId) {
user = user || (await _getUser(userId))
user = user || (await _getUser(userId, splitTestName))
if (user) {
const assignedSplitTests = user.splitTests || []
const assignmentLog = assignedSplitTests[splitTestName] || []
@ -387,23 +401,52 @@ function _makeAssignment(splitTest, variant, currentVersion) {
function _getCachedVariantFromSession(session, splitTestName, currentVersion) {
if (!session.cachedSplitTestAssignments) {
session.cachedSplitTestAssignments = {}
return
}
const cacheKey = `${splitTestName}-${currentVersion.versionNumber}`
if (currentVersion.active) {
return session.cachedSplitTestAssignments[cacheKey]
} else {
}
function _setVariantInSession({
session,
splitTestName,
currentVersion,
selectedVariantName,
activeForUser,
}) {
if (!session.cachedSplitTestAssignments) {
session.cachedSplitTestAssignments = {}
}
// clean up previous entries from this split test
for (const cacheKey of Object.keys(session.cachedSplitTestAssignments)) {
// drop '-versionNumber'
const name = cacheKey.split('-').slice(0, -1).join('-')
if (name === splitTestName) {
delete session.cachedSplitTestAssignments[cacheKey]
}
}
async function _getUser(id) {
const user = await UserGetter.promises.getUser(id, {
const cacheKey = `${splitTestName}-${currentVersion.versionNumber}`
if (activeForUser) {
session.cachedSplitTestAssignments[cacheKey] = selectedVariantName
} else {
session.cachedSplitTestAssignments[cacheKey] =
CACHE_TOMBSTONE_SPLIT_TEST_NOT_ACTIVE_FOR_USER
}
}
async function _getUser(id, splitTestName) {
const projection = {
analyticsId: 1,
splitTests: 1,
alphaProgram: 1,
betaProgram: 1,
})
}
if (splitTestName) {
projection[`splitTests.${splitTestName}`] = 1
} else {
projection.splitTests = 1
}
const user = await UserGetter.promises.getUser(id, projection)
Metrics.histogram(
'split_test_get_user_from_mongo_size',
JSON.stringify(user).length,