blob: 1528a00c9f5db2eac4a2c5888a0f43f6f428bcb3 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Manages the current user's participation in experiments (e.g.
7 * phased rollouts).
8 *
9 * This file is an early prototype serving the needs of go/monorail-slo-v0.
10 *
11 * The more mature design is under discussion:
12 * http://doc/1rtYXq68WSlTNCzVJiSttLWF14CiK5sOlEef2JWAgheg
13 */
14
15/**
16 * An Enum representing known expreriments.
17 *
18 * @typedef {string} Experiment
19 */
20
21/**
22 * @type {Experiment}
23 */
24export const SLO_EXPERIMENT = 'slo';
25
26const EXPERIMENT_QUERY_PARAM = 'e';
27
28const DISABLED_STR = '-';
29
30const _SLO_EXPERIMENT_USER_DISPLAY_NAMES = new Set([
31 'jessan@google.com',
32]);
33
34/**
35 * Checks whether the current user is in given experiment.
36 *
37 * @param {Experiment} experiment The experiment to check.
38 * @param {UserV0=} user The current user. Although any user can currently
39 * be passed in, we only intend to support checking if the current user is
40 * in the experiment. In the future the user parameter may be removed.
41 * @param {Object} queryParams The current query parameters, parsed by qs.
42 * We support a string like 'e=-exp1,-exp2...' for disabling experiments.
43 *
44 * We allow disabling so that a user in the fishfood group can work around
45 * any bugs or undesired behaviors the experiment may introduce for them.
46 *
47 * As of now, we don't allow enabling experiments by override params.
48 * We may not want access shared beyond the fishfood group (e.g. if it is a
49 * feature we are likely to change dramatically or take away).
50 * @return {boolean} Whether the experiment is enabled for the current user.
51 */
52export const isExperimentEnabled = (experiment, user, queryParams) => {
53 const experimentOverrides = parseExperimentParam(
54 queryParams[EXPERIMENT_QUERY_PARAM]);
55 if (experimentOverrides[experiment] === false) {
56 return false;
57 }
58 switch (experiment) {
59 case SLO_EXPERIMENT:
60 return !!user &&
61 _SLO_EXPERIMENT_USER_DISPLAY_NAMES.has(user.displayName);
62 default:
63 throw Error('Unknown experiment provided');
64 }
65};
66
67/**
68 * Parses a comma separated list of experiments from the query string.
69 * Experiment strings preceded by DISABLED_STR are overrode to be disabled,
70 * otherwise they are to be enabled.
71 *
72 * Does not do any validation of the experiment string provided.
73 *
74 * @param {string?} experimentParam comma separated experiements.
75 * @return {Object} Maps experiment name to whether enabled or
76 * disabled boolean. May include invalid experiment names.
77 */
78const parseExperimentParam = (experimentParam) => {
79 const experimentOverrides = {};
80 if (experimentParam) {
81 for (const experimentOverride of experimentParam.split(',')) {
82 if (experimentOverride.startsWith(DISABLED_STR)) {
83 const experiment = experimentOverride.substr(DISABLED_STR.length);
84 experimentOverrides[experiment] = false;
85 } else {
86 experimentOverrides[experimentOverride] = true;
87 }
88 }
89 }
90 return experimentOverrides;
91};