UNPKG

@splitsoftware/splitio-commons

Version:
184 lines (183 loc) 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clientFactory = void 0; var evaluator_1 = require("../evaluator"); var thenable_1 = require("../utils/promise/thenable"); var key_1 = require("../utils/key"); var splitExistence_1 = require("../utils/inputValidation/splitExistence"); var trafficTypeExistence_1 = require("../utils/inputValidation/trafficTypeExistence"); var labels_1 = require("../utils/labels"); var constants_1 = require("../utils/constants"); var constants_2 = require("../logger/constants"); var mode_1 = require("../utils/settingsValidation/mode"); var treatmentNotReady = { treatment: constants_1.CONTROL, label: labels_1.SDK_NOT_READY }; function treatmentsNotReady(featureFlagNames) { var evaluations = {}; featureFlagNames.forEach(function (featureFlagName) { evaluations[featureFlagName] = treatmentNotReady; }); return evaluations; } function stringify(options) { if (options && options.properties) { try { return JSON.stringify(options.properties); } catch ( /* JSON.stringify should never throw with validated options, but handling just in case */_a) { /* JSON.stringify should never throw with validated options, but handling just in case */ } } } /** * Creator of base client with getTreatments and track methods. */ function clientFactory(params) { var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage, settings = params.settings, impressionsTracker = params.impressionsTracker, eventTracker = params.eventTracker, telemetryTracker = params.telemetryTracker; var log = settings.log, mode = settings.mode; var isAsync = (0, mode_1.isConsumerMode)(mode); function getTreatment(key, featureFlagName, attributes, options, withConfig, methodName) { if (withConfig === void 0) { withConfig = false; } if (methodName === void 0) { methodName = constants_1.GET_TREATMENT; } var stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? constants_1.TREATMENT_WITH_CONFIG : constants_1.TREATMENT); var wrapUp = function (evaluationResult) { var queue = []; var treatment = processEvaluation(evaluationResult, featureFlagName, key, stringify(options), withConfig, methodName, queue); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); return treatment; }; var evaluation = readinessManager.isReady() || readinessManager.isReadyFromCache() ? (0, evaluator_1.evaluateFeature)(log, key, featureFlagName, attributes, storage) : isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected Promise.resolve(treatmentNotReady) : treatmentNotReady; return (0, thenable_1.thenable)(evaluation) ? evaluation.then(function (res) { return wrapUp(res); }) : wrapUp(evaluation); } function getTreatmentWithConfig(key, featureFlagName, attributes, options) { return getTreatment(key, featureFlagName, attributes, options, true, constants_1.GET_TREATMENT_WITH_CONFIG); } function getTreatments(key, featureFlagNames, attributes, options, withConfig, methodName) { if (withConfig === void 0) { withConfig = false; } if (methodName === void 0) { methodName = constants_1.GET_TREATMENTS; } var stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? constants_1.TREATMENTS_WITH_CONFIG : constants_1.TREATMENTS); var wrapUp = function (evaluationResults) { var queue = []; var treatments = {}; var properties = stringify(options); Object.keys(evaluationResults).forEach(function (featureFlagName) { treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, properties, withConfig, methodName, queue); }); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); return treatments; }; var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ? (0, evaluator_1.evaluateFeatures)(log, key, featureFlagNames, attributes, storage) : isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected Promise.resolve(treatmentsNotReady(featureFlagNames)) : treatmentsNotReady(featureFlagNames); return (0, thenable_1.thenable)(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations); } function getTreatmentsWithConfig(key, featureFlagNames, attributes, options) { return getTreatments(key, featureFlagNames, attributes, options, true, constants_1.GET_TREATMENTS_WITH_CONFIG); } function getTreatmentsByFlagSets(key, flagSetNames, attributes, options, withConfig, method, methodName) { if (withConfig === void 0) { withConfig = false; } if (method === void 0) { method = constants_1.TREATMENTS_BY_FLAGSETS; } if (methodName === void 0) { methodName = constants_1.GET_TREATMENTS_BY_FLAG_SETS; } var stopTelemetryTracker = telemetryTracker.trackEval(method); var wrapUp = function (evaluationResults) { var queue = []; var treatments = {}; var properties = stringify(options); Object.keys(evaluationResults).forEach(function (featureFlagName) { treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, properties, withConfig, methodName, queue); }); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); return treatments; }; var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ? (0, evaluator_1.evaluateFeaturesByFlagSets)(log, key, flagSetNames, attributes, storage, methodName) : isAsync ? Promise.resolve({}) : {}; return (0, thenable_1.thenable)(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations); } function getTreatmentsWithConfigByFlagSets(key, flagSetNames, attributes, options) { return getTreatmentsByFlagSets(key, flagSetNames, attributes, options, true, constants_1.TREATMENTS_WITH_CONFIG_BY_FLAGSETS, constants_1.GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS); } function getTreatmentsByFlagSet(key, flagSetName, attributes, options) { return getTreatmentsByFlagSets(key, [flagSetName], attributes, options, false, constants_1.TREATMENTS_BY_FLAGSET, constants_1.GET_TREATMENTS_BY_FLAG_SET); } function getTreatmentsWithConfigByFlagSet(key, flagSetName, attributes, options) { return getTreatmentsByFlagSets(key, [flagSetName], attributes, options, true, constants_1.TREATMENTS_WITH_CONFIG_BY_FLAGSET, constants_1.GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET); } // Internal function function processEvaluation(evaluation, featureFlagName, key, properties, withConfig, invokingMethodName, queue) { var matchingKey = (0, key_1.getMatching)(key); var bucketingKey = (0, key_1.getBucketing)(key); var treatment = evaluation.treatment, label = evaluation.label, changeNumber = evaluation.changeNumber, _a = evaluation.config, config = _a === void 0 ? null : _a, impressionsDisabled = evaluation.impressionsDisabled; log.info(constants_2.IMPRESSION, [featureFlagName, matchingKey, treatment, label]); if ((0, splitExistence_1.validateSplitExistence)(log, readinessManager, featureFlagName, label, invokingMethodName)) { log.info(constants_2.IMPRESSION_QUEUEING); queue.push({ imp: { feature: featureFlagName, keyName: matchingKey, treatment: treatment, time: Date.now(), bucketingKey: bucketingKey, label: label, changeNumber: changeNumber, properties: properties }, disabled: impressionsDisabled }); } if (withConfig) { return { treatment: treatment, config: config }; } return treatment; } function track(key, trafficTypeName, eventTypeId, value, properties, size) { if (size === void 0) { size = 1024; } var stopTelemetryTracker = telemetryTracker.trackEval(constants_1.TRACK); var matchingKey = (0, key_1.getMatching)(key); var timestamp = Date.now(); var eventData = { eventTypeId: eventTypeId, trafficTypeName: trafficTypeName, value: value, timestamp: timestamp, key: matchingKey, properties: properties }; // This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event. (0, trafficTypeExistence_1.validateTrafficTypeExistence)(log, readinessManager, storage.splits, mode, trafficTypeName, constants_1.TRACK_FN_LABEL); var result = eventTracker.track(eventData, size); if ((0, thenable_1.thenable)(result)) { return result.then(function (result) { stopTelemetryTracker(); return result; }); } else { stopTelemetryTracker(); return result; } } return { getTreatment: getTreatment, getTreatmentWithConfig: getTreatmentWithConfig, getTreatments: getTreatments, getTreatmentsWithConfig: getTreatmentsWithConfig, getTreatmentsByFlagSets: getTreatmentsByFlagSets, getTreatmentsWithConfigByFlagSets: getTreatmentsWithConfigByFlagSets, getTreatmentsByFlagSet: getTreatmentsByFlagSet, getTreatmentsWithConfigByFlagSet: getTreatmentsWithConfigByFlagSet, track: track, }; } exports.clientFactory = clientFactory;