mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #14736 from overleaf/jpa-split-test-optimizations
[web] split test optimizations GitOrigin-RevId: 97aa6c5aaad7f2dbb2f2fe9da33812857982996a
This commit is contained in:
parent
0f30edf69f
commit
d19090e398
1 changed files with 53 additions and 10 deletions
|
@ -17,6 +17,7 @@ const Settings = require('@overleaf/settings')
|
||||||
const DEFAULT_VARIANT = 'default'
|
const DEFAULT_VARIANT = 'default'
|
||||||
const ALPHA_PHASE = 'alpha'
|
const ALPHA_PHASE = 'alpha'
|
||||||
const BETA_PHASE = 'beta'
|
const BETA_PHASE = 'beta'
|
||||||
|
const CACHE_TOMBSTONE_SPLIT_TEST_NOT_ACTIVE_FOR_USER = null
|
||||||
const DEFAULT_ASSIGNMENT = {
|
const DEFAULT_ASSIGNMENT = {
|
||||||
variant: DEFAULT_VARIANT,
|
variant: DEFAULT_VARIANT,
|
||||||
analytics: {
|
analytics: {
|
||||||
|
@ -224,6 +225,10 @@ async function _getAssignment(
|
||||||
splitTest.name,
|
splitTest.name,
|
||||||
currentVersion
|
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) {
|
if (cachedVariant) {
|
||||||
Metrics.inc('split_test_get_assignment_source', 1, { status: 'cache' })
|
Metrics.inc('split_test_get_assignment_source', 1, { status: 'cache' })
|
||||||
return _makeAssignment(splitTest, cachedVariant, currentVersion)
|
return _makeAssignment(splitTest, cachedVariant, currentVersion)
|
||||||
|
@ -238,9 +243,18 @@ async function _getAssignment(
|
||||||
Metrics.inc('split_test_get_assignment_source', 1, { status: 'none' })
|
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 } =
|
const { activeForUser, selectedVariantName, phase, versionNumber } =
|
||||||
await _getAssignmentMetadata(analyticsId, user, splitTest)
|
await _getAssignmentMetadata(analyticsId, user, splitTest)
|
||||||
|
if (session) {
|
||||||
|
_setVariantInSession({
|
||||||
|
session,
|
||||||
|
splitTestName,
|
||||||
|
currentVersion,
|
||||||
|
selectedVariantName,
|
||||||
|
activeForUser,
|
||||||
|
})
|
||||||
|
}
|
||||||
if (activeForUser) {
|
if (activeForUser) {
|
||||||
const assignmentConfig = {
|
const assignmentConfig = {
|
||||||
user,
|
user,
|
||||||
|
@ -329,7 +343,7 @@ async function _updateVariantAssignment({
|
||||||
}
|
}
|
||||||
// if the user is logged in
|
// if the user is logged in
|
||||||
if (userId) {
|
if (userId) {
|
||||||
user = user || (await _getUser(userId))
|
user = user || (await _getUser(userId, splitTestName))
|
||||||
if (user) {
|
if (user) {
|
||||||
const assignedSplitTests = user.splitTests || []
|
const assignedSplitTests = user.splitTests || []
|
||||||
const assignmentLog = assignedSplitTests[splitTestName] || []
|
const assignmentLog = assignedSplitTests[splitTestName] || []
|
||||||
|
@ -387,23 +401,52 @@ function _makeAssignment(splitTest, variant, currentVersion) {
|
||||||
function _getCachedVariantFromSession(session, splitTestName, currentVersion) {
|
function _getCachedVariantFromSession(session, splitTestName, currentVersion) {
|
||||||
if (!session.cachedSplitTestAssignments) {
|
if (!session.cachedSplitTestAssignments) {
|
||||||
session.cachedSplitTestAssignments = {}
|
session.cachedSplitTestAssignments = {}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
const cacheKey = `${splitTestName}-${currentVersion.versionNumber}`
|
const cacheKey = `${splitTestName}-${currentVersion.versionNumber}`
|
||||||
if (currentVersion.active) {
|
return session.cachedSplitTestAssignments[cacheKey]
|
||||||
return session.cachedSplitTestAssignments[cacheKey]
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheKey = `${splitTestName}-${currentVersion.versionNumber}`
|
||||||
|
if (activeForUser) {
|
||||||
|
session.cachedSplitTestAssignments[cacheKey] = selectedVariantName
|
||||||
} else {
|
} else {
|
||||||
delete session.cachedSplitTestAssignments[cacheKey]
|
session.cachedSplitTestAssignments[cacheKey] =
|
||||||
|
CACHE_TOMBSTONE_SPLIT_TEST_NOT_ACTIVE_FOR_USER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _getUser(id) {
|
async function _getUser(id, splitTestName) {
|
||||||
const user = await UserGetter.promises.getUser(id, {
|
const projection = {
|
||||||
analyticsId: 1,
|
analyticsId: 1,
|
||||||
splitTests: 1,
|
|
||||||
alphaProgram: 1,
|
alphaProgram: 1,
|
||||||
betaProgram: 1,
|
betaProgram: 1,
|
||||||
})
|
}
|
||||||
|
if (splitTestName) {
|
||||||
|
projection[`splitTests.${splitTestName}`] = 1
|
||||||
|
} else {
|
||||||
|
projection.splitTests = 1
|
||||||
|
}
|
||||||
|
const user = await UserGetter.promises.getUser(id, projection)
|
||||||
Metrics.histogram(
|
Metrics.histogram(
|
||||||
'split_test_get_user_from_mongo_size',
|
'split_test_get_user_from_mongo_size',
|
||||||
JSON.stringify(user).length,
|
JSON.stringify(user).length,
|
||||||
|
|
Loading…
Reference in a new issue