UNPKG

@splitsoftware/splitio-commons

Version:
162 lines (161 loc) 7.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.evaluateDefaultTreatment = exports.evaluateFeaturesByFlagSets = exports.evaluateFeatures = exports.evaluateFeature = void 0; var Engine_1 = require("./Engine"); var thenable_1 = require("../utils/promise/thenable"); var labels_1 = require("../utils/labels"); var constants_1 = require("../utils/constants"); var sets_1 = require("../utils/lang/sets"); var constants_2 = require("../logger/constants"); var EVALUATION_EXCEPTION = { treatment: constants_1.CONTROL, label: labels_1.EXCEPTION, config: null }; var EVALUATION_DEFINITION_NOT_FOUND = { treatment: constants_1.CONTROL, label: labels_1.DEFINITION_NOT_FOUND, config: null }; function treatmentsException(definitionNames) { var evaluations = {}; definitionNames.forEach(function (definitionName) { evaluations[definitionName] = EVALUATION_EXCEPTION; }); return evaluations; } function evaluateFeature(log, key, definitionName, attributes, storage, options) { var definition; try { definition = storage.definitions.get(definitionName); } catch (e) { // Exception on sync storage. Not possible ATM with InMemory and InLocal storages. return EVALUATION_EXCEPTION; } if ((0, thenable_1.thenable)(definition)) { return definition.then(function (definition) { return getEvaluation(log, key, definition, attributes, storage, options); }).catch( // Exception on async 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 EVALUATION_EXCEPTION; }); } return getEvaluation(log, key, definition, attributes, storage, options); } exports.evaluateFeature = evaluateFeature; function evaluateFeatures(log, key, definitionNames, attributes, storage, options) { var definitions; try { definitions = storage.definitions.getMany(definitionNames); } catch (e) { // Exception on sync storage. Not possible ATM with InMemory and InLocal storages. return treatmentsException(definitionNames); } return (0, thenable_1.thenable)(definitions) ? definitions.then(function (definitions) { return getEvaluations(log, key, definitionNames, definitions, attributes, storage, options); }) .catch(function () { // Exception on async 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(definitionNames); }) : getEvaluations(log, key, definitionNames, definitions, attributes, storage, options); } exports.evaluateFeatures = evaluateFeatures; function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, method, options) { 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 = (0, sets_1.returnSetsUnion)(featureFlags, featureFlagByFlagSet); } else { log.warn(constants_2.WARN_FLAGSET_WITHOUT_FLAGS, [method, flagSets[i]]); } } return featureFlags.size ? evaluateFeatures(log, key, (0, sets_1.setToArray)(featureFlags), attributes, storage, options) : {}; } // get features by flag sets try { storedFlagNames = storage.definitions.getNamesBySets(flagSets); } catch (e) { // return empty evaluations return {}; } // evaluate related features return (0, thenable_1.thenable)(storedFlagNames) ? storedFlagNames.then(function (storedFlagNames) { return evaluate(storedFlagNames); }) .catch(function () { return {}; }) : evaluate(storedFlagNames); } exports.evaluateFeaturesByFlagSets = evaluateFeaturesByFlagSets; function getEvaluation(log, key, definition, attributes, storage, options) { if (definition) { var split = (0, Engine_1.engineParser)(log, definition, storage); var evaluation = split.getTreatment(key, attributes, evaluateFeature); // If the storage is async and the evaluated definition uses segments or dependencies, evaluation is thenable if ((0, thenable_1.thenable)(evaluation)) { return evaluation.then(function (result) { result.changeNumber = definition.changeNumber; result.config = definition.configurations && definition.configurations[result.treatment] || null; // @ts-expect-error impressionsDisabled is not exposed in the public typings yet. result.impressionsDisabled = (options === null || options === void 0 ? void 0 : options.impressionsDisabled) || definition.impressionsDisabled; return result; }); } else { evaluation.changeNumber = definition.changeNumber; evaluation.config = definition.configurations && definition.configurations[evaluation.treatment] || null; // @ts-expect-error impressionsDisabled is not exposed in the public typings yet. evaluation.impressionsDisabled = (options === null || options === void 0 ? void 0 : options.impressionsDisabled) || definition.impressionsDisabled; } return evaluation; } return EVALUATION_DEFINITION_NOT_FOUND; } function getEvaluations(log, key, definitionNames, definitions, attributes, storage, options) { var result = {}; var thenables = []; definitionNames.forEach(function (definitionName) { var evaluation = getEvaluation(log, key, definitions[definitionName], attributes, storage, options); if ((0, thenable_1.thenable)(evaluation)) { thenables.push(evaluation.then(function (res) { result[definitionName] = res; })); } else { result[definitionName] = evaluation; } }); return thenables.length > 0 ? Promise.all(thenables).then(function () { return result; }) : result; } function evaluateDefaultTreatment(definitionName, storage) { var definition; try { definition = storage.definitions.get(definitionName); } catch (e) { return EVALUATION_EXCEPTION; } return (0, thenable_1.thenable)(definition) ? definition.then(getDefaultTreatment).catch(function () { return EVALUATION_EXCEPTION; }) : getDefaultTreatment(definition); } exports.evaluateDefaultTreatment = evaluateDefaultTreatment; function getDefaultTreatment(definition) { if (definition) { return { treatment: definition.defaultTreatment, label: labels_1.NO_CONDITION_MATCH, config: definition.configurations && definition.configurations[definition.defaultTreatment] || null, changeNumber: definition.changeNumber }; } return EVALUATION_DEFINITION_NOT_FOUND; }