From 87b3654bff30bedf4eff75843ea3266be98e00fd Mon Sep 17 00:00:00 2001 From: Alexandre Bourdin Date: Thu, 6 May 2021 16:07:54 +0200 Subject: [PATCH] Merge pull request #4001 from overleaf/ab-hash-split-test Add hashing to compute the user's percentile in a split test GitOrigin-RevId: 94302cd1c0ab9e9075a506096b4f36ba50b9b7fa --- .../src/Features/Project/ProjectCreationHandler.js | 5 +++-- .../app/src/Features/SplitTests/SplitTestHandler.js | 13 +++++++++++-- services/web/config/settings.defaults.coffee | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/services/web/app/src/Features/Project/ProjectCreationHandler.js b/services/web/app/src/Features/Project/ProjectCreationHandler.js index ed303f84cb..70bfcc1fb9 100644 --- a/services/web/app/src/Features/Project/ProjectCreationHandler.js +++ b/services/web/app/src/Features/Project/ProjectCreationHandler.js @@ -30,6 +30,7 @@ const MONTH_NAMES = [ 'November', 'December', ] +const EXAMPLE_PROJECT_SPLITTEST_ID = 'example-project-v2' async function createBlankProject(ownerId, projectName, attributes = {}) { const isImport = attributes && attributes.overleaf @@ -72,7 +73,7 @@ async function createExampleProject(ownerId, projectName) { const testSegmentation = SplitTestHandler.getTestSegmentation( ownerId, - 'example-project' + EXAMPLE_PROJECT_SPLITTEST_ID ) if (testSegmentation.variant === 'example-frog') { @@ -84,7 +85,7 @@ async function createExampleProject(ownerId, projectName) { if (testSegmentation.enabled) { AnalyticsManager.recordEvent(ownerId, 'project-created', { projectId: project._id, - splitTestId: 'example-project', + splitTestId: EXAMPLE_PROJECT_SPLITTEST_ID, splitTestVariantId: testSegmentation.variant, }) } else { diff --git a/services/web/app/src/Features/SplitTests/SplitTestHandler.js b/services/web/app/src/Features/SplitTests/SplitTestHandler.js index b5ce435373..54b4cd8921 100644 --- a/services/web/app/src/Features/SplitTests/SplitTestHandler.js +++ b/services/web/app/src/Features/SplitTests/SplitTestHandler.js @@ -1,6 +1,6 @@ const Settings = require('settings-sharelatex') const _ = require('lodash') -const { ObjectId } = require('mongodb') +const crypto = require('crypto') const OError = require('@overleaf/o-error') const ACTIVE_SPLIT_TESTS = [] @@ -34,7 +34,7 @@ for (const splitTest of Settings.splitTests) { function getTestSegmentation(userId, splitTestId) { const splitTest = _.find(ACTIVE_SPLIT_TESTS, ['id', splitTestId]) if (splitTest) { - let userIdAsPercentile = (ObjectId(userId).getTimestamp() / 1000) % 100 + let userIdAsPercentile = _getPercentile(userId, splitTestId) for (const variant of splitTest.variants) { if (userIdAsPercentile < variant.rolloutPercent) { return { @@ -55,6 +55,15 @@ function getTestSegmentation(userId, splitTestId) { } } +function _getPercentile(userId, splitTestId) { + const hash = crypto + .createHash('md5') + .update(userId + splitTestId) + .digest('hex') + const hashPrefix = hash.substr(0, 8) + return Math.floor((parseInt(hashPrefix, 16) / 0xffffffff) * 100) +} + module.exports = { getTestSegmentation, } diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 82ab2a2932..ae84ea8c14 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -238,7 +238,7 @@ module.exports = settings = splitTests: [ { - id: 'example-project' + id: 'example-project-v2' active: process.env['SPLITTEST_EXAMPLE_PROJECT_ACTIVE'] == 'true' variants: [ {