UNPKG

@splitsoftware/splitio-commons

Version:
129 lines (128 loc) 5.29 kB
import { engineParser } from './Engine'; import { thenable } from '../utils/promise/thenable'; import { EXCEPTION, SPLIT_NOT_FOUND } from '../utils/labels'; import { CONTROL } from '../utils/constants'; import { returnSetsUnion, setToArray } from '../utils/lang/sets'; import { WARN_FLAGSET_WITHOUT_FLAGS } from '../logger/constants'; var treatmentException = { treatment: CONTROL, label: EXCEPTION, config: null }; function treatmentsException(splitNames) { var evaluations = {}; splitNames.forEach(function (splitName) { evaluations[splitName] = treatmentException; }); return evaluations; } export function evaluateFeature(log, key, splitName, attributes, storage) { var parsedSplit; try { parsedSplit = storage.splits.getSplit(splitName); } catch (e) { // Exception on sync `getSplit` storage. Not possible ATM with InMemory and InLocal storages. return treatmentException; } if (thenable(parsedSplit)) { return parsedSplit.then(function (split) { return getEvaluation(log, key, split, attributes, storage); }).catch( // Exception on async `getSplit` storage. For example, when the storage is redis or // pluggable and there is a connection issue and we can't retrieve the split to be evaluated function () { return treatmentException; }); } return getEvaluation(log, key, parsedSplit, attributes, storage); } export function evaluateFeatures(log, key, splitNames, attributes, storage) { var parsedSplits; try { parsedSplits = storage.splits.getSplits(splitNames); } catch (e) { // Exception on sync `getSplits` storage. Not possible ATM with InMemory and InLocal storages. return treatmentsException(splitNames); } return thenable(parsedSplits) ? parsedSplits.then(function (splits) { return getEvaluations(log, key, splitNames, splits, attributes, storage); }) .catch(function () { // Exception on async `getSplits` storage. For example, when the storage is redis or // pluggable and there is a connection issue and we can't retrieve the split to be evaluated return treatmentsException(splitNames); }) : getEvaluations(log, key, splitNames, parsedSplits, attributes, storage); } export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, method) { var storedFlagNames; function evaluate(featureFlagsByFlagSets) { var featureFlags = new Set(); for (var i = 0; i < flagSets.length; i++) { var featureFlagByFlagSet = featureFlagsByFlagSets[i]; if (featureFlagByFlagSet.size) { featureFlags = returnSetsUnion(featureFlags, featureFlagByFlagSet); } else { log.warn(WARN_FLAGSET_WITHOUT_FLAGS, [method, flagSets[i]]); } } return featureFlags.size ? evaluateFeatures(log, key, setToArray(featureFlags), attributes, storage) : {}; } // get features by flag sets try { storedFlagNames = storage.splits.getNamesByFlagSets(flagSets); } catch (e) { // return empty evaluations return {}; } // evaluate related features return thenable(storedFlagNames) ? storedFlagNames.then(function (storedFlagNames) { return evaluate(storedFlagNames); }) .catch(function () { return {}; }) : evaluate(storedFlagNames); } function getEvaluation(log, key, splitJSON, attributes, storage) { var evaluation = { treatment: CONTROL, label: SPLIT_NOT_FOUND, config: null }; if (splitJSON) { var split = engineParser(log, splitJSON, storage); evaluation = split.getTreatment(key, attributes, evaluateFeature); // If the storage is async and the evaluated flag uses segments or dependencies, evaluation is thenable if (thenable(evaluation)) { return evaluation.then(function (result) { result.changeNumber = splitJSON.changeNumber; result.config = splitJSON.configurations && splitJSON.configurations[result.treatment] || null; result.impressionsDisabled = splitJSON.impressionsDisabled; return result; }); } else { evaluation.changeNumber = splitJSON.changeNumber; evaluation.config = splitJSON.configurations && splitJSON.configurations[evaluation.treatment] || null; evaluation.impressionsDisabled = splitJSON.impressionsDisabled; } } return evaluation; } function getEvaluations(log, key, splitNames, splits, attributes, storage) { var result = {}; var thenables = []; splitNames.forEach(function (splitName) { var evaluation = getEvaluation(log, key, splits[splitName], attributes, storage); if (thenable(evaluation)) { thenables.push(evaluation.then(function (res) { result[splitName] = res; })); } else { result[splitName] = evaluation; } }); return thenables.length > 0 ? Promise.all(thenables).then(function () { return result; }) : result; }