Преглед изворни кода

Merge pull request #10266 from overleaf/ab-split-test-no-serialization

[web] Skip mongoose object transformations for the split test cache

GitOrigin-RevId: 8fb5420f6f938c0ab7cfe1ca82c107c7ce3522ca
Jakob Ackermann пре 4 година
родитељ
комит
10c6bd20ab

+ 4 - 4
services/web/app/src/Features/SplitTests/SplitTestCache.js

@@ -1,5 +1,4 @@
 const SplitTestManager = require('./SplitTestManager')
 const SplitTestManager = require('./SplitTestManager')
-const { SplitTest } = require('../../models/SplitTest')
 const { CacheLoader } = require('cache-flow')
 const { CacheLoader } = require('cache-flow')
 
 
 class SplitTestCache extends CacheLoader {
 class SplitTestCache extends CacheLoader {
@@ -10,18 +9,19 @@ class SplitTestCache extends CacheLoader {
   }
   }
 
 
   async load(name) {
   async load(name) {
-    return await SplitTestManager.getSplitTest({
+    const splitTest = await SplitTestManager.getSplitTest({
       name,
       name,
       archived: { $ne: true },
       archived: { $ne: true },
     })
     })
+    return splitTest?.toObject()
   }
   }
 
 
   serialize(value) {
   serialize(value) {
-    return value ? value.toObject() : undefined
+    return value
   }
   }
 
 
   deserialize(value) {
   deserialize(value) {
-    return new SplitTest(value)
+    return value
   }
   }
 }
 }
 
 

+ 6 - 5
services/web/app/src/Features/SplitTests/SplitTestHandler.js

@@ -10,6 +10,7 @@ const { SplitTest } = require('../../models/SplitTest')
 const UserAnalyticsIdCache = require('../Analytics/UserAnalyticsIdCache')
 const UserAnalyticsIdCache = require('../Analytics/UserAnalyticsIdCache')
 const { getAnalyticsIdFromMongoUser } = require('../Analytics/AnalyticsHelper')
 const { getAnalyticsIdFromMongoUser } = require('../Analytics/AnalyticsHelper')
 const Features = require('../../infrastructure/Features')
 const Features = require('../../infrastructure/Features')
+const SplitTestUtils = require('./SplitTestUtils')
 
 
 const DEFAULT_VARIANT = 'default'
 const DEFAULT_VARIANT = 'default'
 const ALPHA_PHASE = 'alpha'
 const ALPHA_PHASE = 'alpha'
