From 2ac9b262576c0f2765341b6335a34364cd8903f4 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Oct 2018 16:40:51 +0200 Subject: [PATCH] phased rollout expired function --- src/PhasedRollOut.js | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/PhasedRollOut.js diff --git a/src/PhasedRollOut.js b/src/PhasedRollOut.js new file mode 100644 index 0000000000..db91f8ab76 --- /dev/null +++ b/src/PhasedRollOut.js @@ -0,0 +1,62 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd +Copyright 2018 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import SdkConfig from './SdkConfig'; + +function hashCode(str) { + var hash = 0, i, chr; + if (str.length === 0) return hash; + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; + } + return Math.abs(hash); +} + +export function phasedRollOutExpiredForUser(username, feature, now, rollOutConfig = SdkConfig.get().phasedRollOut) { + if (!rollOutConfig) { + console.log(`no phased rollout configuration, so enabling ${feature}`); + return true; + } + const featureConfig = rollOutConfig[feature]; + if (!featureConfig) { + console.log(`${feature} doesn't have phased rollout configured, so enabling`); + return true; + } + if (!Number.isFinite(featureConfig.offset) || !Number.isFinite(featureConfig.period)) { + console.error(`phased rollout of ${feature} is misconfigured, offset and/or period are not numbers, so disabling`, featureConfig); + return false; + } + + const hash = hashCode(username); + //ms -> min, enable users at minute granularity + const bucketRatio = 1000 * 60; + const bucketCount = featureConfig.period / bucketRatio; + const userBucket = hash % bucketCount; + const userMs = userBucket * bucketRatio; + const enableAt = featureConfig.offset + userMs; + const result = now >= enableAt; + const bucketStr = `(bucket ${userBucket}/${bucketCount})`; + if (result) { + console.log(`${feature} enabled for ${username} ${bucketStr}`) + } else { + console.log(`${feature} will be enabled for ${username} in ${Math.ceil((enableAt - now)/1000)}s ${bucketStr}`); + } + return result; +}