@splitsoftware/splitio-commons 2.12.0 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +19 -1
- package/cjs/evaluator/condition/engineUtils.js +2 -2
- package/cjs/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.js +70 -0
- package/cjs/evaluator/fallbackConfigsCalculator/index.js +25 -0
- package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
- package/cjs/evaluator/fallbackTreatmentsCalculator/index.js +21 -32
- package/cjs/evaluator/index.js +73 -48
- package/cjs/evaluator/matchers/whitelist.js +1 -1
- package/cjs/integrations/pluggable.js +1 -1
- package/cjs/listeners/browser.js +4 -3
- package/cjs/listeners/node.js +4 -4
- package/cjs/logger/constants.js +15 -21
- package/cjs/logger/index.js +1 -1
- package/cjs/logger/messages/debug.js +6 -7
- package/cjs/logger/messages/error.js +4 -4
- package/cjs/logger/messages/info.js +2 -4
- package/cjs/logger/messages/warn.js +9 -10
- package/cjs/platform/browser.js +15 -0
- package/cjs/platform/getEventSource/browser.js +8 -0
- package/cjs/platform/getEventSource/eventsource.js +480 -0
- package/cjs/platform/getEventSource/node.js +26 -0
- package/cjs/platform/getFetch/browser.js +9 -0
- package/cjs/platform/getFetch/node.js +27 -0
- package/cjs/platform/getOptions/node.js +25 -0
- package/cjs/platform/node.js +17 -0
- package/cjs/readiness/constants.js +5 -4
- package/cjs/readiness/readinessManager.js +22 -22
- package/cjs/readiness/sdkReadinessManager.js +0 -16
- package/cjs/sdkClient/client.js +9 -35
- package/cjs/sdkClient/clientAttributesDecoration.js +3 -3
- package/cjs/sdkClient/clientInputValidation.js +38 -81
- package/cjs/sdkClient/identity.js +1 -1
- package/cjs/sdkClient/sdkClient.js +4 -49
- package/cjs/sdkClient/sdkLifecycle.js +71 -0
- package/cjs/sdkClient/trackMethod.js +56 -0
- package/cjs/sdkFactory/index.js +13 -50
- package/cjs/sdkManager/index.js +5 -5
- package/cjs/services/authProvider.js +67 -0
- package/cjs/services/secureSplitHttpClient.js +39 -0
- package/cjs/services/splitApi.js +24 -14
- package/cjs/services/splitHttpClient.js +1 -1
- package/cjs/storages/AbstractDefinitionsCacheAsync.js +51 -0
- package/cjs/storages/AbstractDefinitionsCacheSync.js +76 -0
- package/cjs/storages/KeyBuilder.js +16 -16
- package/cjs/storages/KeyBuilderCS.js +17 -17
- package/cjs/storages/KeyBuilderSS.js +16 -16
- package/cjs/storages/getRolloutPlan.js +4 -4
- package/cjs/storages/inLocalStorage/DefinitionsCacheInLocal.js +194 -0
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -1
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +10 -10
- package/cjs/storages/inLocalStorage/index.js +6 -6
- package/cjs/storages/inLocalStorage/validateCache.js +3 -3
- package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +121 -0
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +5 -5
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +5 -5
- package/cjs/storages/inRedis/DefinitionsCacheInRedis.js +243 -0
- package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +5 -5
- package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RedisAdapter.js +8 -8
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +7 -7
- package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +3 -3
- package/cjs/storages/inRedis/index.js +2 -2
- package/cjs/storages/pluggable/DefinitionsCachePluggable.js +212 -0
- package/cjs/storages/pluggable/EventsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +6 -6
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +7 -7
- package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +2 -2
- package/cjs/storages/pluggable/index.js +5 -5
- package/cjs/storages/pluggable/wrapperAdapter.js +1 -1
- package/cjs/storages/setRolloutPlan.js +6 -6
- package/cjs/storages/utils.js +6 -6
- package/cjs/sync/offline/splitsParser/parseCondition.js +1 -1
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +24 -15
- package/cjs/sync/polling/pollingManagerCS.js +18 -18
- package/cjs/sync/polling/pollingManagerSS.js +13 -13
- package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +12 -0
- package/cjs/sync/polling/updaters/{splitChangesUpdater.js → definitionChangesUpdater.js} +72 -64
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +3 -3
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
- package/cjs/sync/streaming/SSEClient/index.js +2 -2
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +1 -1
- package/cjs/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +18 -18
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +2 -2
- package/cjs/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -2
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/parseUtils.js +12 -12
- package/cjs/sync/streaming/pushManager.js +14 -14
- package/cjs/sync/submitters/impressionsSubmitter.js +6 -6
- package/cjs/sync/submitters/submitter.js +1 -1
- package/cjs/sync/submitters/telemetrySubmitter.js +1 -2
- package/cjs/sync/syncManagerOnline.js +9 -6
- package/cjs/trackers/eventTracker.js +10 -12
- package/cjs/trackers/impressionObserver/buildKey.js +1 -1
- package/cjs/trackers/impressionsTracker.js +37 -20
- package/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/Backoff.js +20 -0
- package/cjs/utils/EventEmitter.js +391 -0
- package/cjs/utils/filter/bloomFilter.js +37 -0
- package/cjs/utils/inputValidation/apiKey.js +1 -1
- package/cjs/utils/inputValidation/attribute.js +2 -2
- package/cjs/utils/inputValidation/{split.js → definition.js} +10 -10
- package/cjs/utils/inputValidation/{splitExistence.js → definitionExistence.js} +6 -6
- package/cjs/utils/inputValidation/definitions.js +25 -0
- package/cjs/utils/inputValidation/eventProperties.js +1 -1
- package/cjs/utils/inputValidation/index.js +7 -7
- package/cjs/utils/inputValidation/isOperational.js +4 -4
- package/cjs/utils/inputValidation/target.js +22 -0
- package/cjs/utils/labels/index.js +3 -3
- package/cjs/utils/lang/index.js +1 -1
- package/cjs/utils/lang/sets.js +4 -4
- package/cjs/utils/promise/timeout.js +1 -1
- package/cjs/utils/settingsValidation/splitFilters.js +4 -4
- package/cjs/utils/settingsValidation/url.js +6 -6
- package/esm/evaluator/condition/engineUtils.js +2 -2
- package/esm/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.js +64 -0
- package/esm/evaluator/fallbackConfigsCalculator/index.js +21 -0
- package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
- package/esm/evaluator/fallbackTreatmentsCalculator/index.js +21 -33
- package/esm/evaluator/index.js +72 -48
- package/esm/evaluator/matchers/whitelist.js +1 -1
- package/esm/integrations/pluggable.js +1 -1
- package/esm/listeners/browser.js +4 -3
- package/esm/listeners/node.js +4 -4
- package/esm/logger/constants.js +12 -18
- package/esm/logger/index.js +1 -1
- package/esm/logger/messages/debug.js +5 -6
- package/esm/logger/messages/error.js +3 -3
- package/esm/logger/messages/info.js +1 -3
- package/esm/logger/messages/warn.js +8 -9
- package/esm/platform/browser.js +12 -0
- package/esm/platform/getEventSource/browser.js +4 -0
- package/esm/platform/getEventSource/eventsource.js +480 -0
- package/esm/platform/getEventSource/node.js +20 -0
- package/esm/platform/getFetch/browser.js +5 -0
- package/esm/platform/getFetch/node.js +22 -0
- package/esm/platform/getOptions/node.js +20 -0
- package/esm/platform/node.js +14 -0
- package/esm/readiness/constants.js +4 -3
- package/esm/readiness/readinessManager.js +23 -23
- package/esm/readiness/sdkReadinessManager.js +1 -17
- package/esm/sdkClient/client.js +10 -37
- package/esm/sdkClient/clientAttributesDecoration.js +3 -3
- package/esm/sdkClient/clientInputValidation.js +40 -83
- package/esm/sdkClient/identity.js +1 -1
- package/esm/sdkClient/sdkClient.js +4 -49
- package/esm/sdkClient/sdkLifecycle.js +67 -0
- package/esm/sdkClient/trackMethod.js +52 -0
- package/esm/sdkFactory/index.js +14 -51
- package/esm/sdkManager/index.js +6 -6
- package/esm/services/authProvider.js +63 -0
- package/esm/services/secureSplitHttpClient.js +35 -0
- package/esm/services/splitApi.js +24 -14
- package/esm/services/splitHttpClient.js +1 -1
- package/esm/storages/AbstractDefinitionsCacheAsync.js +48 -0
- package/esm/storages/AbstractDefinitionsCacheSync.js +71 -0
- package/esm/storages/KeyBuilder.js +16 -16
- package/esm/storages/KeyBuilderCS.js +16 -16
- package/esm/storages/KeyBuilderSS.js +15 -15
- package/esm/storages/getRolloutPlan.js +4 -4
- package/esm/storages/inLocalStorage/DefinitionsCacheInLocal.js +191 -0
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +7 -7
- package/esm/storages/inLocalStorage/index.js +6 -6
- package/esm/storages/inLocalStorage/validateCache.js +3 -3
- package/esm/storages/inMemory/DefinitionsCacheInMemory.js +118 -0
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +2 -2
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +5 -5
- package/esm/storages/inRedis/DefinitionsCacheInRedis.js +240 -0
- package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +4 -4
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/RedisAdapter.js +7 -7
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +7 -7
- package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +1 -1
- package/esm/storages/inRedis/index.js +2 -2
- package/esm/storages/pluggable/DefinitionsCachePluggable.js +209 -0
- package/esm/storages/pluggable/EventsCachePluggable.js +1 -1
- package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +5 -5
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/esm/storages/pluggable/TelemetryCachePluggable.js +7 -7
- package/esm/storages/pluggable/UniqueKeysCachePluggable.js +1 -1
- package/esm/storages/pluggable/index.js +4 -4
- package/esm/storages/pluggable/wrapperAdapter.js +1 -1
- package/esm/storages/setRolloutPlan.js +6 -6
- package/esm/storages/utils.js +6 -6
- package/esm/sync/offline/splitsParser/parseCondition.js +1 -1
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +25 -16
- package/esm/sync/polling/pollingManagerCS.js +15 -15
- package/esm/sync/polling/pollingManagerSS.js +13 -13
- package/esm/sync/polling/syncTasks/definitionsSyncTask.js +8 -0
- package/esm/sync/polling/updaters/definitionChangesUpdater.js +200 -0
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +3 -3
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
- package/esm/sync/streaming/SSEClient/index.js +2 -2
- package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +2 -2
- package/esm/sync/streaming/SSEHandler/index.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +17 -17
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -2
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/parseUtils.js +10 -10
- package/esm/sync/streaming/pushManager.js +16 -16
- package/esm/sync/submitters/impressionsSubmitter.js +6 -6
- package/esm/sync/submitters/submitter.js +1 -1
- package/esm/sync/submitters/telemetrySubmitter.js +1 -2
- package/esm/sync/syncManagerOnline.js +8 -5
- package/esm/trackers/eventTracker.js +10 -12
- package/esm/trackers/impressionObserver/buildKey.js +1 -1
- package/esm/trackers/impressionsTracker.js +38 -21
- package/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/Backoff.js +20 -0
- package/esm/utils/EventEmitter.js +387 -0
- package/esm/utils/filter/bloomFilter.js +33 -0
- package/esm/utils/inputValidation/apiKey.js +1 -1
- package/esm/utils/inputValidation/attribute.js +2 -2
- package/esm/utils/inputValidation/{split.js → definition.js} +8 -8
- package/esm/utils/inputValidation/definitionExistence.js +15 -0
- package/esm/utils/inputValidation/definitions.js +21 -0
- package/esm/utils/inputValidation/index.js +3 -3
- package/esm/utils/inputValidation/isOperational.js +4 -4
- package/esm/utils/inputValidation/target.js +18 -0
- package/esm/utils/labels/index.js +2 -2
- package/esm/utils/lang/sets.js +4 -4
- package/esm/utils/promise/timeout.js +1 -1
- package/esm/utils/settingsValidation/splitFilters.js +4 -4
- package/esm/utils/settingsValidation/url.js +6 -6
- package/package.json +15 -6
- package/src/dtos/types.ts +65 -70
- package/src/evaluator/Engine.ts +4 -4
- package/src/evaluator/combiners/and.ts +3 -3
- package/src/evaluator/combiners/ifelseif.ts +2 -2
- package/src/evaluator/condition/engineUtils.ts +2 -2
- package/src/evaluator/condition/index.ts +3 -3
- package/src/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.ts +76 -0
- package/src/evaluator/fallbackConfigsCalculator/index.ts +24 -0
- package/src/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.ts +5 -7
- package/src/evaluator/fallbackTreatmentsCalculator/index.ts +27 -41
- package/src/evaluator/index.ts +86 -51
- package/src/evaluator/matchers/dependency.ts +2 -2
- package/src/evaluator/matchers/matcherTypes.ts +2 -2
- package/src/evaluator/matchers/prerequisites.ts +4 -4
- package/src/evaluator/matchers/rbsegment.ts +2 -2
- package/src/evaluator/matchers/whitelist.ts +2 -2
- package/src/evaluator/matchersTransform/index.ts +2 -2
- package/src/evaluator/matchersTransform/whitelist.ts +2 -2
- package/src/evaluator/parser/index.ts +4 -4
- package/src/evaluator/treatments/index.ts +2 -2
- package/src/evaluator/types.ts +6 -6
- package/src/evaluator/value/index.ts +1 -1
- package/src/integrations/pluggable.ts +1 -1
- package/src/listeners/browser.ts +11 -8
- package/src/listeners/node.ts +2 -5
- package/src/logger/constants.ts +12 -18
- package/src/logger/messages/debug.ts +5 -6
- package/src/logger/messages/error.ts +3 -3
- package/src/logger/messages/info.ts +1 -3
- package/src/logger/messages/warn.ts +8 -9
- package/src/platform/browser.ts +14 -0
- package/src/platform/getEventSource/browser.ts +4 -0
- package/src/platform/getEventSource/eventsource.js +519 -0
- package/src/platform/getEventSource/node.ts +23 -0
- package/src/platform/getFetch/browser.ts +5 -0
- package/src/platform/getFetch/node.ts +27 -0
- package/src/platform/getOptions/node.ts +24 -0
- package/src/platform/node.ts +16 -0
- package/src/readiness/constants.ts +4 -3
- package/src/readiness/readinessManager.ts +22 -22
- package/src/readiness/sdkReadinessManager.ts +1 -16
- package/src/readiness/types.ts +10 -16
- package/src/sdkClient/client.ts +11 -41
- package/src/sdkClient/clientInputValidation.ts +44 -84
- package/src/sdkClient/sdkClient.ts +5 -54
- package/src/sdkClient/sdkLifecycle.ts +79 -0
- package/src/sdkClient/trackMethod.ts +59 -0
- package/src/sdkFactory/index.ts +15 -59
- package/src/sdkFactory/types.ts +19 -16
- package/src/sdkManager/index.ts +15 -15
- package/src/services/authProvider.ts +86 -0
- package/src/services/secureSplitHttpClient.ts +44 -0
- package/src/services/splitApi.ts +14 -2
- package/src/services/types.ts +7 -2
- package/src/storages/AbstractDefinitionsCacheAsync.ts +63 -0
- package/src/storages/AbstractDefinitionsCacheSync.ts +95 -0
- package/src/storages/KeyBuilder.ts +6 -6
- package/src/storages/KeyBuilderCS.ts +6 -6
- package/src/storages/KeyBuilderSS.ts +2 -2
- package/src/storages/getRolloutPlan.ts +3 -3
- package/src/storages/inLocalStorage/DefinitionsCacheInLocal.ts +234 -0
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +8 -8
- package/src/storages/inLocalStorage/index.ts +6 -6
- package/src/storages/inLocalStorage/validateCache.ts +4 -4
- package/src/storages/inMemory/DefinitionsCacheInMemory.ts +130 -0
- package/src/storages/inMemory/InMemoryStorage.ts +4 -4
- package/src/storages/inMemory/InMemoryStorageCS.ts +5 -5
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +3 -3
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +1 -1
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +5 -5
- package/src/storages/inRedis/{SplitsCacheInRedis.ts → DefinitionsCacheInRedis.ts} +69 -69
- package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +2 -2
- package/src/storages/inRedis/index.ts +2 -2
- package/src/storages/pluggable/DefinitionsCachePluggable.ts +230 -0
- package/src/storages/pluggable/RBSegmentsCachePluggable.ts +2 -2
- package/src/storages/pluggable/index.ts +2 -2
- package/src/storages/setRolloutPlan.ts +7 -7
- package/src/storages/types.ts +34 -29
- package/src/sync/offline/splitsParser/parseCondition.ts +2 -2
- package/src/sync/offline/splitsParser/splitsParserFromSettings.ts +3 -3
- package/src/sync/offline/splitsParser/types.ts +6 -3
- package/src/sync/offline/syncManagerOffline.ts +2 -2
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +14 -14
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +58 -23
- package/src/sync/polling/fetchers/types.ts +5 -3
- package/src/sync/polling/pollingManagerCS.ts +16 -14
- package/src/sync/polling/pollingManagerSS.ts +15 -13
- package/src/sync/polling/syncTasks/{splitsSyncTask.ts → definitionsSyncTask.ts} +11 -12
- package/src/sync/polling/types.ts +3 -3
- package/src/sync/polling/updaters/definitionChangesUpdater.ts +239 -0
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +3 -3
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +7 -7
- package/src/sync/streaming/AuthClient/index.ts +2 -2
- package/src/sync/streaming/AuthClient/types.ts +14 -11
- package/src/sync/streaming/SSEClient/index.ts +2 -2
- package/src/sync/streaming/SSEClient/types.ts +2 -2
- package/src/sync/streaming/SSEHandler/NotificationKeeper.ts +2 -2
- package/src/sync/streaming/SSEHandler/index.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.ts → DefinitionsUpdateWorker.ts} +21 -21
- package/src/sync/streaming/constants.ts +2 -2
- package/src/sync/streaming/parseUtils.ts +12 -12
- package/src/sync/streaming/pushManager.ts +18 -18
- package/src/sync/streaming/types.ts +2 -2
- package/src/sync/submitters/impressionsSubmitter.ts +9 -9
- package/src/sync/submitters/telemetrySubmitter.ts +1 -2
- package/src/sync/submitters/types.ts +3 -0
- package/src/sync/syncManagerOnline.ts +9 -5
- package/src/trackers/eventTracker.ts +7 -10
- package/src/trackers/impressionsTracker.ts +42 -26
- package/src/trackers/types.ts +3 -1
- package/src/utils/Backoff.ts +21 -0
- package/src/utils/EventEmitter.js +444 -0
- package/src/utils/filter/bloomFilter.ts +38 -0
- package/src/utils/inputValidation/definition.ts +27 -0
- package/src/utils/inputValidation/definitionExistence.ts +19 -0
- package/src/utils/inputValidation/definitions.ts +21 -0
- package/src/utils/inputValidation/index.ts +3 -3
- package/src/utils/inputValidation/isOperational.ts +4 -4
- package/src/utils/inputValidation/target.ts +21 -0
- package/src/utils/inputValidation/trafficTypeExistence.ts +2 -2
- package/src/utils/jwt/types.ts +1 -1
- package/src/utils/labels/index.ts +2 -2
- package/src/utils/lang/sets.ts +4 -2
- package/src/utils/settingsValidation/splitFilters.ts +3 -3
- package/src/utils/settingsValidation/url.ts +1 -1
- package/types/splitio.d.ts +222 -11
- package/cjs/storages/AbstractSplitsCacheAsync.js +0 -51
- package/cjs/storages/AbstractSplitsCacheSync.js +0 -76
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -194
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -121
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +0 -243
- package/cjs/storages/pluggable/SplitsCachePluggable.js +0 -212
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +0 -13
- package/cjs/utils/inputValidation/splits.js +0 -25
- package/esm/storages/AbstractSplitsCacheAsync.js +0 -48
- package/esm/storages/AbstractSplitsCacheSync.js +0 -71
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -191
- package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -118
- package/esm/storages/inRedis/SplitsCacheInRedis.js +0 -240
- package/esm/storages/pluggable/SplitsCachePluggable.js +0 -209
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +0 -9
- package/esm/sync/polling/updaters/splitChangesUpdater.js +0 -192
- package/esm/utils/inputValidation/splitExistence.js +0 -15
- package/esm/utils/inputValidation/splits.js +0 -21
- package/src/storages/AbstractSplitsCacheAsync.ts +0 -63
- package/src/storages/AbstractSplitsCacheSync.ts +0 -95
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -234
- package/src/storages/inMemory/SplitsCacheInMemory.ts +0 -130
- package/src/storages/pluggable/SplitsCachePluggable.ts +0 -230
- package/src/sync/polling/updaters/splitChangesUpdater.ts +0 -230
- package/src/utils/inputValidation/split.ts +0 -27
- package/src/utils/inputValidation/splitExistence.ts +0 -19
- package/src/utils/inputValidation/splits.ts +0 -21
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
2
|
+
import { KeyBuilder } from '../KeyBuilder';
|
|
3
|
+
import { IPluggableStorageWrapper } from '../types';
|
|
4
|
+
import { ILogger } from '../../logger/types';
|
|
5
|
+
import { IDefinition, ISplitFiltersValidation } from '../../dtos/types';
|
|
6
|
+
import { LOG_PREFIX } from './constants';
|
|
7
|
+
import { AbstractDefinitionsCacheAsync } from '../AbstractDefinitionsCacheAsync';
|
|
8
|
+
import { returnDifference } from '../../utils/lang/sets';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* IDefinitionsCacheAsync implementation for pluggable storages.
|
|
12
|
+
*/
|
|
13
|
+
export class DefinitionsCachePluggable extends AbstractDefinitionsCacheAsync {
|
|
14
|
+
|
|
15
|
+
private readonly log: ILogger;
|
|
16
|
+
private readonly keys: KeyBuilder;
|
|
17
|
+
private readonly wrapper: IPluggableStorageWrapper;
|
|
18
|
+
private readonly setsFilter: string[];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a DefinitionsCache that uses a storage wrapper.
|
|
22
|
+
* @param log - Logger instance.
|
|
23
|
+
* @param keys - Key builder.
|
|
24
|
+
* @param wrapper - Adapted wrapper storage.
|
|
25
|
+
*/
|
|
26
|
+
constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper, splitFiltersValidation?: ISplitFiltersValidation) {
|
|
27
|
+
super();
|
|
28
|
+
this.log = log;
|
|
29
|
+
this.keys = keys;
|
|
30
|
+
this.wrapper = wrapper;
|
|
31
|
+
this.setsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private _decrementCounts(definition: IDefinition) {
|
|
35
|
+
const ttKey = this.keys.buildTrafficTypeKey(definition.trafficTypeName);
|
|
36
|
+
return this.wrapper.decr(ttKey).then(count => {
|
|
37
|
+
if (count === 0) return this.wrapper.del(ttKey);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private _incrementCounts(definition: IDefinition) {
|
|
42
|
+
const ttKey = this.keys.buildTrafficTypeKey(definition.trafficTypeName);
|
|
43
|
+
return this.wrapper.incr(ttKey);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private _updateSets(definitionName: string, setsOfRemovedDefinition?: string[] | null, setsOfAddedDefinition?: string[] | null) {
|
|
47
|
+
const removeFromSets = returnDifference(setsOfRemovedDefinition, setsOfAddedDefinition);
|
|
48
|
+
|
|
49
|
+
let addToSets = returnDifference(setsOfAddedDefinition, setsOfRemovedDefinition);
|
|
50
|
+
if (this.setsFilter.length > 0) {
|
|
51
|
+
addToSets = addToSets.filter(set => {
|
|
52
|
+
return this.setsFilter.some(filterSet => filterSet === set);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const items = [definitionName];
|
|
57
|
+
|
|
58
|
+
return Promise.all([
|
|
59
|
+
...removeFromSets.map(setName => this.wrapper.removeItems(this.keys.buildSetKey(setName), items)),
|
|
60
|
+
...addToSets.map(setName => this.wrapper.addItems(this.keys.buildSetKey(setName), items))
|
|
61
|
+
]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Add a given definition.
|
|
66
|
+
* The returned promise is resolved when the operation success
|
|
67
|
+
* or rejected if it fails (e.g., wrapper operation fails)
|
|
68
|
+
*/
|
|
69
|
+
add(definition: IDefinition): Promise<boolean> {
|
|
70
|
+
const name = definition.name;
|
|
71
|
+
const definitionKey = this.keys.buildDefinitionKey(name);
|
|
72
|
+
return this.wrapper.get(definitionKey).then(definitionFromStorage => {
|
|
73
|
+
|
|
74
|
+
// handling parsing error
|
|
75
|
+
let parsedPreviousDefinition: IDefinition, stringifiedNewDefinition;
|
|
76
|
+
try {
|
|
77
|
+
parsedPreviousDefinition = definitionFromStorage ? JSON.parse(definitionFromStorage) : undefined;
|
|
78
|
+
stringifiedNewDefinition = JSON.stringify(definition);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
throw new Error('Error parsing feature flag definition: ' + e);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return this.wrapper.set(definitionKey, stringifiedNewDefinition).then(() => {
|
|
84
|
+
// avoid unnecessary increment/decrement operations
|
|
85
|
+
if (parsedPreviousDefinition && parsedPreviousDefinition.trafficTypeName === definition.trafficTypeName) return;
|
|
86
|
+
|
|
87
|
+
// update traffic type counts
|
|
88
|
+
return this._incrementCounts(definition).then(() => {
|
|
89
|
+
if (parsedPreviousDefinition) return this._decrementCounts(parsedPreviousDefinition);
|
|
90
|
+
});
|
|
91
|
+
}).then(() => this._updateSets(name, parsedPreviousDefinition && parsedPreviousDefinition.sets, definition.sets));
|
|
92
|
+
}).then(() => true);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Remove a given definition.
|
|
97
|
+
* The returned promise is resolved when the operation success, with a boolean indicating if the definition existed or not.
|
|
98
|
+
* or rejected if it fails (e.g., wrapper operation fails).
|
|
99
|
+
*/
|
|
100
|
+
remove(name: string) {
|
|
101
|
+
return this.get(name).then((definition) => {
|
|
102
|
+
if (definition) {
|
|
103
|
+
return this._decrementCounts(definition).then(() => this._updateSets(name, definition.sets));
|
|
104
|
+
}
|
|
105
|
+
}).then(() => {
|
|
106
|
+
return this.wrapper.del(this.keys.buildDefinitionKey(name));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get definition.
|
|
112
|
+
* The returned promise is resolved with the definition or null if it's not defined,
|
|
113
|
+
* or rejected if wrapper operation fails.
|
|
114
|
+
*/
|
|
115
|
+
get(name: string): Promise<IDefinition | null> {
|
|
116
|
+
return this.wrapper.get(this.keys.buildDefinitionKey(name))
|
|
117
|
+
.then(maybeDefinition => maybeDefinition && JSON.parse(maybeDefinition));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get list of definitions.
|
|
122
|
+
* The returned promise is resolved with a map of names to their definition or null if it's not defined,
|
|
123
|
+
* or rejected if wrapper operation fails.
|
|
124
|
+
*/
|
|
125
|
+
getMany(names: string[]): Promise<Record<string, IDefinition | null>> {
|
|
126
|
+
const keys = names.map(name => this.keys.buildDefinitionKey(name));
|
|
127
|
+
|
|
128
|
+
return this.wrapper.getMany(keys).then(stringifiedDefinitions => {
|
|
129
|
+
const definitions: Record<string, IDefinition | null> = {};
|
|
130
|
+
names.forEach((name, idx) => {
|
|
131
|
+
const definition = stringifiedDefinitions[idx];
|
|
132
|
+
definitions[name] = definition && JSON.parse(definition);
|
|
133
|
+
});
|
|
134
|
+
return Promise.resolve(definitions);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get list of all definitions.
|
|
140
|
+
* The returned promise is resolved with the list of definitions,
|
|
141
|
+
* or rejected if wrapper operation fails.
|
|
142
|
+
*/
|
|
143
|
+
getAll(): Promise<IDefinition[]> {
|
|
144
|
+
return this.wrapper.getKeysByPrefix(this.keys.buildDefinitionKeyPrefix())
|
|
145
|
+
.then((listOfKeys) => this.wrapper.getMany(listOfKeys))
|
|
146
|
+
.then((definitions) => definitions.map((definition) => {
|
|
147
|
+
return JSON.parse(definition as string);
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get list of definition names.
|
|
153
|
+
* The returned promise is resolved with the list of names,
|
|
154
|
+
* or rejected if wrapper operation fails.
|
|
155
|
+
*/
|
|
156
|
+
getNames(): Promise<string[]> {
|
|
157
|
+
return this.wrapper.getKeysByPrefix(this.keys.buildDefinitionKeyPrefix()).then(
|
|
158
|
+
(listOfKeys) => listOfKeys.map(this.keys.extractKey)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get list of definition names related to a given list of set names.
|
|
164
|
+
* The returned promise is resolved with the list of names per set.
|
|
165
|
+
* It never rejects (If there is a wrapper error for some set, an empty set is returned for it).
|
|
166
|
+
*/
|
|
167
|
+
getNamesBySets(sets: string[]): Promise<Set<string>[]> {
|
|
168
|
+
return Promise.all(sets.map(set => {
|
|
169
|
+
const setKey = this.keys.buildSetKey(set);
|
|
170
|
+
return this.wrapper.getItems(setKey).catch(() => []);
|
|
171
|
+
})).then(namesBySets => namesBySets.map(namesBySet => new Set(namesBySet)));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Check traffic type existence.
|
|
176
|
+
* The returned promise is resolved with a boolean indicating whether the TT exist or not.
|
|
177
|
+
* In case of wrapper operation failures, the promise resolves with a true value, assuming that the TT might exist.
|
|
178
|
+
* It will never be rejected.
|
|
179
|
+
*/
|
|
180
|
+
trafficTypeExists(trafficType: string): Promise<boolean> {
|
|
181
|
+
// If there is a number there should be > 0, otherwise the TT is considered as not existent.
|
|
182
|
+
return this.wrapper.get(this.keys.buildTrafficTypeKey(trafficType))
|
|
183
|
+
.then((ttCount: string | null | number) => {
|
|
184
|
+
if (ttCount === null) return false; // if entry doesn't exist, means that TT doesn't exist
|
|
185
|
+
|
|
186
|
+
ttCount = parseInt(ttCount as string, 10);
|
|
187
|
+
if (!isFiniteNumber(ttCount) || ttCount < 0) {
|
|
188
|
+
this.log.info(LOG_PREFIX + `Could not validate traffic type existence of ${trafficType} due to data corruption of some sorts.`);
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return ttCount > 0;
|
|
193
|
+
}).catch(e => {
|
|
194
|
+
this.log.error(LOG_PREFIX + `Could not validate traffic type existence of ${trafficType} due to an error: ${e}.`);
|
|
195
|
+
// If there is an error, bypass the validation so the event can get tracked.
|
|
196
|
+
return true;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Set till number.
|
|
202
|
+
* The returned promise is resolved when the operation success,
|
|
203
|
+
* or rejected if it fails (e.g., wrapper operation fails).
|
|
204
|
+
*/
|
|
205
|
+
setChangeNumber(changeNumber: number) {
|
|
206
|
+
return this.wrapper.set(this.keys.buildDefinitionsTillKey(), changeNumber + '');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get till number or -1 if it's not defined.
|
|
211
|
+
* The returned promise is resolved with the changeNumber or -1 if it doesn't exist or a wrapper operation fails.
|
|
212
|
+
* The promise will never be rejected.
|
|
213
|
+
*/
|
|
214
|
+
getChangeNumber(): Promise<number> {
|
|
215
|
+
return this.wrapper.get(this.keys.buildDefinitionsTillKey()).then((value) => {
|
|
216
|
+
const i = parseInt(value as string, 10);
|
|
217
|
+
|
|
218
|
+
return isNaNNumber(i) ? -1 : i;
|
|
219
|
+
}).catch((e) => {
|
|
220
|
+
this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
|
|
221
|
+
return -1;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// @TODO implement if required by DataLoader or producer mode
|
|
226
|
+
clear() {
|
|
227
|
+
return Promise.resolve(true);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
}
|
|
@@ -36,7 +36,7 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
39
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean> {
|
|
40
40
|
return Promise.all([
|
|
41
41
|
this.setChangeNumber(changeNumber),
|
|
42
42
|
Promise.all(toAdd.map(toAdd => {
|
|
@@ -45,7 +45,7 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
|
|
|
45
45
|
return this.wrapper.set(key, stringifiedNewRBSegment).then(() => true);
|
|
46
46
|
})),
|
|
47
47
|
Promise.all(toRemove.map(toRemove => {
|
|
48
|
-
const key = this.keys.buildRBSegmentKey(toRemove
|
|
48
|
+
const key = this.keys.buildRBSegmentKey(toRemove);
|
|
49
49
|
return this.wrapper.del(key);
|
|
50
50
|
}))
|
|
51
51
|
]).then(([, added, removed]) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IPluggableStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams, ITelemetryCacheAsync } from '../types';
|
|
2
2
|
|
|
3
3
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
4
|
-
import {
|
|
4
|
+
import { DefinitionsCachePluggable } from './DefinitionsCachePluggable';
|
|
5
5
|
import { SegmentsCachePluggable } from './SegmentsCachePluggable';
|
|
6
6
|
import { ImpressionsCachePluggable } from './ImpressionsCachePluggable';
|
|
7
7
|
import { EventsCachePluggable } from './EventsCachePluggable';
|
|
@@ -118,7 +118,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
return {
|
|
121
|
-
|
|
121
|
+
definitions: new DefinitionsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
122
122
|
rbSegments: new RBSegmentsCachePluggable(log, keys, wrapper),
|
|
123
123
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
124
124
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import SplitIO from '../../types/splitio';
|
|
2
|
-
import { IRBSegmentsCacheSync, ISegmentsCacheSync,
|
|
2
|
+
import { IRBSegmentsCacheSync, ISegmentsCacheSync, IDefinitionsCacheSync } from './types';
|
|
3
3
|
import { ILogger } from '../logger/types';
|
|
4
4
|
import { isObject } from '../utils/lang';
|
|
5
5
|
import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
@@ -27,20 +27,20 @@ export function validateRolloutPlan(log: ILogger, settings: SplitIO.ISettings):
|
|
|
27
27
|
* If `matchingKey` is provided, the storage is handled as a client-side storage (segments and largeSegments are instances of MySegmentsCache).
|
|
28
28
|
* Otherwise, the storage is handled as a server-side storage (segments is an instance of SegmentsCache).
|
|
29
29
|
*/
|
|
30
|
-
export function setRolloutPlan(log: ILogger, rolloutPlan: RolloutPlan, storage: {
|
|
31
|
-
const {
|
|
30
|
+
export function setRolloutPlan(log: ILogger, rolloutPlan: RolloutPlan, storage: { definitions?: IDefinitionsCacheSync, rbSegments?: IRBSegmentsCacheSync, segments: ISegmentsCacheSync, largeSegments?: ISegmentsCacheSync }, matchingKey?: string) {
|
|
31
|
+
const { definitions, rbSegments, segments, largeSegments } = storage;
|
|
32
32
|
const { splitChanges: { ff, rbs } } = rolloutPlan;
|
|
33
33
|
|
|
34
34
|
log.debug(`storage: set feature flags and segments${matchingKey ? ` for key ${matchingKey}` : ''}`);
|
|
35
35
|
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
if (definitions && ff) {
|
|
37
|
+
definitions.clear();
|
|
38
|
+
definitions.update(ff.d || [], [], ff.t);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (rbSegments && rbs) {
|
|
42
42
|
rbSegments.clear();
|
|
43
|
-
rbSegments.update(rbs.d, [], rbs.t);
|
|
43
|
+
rbSegments.update(rbs.d || [], [], rbs.t);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const segmentChanges = rolloutPlan.segmentChanges;
|
package/src/storages/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import SplitIO from '../../types/splitio';
|
|
2
|
-
import { MaybeThenable,
|
|
2
|
+
import { MaybeThenable, IDefinition, IRBSegment, IMySegmentsResponse, IMembershipsResponse, ISegmentChangesResponse } from '../dtos/types';
|
|
3
|
+
import { ISplitChangesResponse } from '../sync/polling/fetchers/splitChangesFetcher';
|
|
3
4
|
import { MySegmentsData } from '../sync/polling/types';
|
|
4
5
|
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
5
6
|
import { ISettings } from '../types';
|
|
@@ -193,55 +194,55 @@ export interface IPluggableStorageWrapper {
|
|
|
193
194
|
|
|
194
195
|
/** Splits cache */
|
|
195
196
|
|
|
196
|
-
export interface
|
|
197
|
-
update(toAdd:
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
export interface IDefinitionsCacheBase {
|
|
198
|
+
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): MaybeThenable<boolean>,
|
|
199
|
+
get(name: string): MaybeThenable<IDefinition | null>,
|
|
200
|
+
getMany(names: string[]): MaybeThenable<Record<string, IDefinition | null>>, // `fetchMany` in spec
|
|
200
201
|
// should never reject or throw an exception. Instead return -1 by default, assuming no splits are present in the storage.
|
|
201
202
|
getChangeNumber(): MaybeThenable<number>,
|
|
202
|
-
getAll(): MaybeThenable<
|
|
203
|
-
|
|
203
|
+
getAll(): MaybeThenable<IDefinition[]>,
|
|
204
|
+
getNames(): MaybeThenable<string[]>,
|
|
204
205
|
// should never reject or throw an exception. Instead return true by default, asssuming the TT might exist.
|
|
205
206
|
trafficTypeExists(trafficType: string): MaybeThenable<boolean>,
|
|
206
207
|
// only for Client-Side. Returns true if the storage is not synchronized yet (getChangeNumber() === -1) or contains a FF using segments or large segments
|
|
207
208
|
usesSegments(): MaybeThenable<boolean>,
|
|
208
209
|
clear(): MaybeThenable<boolean | void>,
|
|
209
210
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>,
|
|
210
|
-
|
|
211
|
+
getNamesBySets(sets: string[]): MaybeThenable<Set<string>[]>
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
export interface
|
|
214
|
-
update(toAdd:
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
export interface IDefinitionsCacheSync extends IDefinitionsCacheBase {
|
|
215
|
+
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): boolean,
|
|
216
|
+
get(name: string): IDefinition | null,
|
|
217
|
+
getMany(names: string[]): Record<string, IDefinition | null>,
|
|
217
218
|
getChangeNumber(): number,
|
|
218
|
-
getAll():
|
|
219
|
-
|
|
219
|
+
getAll(): IDefinition[],
|
|
220
|
+
getNames(): string[],
|
|
220
221
|
trafficTypeExists(trafficType: string): boolean,
|
|
221
222
|
usesSegments(): boolean,
|
|
222
223
|
clear(): void,
|
|
223
224
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
|
|
224
|
-
|
|
225
|
+
getNamesBySets(sets: string[]): Set<string>[]
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
export interface
|
|
228
|
-
update(toAdd:
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
export interface IDefinitionsCacheAsync extends IDefinitionsCacheBase {
|
|
229
|
+
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): Promise<boolean>,
|
|
230
|
+
get(name: string): Promise<IDefinition | null>,
|
|
231
|
+
getMany(names: string[]): Promise<Record<string, IDefinition | null>>,
|
|
231
232
|
getChangeNumber(): Promise<number>,
|
|
232
|
-
getAll(): Promise<
|
|
233
|
-
|
|
233
|
+
getAll(): Promise<IDefinition[]>,
|
|
234
|
+
getNames(): Promise<string[]>,
|
|
234
235
|
trafficTypeExists(trafficType: string): Promise<boolean>,
|
|
235
236
|
usesSegments(): Promise<boolean>,
|
|
236
237
|
clear(): Promise<boolean | void>,
|
|
237
238
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
|
|
238
|
-
|
|
239
|
+
getNamesBySets(sets: string[]): Promise<Set<string>[]>
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
/** Rule-Based Segments cache */
|
|
242
243
|
|
|
243
244
|
export interface IRBSegmentsCacheBase {
|
|
244
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
245
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): MaybeThenable<boolean>,
|
|
245
246
|
get(name: string): MaybeThenable<IRBSegment | null>,
|
|
246
247
|
getChangeNumber(): MaybeThenable<number>,
|
|
247
248
|
clear(): MaybeThenable<boolean | void>,
|
|
@@ -249,7 +250,7 @@ export interface IRBSegmentsCacheBase {
|
|
|
249
250
|
}
|
|
250
251
|
|
|
251
252
|
export interface IRBSegmentsCacheSync extends IRBSegmentsCacheBase {
|
|
252
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
253
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): boolean,
|
|
253
254
|
get(name: string): IRBSegment | null,
|
|
254
255
|
getChangeNumber(): number,
|
|
255
256
|
getAll(): IRBSegment[],
|
|
@@ -260,7 +261,7 @@ export interface IRBSegmentsCacheSync extends IRBSegmentsCacheBase {
|
|
|
260
261
|
}
|
|
261
262
|
|
|
262
263
|
export interface IRBSegmentsCacheAsync extends IRBSegmentsCacheBase {
|
|
263
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
264
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean>,
|
|
264
265
|
get(name: string): Promise<IRBSegment | null>,
|
|
265
266
|
getChangeNumber(): Promise<number>,
|
|
266
267
|
clear(): Promise<boolean | void>,
|
|
@@ -465,7 +466,7 @@ export interface ITelemetryCacheAsync extends ITelemetryEvaluationProducerAsync,
|
|
|
465
466
|
*/
|
|
466
467
|
|
|
467
468
|
export interface IStorageBase<
|
|
468
|
-
|
|
469
|
+
TDefinitionsCache extends IDefinitionsCacheBase = IDefinitionsCacheBase,
|
|
469
470
|
TRBSegmentsCache extends IRBSegmentsCacheBase = IRBSegmentsCacheBase,
|
|
470
471
|
TSegmentsCache extends ISegmentsCacheBase = ISegmentsCacheBase,
|
|
471
472
|
TImpressionsCache extends IImpressionsCacheBase = IImpressionsCacheBase,
|
|
@@ -474,7 +475,7 @@ export interface IStorageBase<
|
|
|
474
475
|
TTelemetryCache extends ITelemetryCacheSync | ITelemetryCacheAsync = ITelemetryCacheSync | ITelemetryCacheAsync,
|
|
475
476
|
TUniqueKeysCache extends IUniqueKeysCacheBase = IUniqueKeysCacheBase
|
|
476
477
|
> {
|
|
477
|
-
|
|
478
|
+
definitions: TDefinitionsCache,
|
|
478
479
|
rbSegments: TRBSegmentsCache,
|
|
479
480
|
segments: TSegmentsCache,
|
|
480
481
|
largeSegments?: TSegmentsCache,
|
|
@@ -489,7 +490,7 @@ export interface IStorageBase<
|
|
|
489
490
|
}
|
|
490
491
|
|
|
491
492
|
export interface IStorageSync extends IStorageBase<
|
|
492
|
-
|
|
493
|
+
IDefinitionsCacheSync,
|
|
493
494
|
IRBSegmentsCacheSync,
|
|
494
495
|
ISegmentsCacheSync,
|
|
495
496
|
IImpressionsCacheSync,
|
|
@@ -504,7 +505,7 @@ export interface IStorageSync extends IStorageBase<
|
|
|
504
505
|
}
|
|
505
506
|
|
|
506
507
|
export interface IStorageAsync extends IStorageBase<
|
|
507
|
-
|
|
508
|
+
IDefinitionsCacheAsync,
|
|
508
509
|
IRBSegmentsCacheAsync,
|
|
509
510
|
ISegmentsCacheAsync,
|
|
510
511
|
IImpressionsCacheAsync | IImpressionsCacheSync,
|
|
@@ -527,6 +528,10 @@ export interface IStorageFactoryParams {
|
|
|
527
528
|
* For emitting SDK_READY_FROM_CACHE event in consumer mode with Redis to allow immediate evaluations
|
|
528
529
|
*/
|
|
529
530
|
onReadyFromCacheCb: () => void,
|
|
531
|
+
/**
|
|
532
|
+
* If true, telemetry will not be recorded.
|
|
533
|
+
*/
|
|
534
|
+
disableTelemetry?: boolean,
|
|
530
535
|
}
|
|
531
536
|
|
|
532
537
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDefinitionCondition } from '../../../dtos/types';
|
|
2
2
|
import { isString } from '../../../utils/lang';
|
|
3
3
|
|
|
4
4
|
export interface IMockSplitEntry {
|
|
@@ -7,7 +7,7 @@ export interface IMockSplitEntry {
|
|
|
7
7
|
config?: string
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export function parseCondition(data: IMockSplitEntry):
|
|
10
|
+
export function parseCondition(data: IMockSplitEntry): IDefinitionCondition {
|
|
11
11
|
const treatment = data.treatment;
|
|
12
12
|
|
|
13
13
|
if (data.keys) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDefinitionPartial } from './types';
|
|
2
2
|
import SplitIO from '../../../../types/splitio';
|
|
3
3
|
import { isObject, forOwn, merge } from '../../../utils/lang';
|
|
4
4
|
import { parseCondition } from './parseCondition';
|
|
@@ -41,12 +41,12 @@ export function splitsParserFromSettingsFactory() {
|
|
|
41
41
|
*
|
|
42
42
|
* @param settings - validated object with mocked features mapping.
|
|
43
43
|
*/
|
|
44
|
-
return function splitsParserFromSettings(settings: Pick<SplitIO.ISettings, 'features'>): false | Record<string,
|
|
44
|
+
return function splitsParserFromSettings(settings: Pick<SplitIO.ISettings, 'features'>): false | Record<string, IDefinitionPartial> {
|
|
45
45
|
const features = settings.features as SplitIO.MockedFeaturesMap || {};
|
|
46
46
|
|
|
47
47
|
if (!mockUpdated(features)) return false;
|
|
48
48
|
|
|
49
|
-
const splitObjects: Record<string,
|
|
49
|
+
const splitObjects: Record<string, IDefinitionPartial> = {};
|
|
50
50
|
|
|
51
51
|
forOwn(features, (data, splitName) => {
|
|
52
52
|
let treatment = data;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDefinition } from '../../../dtos/types';
|
|
2
2
|
import { ISettings } from '../../../types';
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
export type
|
|
4
|
+
// Split definition used in offline mode
|
|
5
|
+
export type IDefinitionPartial = Pick<IDefinition, 'conditions' | 'configurations' | 'trafficTypeName'>
|
|
6
|
+
|
|
7
|
+
// Analog to `IDefinitionChangesFetcher` used by `definitionChangesUpdaterFactory`
|
|
8
|
+
export type IDefinitionsParser = (settings: ISettings) => false | Record<string, IDefinitionPartial>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ISyncManagerCS } from '../types';
|
|
2
2
|
import { fromObjectSyncTaskFactory } from './syncTasks/fromObjectSyncTask';
|
|
3
3
|
import { objectAssign } from '../../utils/lang/objectAssign';
|
|
4
|
-
import {
|
|
4
|
+
import { IDefinitionsParser } from './splitsParser/types';
|
|
5
5
|
import { IReadinessManager } from '../../readiness/types';
|
|
6
6
|
import { SDK_SEGMENTS_ARRIVED } from '../../readiness/constants';
|
|
7
7
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
@@ -17,7 +17,7 @@ function flush() {
|
|
|
17
17
|
* @param splitsParser - e.g., `splitsParserFromFile`, `splitsParserFromSettings`.
|
|
18
18
|
*/
|
|
19
19
|
export function syncManagerOfflineFactory(
|
|
20
|
-
splitsParserFactory: () =>
|
|
20
|
+
splitsParserFactory: () => IDefinitionsParser
|
|
21
21
|
): (params: ISdkFactoryContextSync) => ISyncManagerCS {
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { forOwn } from '../../../utils/lang';
|
|
2
2
|
import { IReadinessManager } from '../../../readiness/types';
|
|
3
3
|
import { IStorageSync } from '../../../storages/types';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { IDefinitionsParser, IDefinitionPartial } from '../splitsParser/types';
|
|
5
|
+
import { IDefinition } from '../../../dtos/types';
|
|
6
6
|
import { syncTaskFactory } from '../../syncTask';
|
|
7
7
|
import { ISyncTask } from '../../types';
|
|
8
8
|
import { ISettings } from '../../../types';
|
|
9
9
|
import { CONTROL } from '../../../utils/constants';
|
|
10
|
-
import {
|
|
10
|
+
import { SDK_DEFINITIONS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_DEFINITIONS_CACHE_LOADED, FLAGS_UPDATE, SEGMENTS_UPDATE } from '../../../readiness/constants';
|
|
11
11
|
import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/constants';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Offline equivalent of `splitChangesUpdaterFactory`
|
|
15
15
|
*/
|
|
16
16
|
export function fromObjectUpdaterFactory(
|
|
17
|
-
splitsParser:
|
|
18
|
-
storage: Pick<IStorageSync, '
|
|
17
|
+
splitsParser: IDefinitionsParser,
|
|
18
|
+
storage: Pick<IStorageSync, 'definitions' | 'validateCache'>,
|
|
19
19
|
readiness: IReadinessManager,
|
|
20
20
|
settings: ISettings,
|
|
21
21
|
): () => Promise<boolean> {
|
|
22
22
|
|
|
23
|
-
const log = settings.log,
|
|
23
|
+
const log = settings.log, definitions = storage.definitions;
|
|
24
24
|
let startingUp = true;
|
|
25
25
|
|
|
26
26
|
return function objectUpdater() {
|
|
27
|
-
const splits:
|
|
27
|
+
const splits: IDefinition[] = [];
|
|
28
28
|
let loadError = null;
|
|
29
|
-
let splitsMock: false | Record<string,
|
|
29
|
+
let splitsMock: false | Record<string, IDefinitionPartial> = {};
|
|
30
30
|
try {
|
|
31
31
|
splitsMock = splitsParser(settings);
|
|
32
32
|
} catch (err) {
|
|
@@ -52,17 +52,17 @@ export function fromObjectUpdaterFactory(
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
return Promise.all([
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
definitions.clear(), // required to sync removed splits from mock
|
|
56
|
+
definitions.update(splits, [], Date.now())
|
|
57
57
|
]).then(() => {
|
|
58
|
-
readiness.
|
|
58
|
+
readiness.definitions.emit(SDK_DEFINITIONS_ARRIVED, { type: FLAGS_UPDATE, names: [] });
|
|
59
59
|
|
|
60
60
|
if (startingUp) {
|
|
61
61
|
startingUp = false;
|
|
62
62
|
Promise.resolve(storage.validateCache ? storage.validateCache() : { initialCacheLoad: true /* Fallback: assume initial load when validateCache doesn't exist */ }).then((cacheMetadata) => {
|
|
63
63
|
// Emits SDK_READY_FROM_CACHE
|
|
64
64
|
if (!cacheMetadata.initialCacheLoad) {
|
|
65
|
-
readiness.
|
|
65
|
+
readiness.definitions.emit(SDK_DEFINITIONS_CACHE_LOADED, cacheMetadata);
|
|
66
66
|
}
|
|
67
67
|
// Emits SDK_READY
|
|
68
68
|
readiness.segments.emit(SDK_SEGMENTS_ARRIVED, { type: SEGMENTS_UPDATE, names: [] });
|
|
@@ -80,8 +80,8 @@ export function fromObjectUpdaterFactory(
|
|
|
80
80
|
* PollingManager in Offline mode
|
|
81
81
|
*/
|
|
82
82
|
export function fromObjectSyncTaskFactory(
|
|
83
|
-
splitsParser:
|
|
84
|
-
storage: Pick<IStorageSync, '
|
|
83
|
+
splitsParser: IDefinitionsParser,
|
|
84
|
+
storage: Pick<IStorageSync, 'definitions' | 'validateCache'>,
|
|
85
85
|
readiness: IReadinessManager,
|
|
86
86
|
settings: ISettings
|
|
87
87
|
): ISyncTask<[], boolean> {
|