@@ -191,7 +192,7 @@ async function getActiveAssignmentsForUser(userId) {
  */
  */
 async function _getVariantNames(splitTestName) {
 async function _getVariantNames(splitTestName) {
   const splitTest = await SplitTestCache.get(splitTestName)
   const splitTest = await SplitTestCache.get(splitTestName)
-  const currentVersion = splitTest?.getCurrentVersion()
+  const currentVersion = SplitTestUtils.getCurrentVersion(splitTest)
   if (currentVersion?.active) {
   if (currentVersion?.active) {
     return currentVersion.variants.map(v => v.name).concat([DEFAULT_VARIANT])
     return currentVersion.variants.map(v => v.name).concat([DEFAULT_VARIANT])
   } else {
   } else {
@@ -208,7 +209,7 @@ async function _getAssignment(
   }
   }
 
 
   const splitTest = await SplitTestCache.get(splitTestName)
   const splitTest = await SplitTestCache.get(splitTestName)
-  const currentVersion = splitTest?.getCurrentVersion()
+  const currentVersion = SplitTestUtils.getCurrentVersion(splitTest)
   if (!currentVersion?.active) {
   if (!currentVersion?.active) {
     return DEFAULT_ASSIGNMENT
     return DEFAULT_ASSIGNMENT
   }
   }
@@ -251,7 +252,7 @@ async function _getAssignment(
 }
 }
 
 
 async function _getAssignmentMetadata(analyticsId, user, splitTest) {
 async function _getAssignmentMetadata(analyticsId, user, splitTest) {
-  const currentVersion = splitTest.getCurrentVersion()
+  const currentVersion = SplitTestUtils.getCurrentVersion(splitTest)
   const phase = currentVersion.phase
   const phase = currentVersion.phase
   if (
   if (
     (phase === ALPHA_PHASE && !user?.alphaProgram) ||
     (phase === ALPHA_PHASE && !user?.alphaProgram) ||
@@ -398,10 +399,10 @@ async function _getUser(id) {
 async function _loadSplitTestInfoInLocals(locals, splitTestName) {
 async function _loadSplitTestInfoInLocals(locals, splitTestName) {
   const splitTest = await SplitTestCache.get(splitTestName)
   const splitTest = await SplitTestCache.get(splitTestName)
   if (splitTest) {
   if (splitTest) {
-    const phase = splitTest.getCurrentVersion().phase
+    const phase = SplitTestUtils.getCurrentVersion(splitTest).phase
     LocalsHelper.setSplitTestInfo(locals, splitTestName, {
     LocalsHelper.setSplitTestInfo(locals, splitTestName, {
       phase,
       phase,
-      badgeInfo: splitTest.toObject().badgeInfo?.[phase],
+      badgeInfo: splitTest.badgeInfo?.[phase],
     })
     })
   }
   }
 }
 }

+ 7 - 5
services/web/app/src/Features/SplitTests/SplitTestManager.js

@@ -1,4 +1,5 @@
 const { SplitTest } = require('../../models/SplitTest')
 const { SplitTest } = require('../../models/SplitTest')
+const SplitTestUtils = require('./SplitTestUtils')
 const OError = require('@overleaf/o-error')
 const OError = require('@overleaf/o-error')
 const _ = require('lodash')
 const _ = require('lodash')
 
 
@@ -89,7 +90,7 @@ async function updateSplitTestConfig(name, configuration) {
   if (splitTest.archived) {
   if (splitTest.archived) {
     throw new OError('Cannot update an archived split test', { name })
     throw new OError('Cannot update an archived split test', { name })
   }
   }
-  const lastVersion = splitTest.getCurrentVersion().toObject()
+  const lastVersion = SplitTestUtils.getCurrentVersion(splitTest).toObject()
   if (configuration.phase !== lastVersion.phase) {
   if (configuration.phase !== lastVersion.phase) {
     throw new OError(
     throw new OError(
       `Cannot update with different phase - use /switch-to-next-phase endpoint instead`
       `Cannot update with different phase - use /switch-to-next-phase endpoint instead`
@@ -145,7 +146,7 @@ async function switchToNextPhase(name) {
       name,
       name,
     })
     })
   }
   }
-  const lastVersionCopy = splitTest.getCurrentVersion().toObject()
+  const lastVersionCopy = SplitTestUtils.getCurrentVersion(splitTest).toObject()
   lastVersionCopy.versionNumber++
   lastVersionCopy.versionNumber++
   if (lastVersionCopy.phase === ALPHA_PHASE) {
   if (lastVersionCopy.phase === ALPHA_PHASE) {
     lastVersionCopy.phase = BETA_PHASE
     lastVersionCopy.phase = BETA_PHASE
@@ -189,13 +190,13 @@ async function revertToPreviousVersion(name, versionNumber) {
       `Cannot revert split test with ID '${name}' to previous version: split test must have at least 2 versions`
       `Cannot revert split test with ID '${name}' to previous version: split test must have at least 2 versions`
     )
     )
   }
   }
-  const previousVersion = splitTest.getVersion(versionNumber)
+  const previousVersion = SplitTestUtils.getVersion(splitTest, versionNumber)
   if (!previousVersion) {
   if (!previousVersion) {
     throw new OError(
     throw new OError(
       `Cannot revert split test with ID '${name}' to version number ${versionNumber}: version not found`
       `Cannot revert split test with ID '${name}' to version number ${versionNumber}: version not found`
     )
     )
   }
   }
-  const lastVersion = splitTest.getCurrentVersion()
+  const lastVersion = SplitTestUtils.getCurrentVersion(splitTest)
   if (
   if (
     lastVersion.phase === RELEASE_PHASE &&
     lastVersion.phase === RELEASE_PHASE &&
     previousVersion.phase !== RELEASE_PHASE
     previousVersion.phase !== RELEASE_PHASE
@@ -217,7 +218,8 @@ async function archive(name) {
     throw new OError(`Split test with ID '${name}' is already archived`)
     throw new OError(`Split test with ID '${name}' is already archived`)
   }
   }
   splitTest.archived = true
   splitTest.archived = true
-  const previousVersionCopy = splitTest.getCurrentVersion().toObject()
+  const previousVersionCopy =
+    SplitTestUtils.getCurrentVersion(splitTest).toObject()
   previousVersionCopy.versionNumber += 1
   previousVersionCopy.versionNumber += 1
   previousVersionCopy.active = false
   previousVersionCopy.active = false
   splitTest.versions.push(previousVersionCopy)
   splitTest.versions.push(previousVersionCopy)

+ 20 - 0
services/web/app/src/Features/SplitTests/SplitTestUtils.js

@@ -0,0 +1,20 @@
+const _ = require('lodash')
+
+function getCurrentVersion(splitTest) {
+  if (splitTest?.versions?.length > 0) {
+    return _.maxBy(splitTest.versions, 'versionNumber')
+  } else {
+    return undefined
+  }
+}
+
+function getVersion(splitTest, versionNumber) {
+  return _.find(splitTest.versions || [], {
+    versionNumber,
+  })
+}
+
+module.exports = {
+  getCurrentVersion,
+  getVersion,
+}

+ 0 - 15
services/web/app/src/models/SplitTest.js

@@ -1,6 +1,5 @@
 const mongoose = require('../infrastructure/Mongoose')
 const mongoose = require('../infrastructure/Mongoose')
 const { Schema } = mongoose
 const { Schema } = mongoose
-const _ = require('lodash')
 
 
 const MIN_NAME_LENGTH = 3
 const MIN_NAME_LENGTH = 3
 const MAX_NAME_LENGTH = 200
 const MAX_NAME_LENGTH = 200
@@ -147,20 +146,6 @@ const SplitTestSchema = new Schema({
   },
   },
 })
 })
 
 
-SplitTestSchema.methods.getCurrentVersion = function () {
-  if (this.versions && this.versions.length > 0) {
-    return _.maxBy(this.versions, 'versionNumber')
-  } else {
-    return undefined
-  }
-}
-
-SplitTestSchema.methods.getVersion = function (versionNumber) {
-  return _.find(this.versions || [], {
-    versionNumber,
-  })
-}
-
 module.exports = {
 module.exports = {
   SplitTest: mongoose.model('SplitTest', SplitTestSchema),
   SplitTest: mongoose.model('SplitTest', SplitTestSchema),
   SplitTestSchema,
   SplitTestSchema,

+ 20 - 17
services/web/test/unit/src/SplitTests/SplitTestHandlerTests.js

@@ -176,28 +176,31 @@ describe('SplitTestHandler', function () {
   })
   })
 })
 })
 
 
-function makeSplitTest(name, opts = {}) {
-  const {
+function makeSplitTest(
+  name,
+  {
     active = true,
     active = true,
     analyticsEnabled = active,
     analyticsEnabled = active,
     phase = 'release',
     phase = 'release',
     versionNumber = 1,
     versionNumber = 1,
-  } = opts
-
+  } = {}
+) {
   return {
   return {
     name,
     name,
-    getCurrentVersion: sinon.stub().returns({
-      active,
-      analyticsEnabled,
-      phase,
-      versionNumber,
-      variants: [
-        {
-          name: 'variant-1',
-          rolloutPercent: 100,
-          rolloutStripes: [{ start: 0, end: 100 }],
-        },
-      ],
-    }),
+    versions: [
+      {
+        active,
+        analyticsEnabled,
+        phase,
+        versionNumber,
+        variants: [
+          {
+            name: 'variant-1',
+            rolloutPercent: 100,
+            rolloutStripes: [{ start: 0, end: 100 }],
+          },
+        ],
+      },
+    ],
   }
   }
 }
 }