@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
|
@@ -3,7 +3,7 @@ import { ISegmentsCacheBase } from '../../../storages/types';
|
|
|
3
3
|
import { IReadinessManager } from '../../../readiness/types';
|
|
4
4
|
import { SDK_SEGMENTS_ARRIVED, SEGMENTS_UPDATE } from '../../../readiness/constants';
|
|
5
5
|
import { ILogger } from '../../../logger/types';
|
|
6
|
-
import { LOG_PREFIX_INSTANTIATION,
|
|
6
|
+
import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC } from '../../../logger/constants';
|
|
7
7
|
import { timeout } from '../../../utils/promise/timeout';
|
|
8
8
|
import { SdkUpdateMetadata } from '../../../../types/splitio';
|
|
9
9
|
|
|
@@ -38,7 +38,7 @@ export function segmentChangesUpdaterFactory(
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function updateSegment(segmentName: string, noCache?: boolean, till?: number, fetchOnlyNew?: boolean, retries?: number): Promise<boolean> {
|
|
41
|
-
log.debug(`${
|
|
41
|
+
log.debug(`${LOG_PREFIX_SYNC}Processing segment ${segmentName}`);
|
|
42
42
|
const sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
|
|
43
43
|
|
|
44
44
|
return sincePromise.then(since => {
|
|
@@ -47,14 +47,14 @@ export function segmentChangesUpdaterFactory(
|
|
|
47
47
|
false :
|
|
48
48
|
segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then((changes) => {
|
|
49
49
|
return Promise.all(changes.map(x => {
|
|
50
|
-
log.debug(`${
|
|
50
|
+
log.debug(`${LOG_PREFIX_SYNC}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
51
51
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
52
52
|
})).then((updates) => {
|
|
53
53
|
return updates.some(update => update);
|
|
54
54
|
});
|
|
55
55
|
}).catch(error => {
|
|
56
56
|
if (retries) {
|
|
57
|
-
log.warn(`${
|
|
57
|
+
log.warn(`${LOG_PREFIX_SYNC}Retrying fetch of segment ${segmentName} (attempt #${retries}). Reason: ${error}`);
|
|
58
58
|
return updateSegment(segmentName, noCache, till, fetchOnlyNew, retries - 1);
|
|
59
59
|
}
|
|
60
60
|
throw error;
|
|
@@ -73,7 +73,7 @@ export function segmentChangesUpdaterFactory(
|
|
|
73
73
|
* @param till - till target for the provided segmentName, for CDN bypass.
|
|
74
74
|
*/
|
|
75
75
|
return function segmentChangesUpdater(fetchOnlyNew?: boolean, segmentName?: string, noCache?: boolean, till?: number) {
|
|
76
|
-
log.debug(`${
|
|
76
|
+
log.debug(`${LOG_PREFIX_SYNC}Started segments update`);
|
|
77
77
|
|
|
78
78
|
// If not a segment name provided, read list of available segments names to be updated.
|
|
79
79
|
let segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
|
|
@@ -102,9 +102,9 @@ export function segmentChangesUpdaterFactory(
|
|
|
102
102
|
// If the operation is forbidden, it may be due to permissions. Destroy the SDK instance.
|
|
103
103
|
// @TODO although factory status is destroyed, synchronization is not stopped
|
|
104
104
|
if (readiness) readiness.setDestroyed();
|
|
105
|
-
log.error(`${LOG_PREFIX_INSTANTIATION}: you passed a client-side type authorizationKey, please grab an SDK Key from
|
|
105
|
+
log.error(`${LOG_PREFIX_INSTANTIATION}: you passed a client-side type authorizationKey, please grab an SDK Key from Harness UI that is of type server-side.`);
|
|
106
106
|
} else {
|
|
107
|
-
log.warn(`${
|
|
107
|
+
log.warn(`${LOG_PREFIX_SYNC}Error while doing fetch of segments. ${error}`);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
return false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IFetchAuth } from '../../../services/types';
|
|
2
|
-
import { IAuthenticate,
|
|
2
|
+
import { IAuthenticate, IJwtCredentialV2 } from './types';
|
|
3
3
|
import { objectAssign } from '../../../utils/lang/objectAssign';
|
|
4
4
|
import { encodeToBase64 } from '../../../utils/base64';
|
|
5
5
|
import { decodeJWTtoken } from '../../../utils/jwt';
|
|
@@ -16,7 +16,7 @@ export function authenticateFactory(fetchAuth: IFetchAuth): IAuthenticate {
|
|
|
16
16
|
* Run authentication requests to Auth Server, and returns a promise that resolves with the decoded JTW token.
|
|
17
17
|
* @param userKeys - set of user Keys to track membership updates. It is undefined for server-side API.
|
|
18
18
|
*/
|
|
19
|
-
return function authenticate(userKeys?: string[]): Promise<
|
|
19
|
+
return function authenticate(userKeys?: string[]): Promise<IJwtCredentialV2> {
|
|
20
20
|
return fetchAuth(userKeys)
|
|
21
21
|
.then(resp => resp.json())
|
|
22
22
|
.then(json => {
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { IDecodedJWTToken } from '../../../utils/jwt/types';
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
pushEnabled:
|
|
5
|
-
token: string
|
|
3
|
+
export type IJwtCredentialV2 = {
|
|
4
|
+
pushEnabled: boolean
|
|
5
|
+
token: string // empty string ("") when `"pushEnabled": false`
|
|
6
6
|
decodedToken: IDecodedJWTToken
|
|
7
7
|
channels: { [channel: string]: string[] }
|
|
8
8
|
connDelay?: number
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export type IJwtCredentialV3 = {
|
|
12
|
+
token: string
|
|
13
|
+
decodedToken: IDecodedJWTToken
|
|
14
|
+
channels: { [channel: string]: string[] }
|
|
15
|
+
config?: {
|
|
16
|
+
streaming?: {
|
|
17
|
+
delay?: number
|
|
18
|
+
enabled?: boolean
|
|
19
|
+
} | null;
|
|
20
|
+
} | null;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
export type
|
|
17
|
-
|
|
18
|
-
export type IAuthenticate = (userKeys?: string[]) => Promise<IAuthToken>
|
|
19
|
-
|
|
20
|
-
export type IAuthenticateV2 = (isClientSide?: boolean) => Promise<IAuthToken>
|
|
23
|
+
export type IAuthenticate = (userKeys?: string[]) => Promise<IJwtCredentialV2>
|
|
@@ -5,7 +5,7 @@ import { ISettings } from '../../../types';
|
|
|
5
5
|
import { checkIfServerSide } from '../../../utils/key';
|
|
6
6
|
import { isString } from '../../../utils/lang';
|
|
7
7
|
import { objectAssign } from '../../../utils/lang/objectAssign';
|
|
8
|
-
import {
|
|
8
|
+
import { IJwtCredentialV2 } from '../AuthClient/types';
|
|
9
9
|
import { ISSEClient, ISseEventHandler } from './types';
|
|
10
10
|
|
|
11
11
|
const ABLY_API_VERSION = '1.1';
|
|
@@ -66,7 +66,7 @@ export class SSEClient implements ISSEClient {
|
|
|
66
66
|
/**
|
|
67
67
|
* Open the connection with a given authToken
|
|
68
68
|
*/
|
|
69
|
-
open(authToken:
|
|
69
|
+
open(authToken: IJwtCredentialV2) {
|
|
70
70
|
this.close(); // it closes connection if previously opened
|
|
71
71
|
|
|
72
72
|
const channelsQueryParam = Object.keys(authToken.channels).map((channel) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IJwtCredentialV2 } from '../AuthClient/types';
|
|
2
2
|
|
|
3
3
|
export interface ISseEventHandler {
|
|
4
4
|
handleError: (ev: Event) => any;
|
|
@@ -7,7 +7,7 @@ export interface ISseEventHandler {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export interface ISSEClient {
|
|
10
|
-
open(authToken:
|
|
10
|
+
open(authToken: IJwtCredentialV2): void,
|
|
11
11
|
close(): void,
|
|
12
12
|
setEventHandler(handler: ISseEventHandler): void
|
|
13
13
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ITelemetryTracker } from '../../../trackers/types';
|
|
2
2
|
import { CONNECTION_ESTABLISHED, DISABLED, ENABLED, OCCUPANCY_PRI, OCCUPANCY_SEC, PAUSED, STREAMING_STATUS } from '../../../utils/constants';
|
|
3
3
|
import { StreamingEventType } from '../../submitters/types';
|
|
4
|
-
import { ControlType, PUSH_SUBSYSTEM_UP,
|
|
4
|
+
import { ControlType, PUSH_SUBSYSTEM_UP, PUSH_NON_RETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN } from '../constants';
|
|
5
5
|
import { IPushEventEmitter } from '../types';
|
|
6
6
|
|
|
7
7
|
const CONTROL_CHANNEL_REGEXS = [/control_pri$/, /control_sec$/];
|
|
@@ -84,7 +84,7 @@ export function notificationKeeperFactory(pushEmitter: IPushEventEmitter, teleme
|
|
|
84
84
|
c.cTime = timestamp;
|
|
85
85
|
if (controlType === ControlType.STREAMING_DISABLED) {
|
|
86
86
|
telemetryTracker.streamingEvent(STREAMING_STATUS, DISABLED);
|
|
87
|
-
pushEmitter.emit(
|
|
87
|
+
pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
|
|
88
88
|
} else if (hasPublishers) {
|
|
89
89
|
if (controlType === ControlType.STREAMING_PAUSED && hasResumed) {
|
|
90
90
|
telemetryTracker.streamingEvent(STREAMING_STATUS, PAUSED);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { errorParser, messageParser } from './NotificationParser';
|
|
2
2
|
import { notificationKeeperFactory } from './NotificationKeeper';
|
|
3
|
-
import { PUSH_RETRYABLE_ERROR,
|
|
3
|
+
import { PUSH_RETRYABLE_ERROR, PUSH_NON_RETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, RB_SEGMENT_UPDATE } from '../constants';
|
|
4
4
|
import { IPushEventEmitter } from '../types';
|
|
5
5
|
import { ISseEventHandler } from '../SSEClient/types';
|
|
6
6
|
import { INotificationError, INotificationMessage } from './types';
|
|
@@ -56,7 +56,7 @@ export function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter,
|
|
|
56
56
|
if (isRetryableError(errorWithParsedData)) {
|
|
57
57
|
pushEmitter.emit(PUSH_RETRYABLE_ERROR);
|
|
58
58
|
} else {
|
|
59
|
-
pushEmitter.emit(
|
|
59
|
+
pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
|
package/src/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.ts → DefinitionsUpdateWorker.ts}
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { IRBSegment,
|
|
1
|
+
import { IRBSegment, IDefinition } from '../../../dtos/types';
|
|
2
2
|
import { STREAMING_PARSING_SPLIT_UPDATE } from '../../../logger/constants';
|
|
3
3
|
import { ILogger } from '../../../logger/types';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { IRBSegmentsCacheSync,
|
|
4
|
+
import { SDK_DEFINITIONS_ARRIVED } from '../../../readiness/constants';
|
|
5
|
+
import { IDefinitionsEventEmitter } from '../../../readiness/types';
|
|
6
|
+
import { IRBSegmentsCacheSync, IDefinitionsCacheSync, IStorageSync } from '../../../storages/types';
|
|
7
7
|
import { ITelemetryTracker } from '../../../trackers/types';
|
|
8
8
|
import { Backoff } from '../../../utils/Backoff';
|
|
9
9
|
import { SPLITS } from '../../../utils/constants';
|
|
10
|
-
import { ISegmentsSyncTask,
|
|
11
|
-
import { InstantUpdate } from '../../polling/updaters/
|
|
10
|
+
import { ISegmentsSyncTask, IDefinitionsSyncTask } from '../../polling/types';
|
|
11
|
+
import { InstantUpdate } from '../../polling/updaters/definitionChangesUpdater';
|
|
12
12
|
import { RB_SEGMENT_UPDATE } from '../constants';
|
|
13
13
|
import { parseFFUpdatePayload } from '../parseUtils';
|
|
14
14
|
import { ISplitKillData, ISplitUpdateData } from '../SSEHandler/types';
|
|
@@ -16,30 +16,30 @@ import { FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT, FETCH_BACKOFF_MAX_RETRIES }
|
|
|
16
16
|
import { IUpdateWorker } from './types';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* DefinitionsUpdateWorker factory
|
|
20
20
|
*/
|
|
21
|
-
export function
|
|
21
|
+
export function DefinitionsUpdateWorker(log: ILogger, storage: IStorageSync, definitionsSyncTask: IDefinitionsSyncTask, definitionsEventEmitter: IDefinitionsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker<[updateData: ISplitUpdateData]> & { killDefinition(event: ISplitKillData): void } {
|
|
22
22
|
|
|
23
|
-
const ff =
|
|
24
|
-
const rbs =
|
|
23
|
+
const ff = DefinitionsUpdateWorker(storage.definitions);
|
|
24
|
+
const rbs = DefinitionsUpdateWorker(storage.rbSegments);
|
|
25
25
|
|
|
26
|
-
function
|
|
26
|
+
function DefinitionsUpdateWorker(cache: IDefinitionsCacheSync | IRBSegmentsCacheSync) {
|
|
27
27
|
let maxChangeNumber = -1;
|
|
28
28
|
let handleNewEvent = false;
|
|
29
29
|
let isHandlingEvent: boolean;
|
|
30
30
|
let cdnBypass: boolean;
|
|
31
31
|
let instantUpdate: InstantUpdate | undefined;
|
|
32
|
-
const backoff = new Backoff(
|
|
32
|
+
const backoff = new Backoff(__handleDefinitionUpdateCall, FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT);
|
|
33
33
|
|
|
34
|
-
function
|
|
34
|
+
function __handleDefinitionUpdateCall() {
|
|
35
35
|
isHandlingEvent = true;
|
|
36
36
|
if (maxChangeNumber > cache.getChangeNumber()) {
|
|
37
37
|
handleNewEvent = false;
|
|
38
38
|
// fetch splits revalidating data if cached
|
|
39
|
-
|
|
39
|
+
definitionsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, instantUpdate).then(() => {
|
|
40
40
|
if (!isHandlingEvent) return; // halt if `stop` has been called
|
|
41
41
|
if (handleNewEvent) {
|
|
42
|
-
|
|
42
|
+
__handleDefinitionUpdateCall();
|
|
43
43
|
} else {
|
|
44
44
|
if (instantUpdate) telemetryTracker.trackUpdatesFromSSE(SPLITS);
|
|
45
45
|
// fetch new registered segments for server-side API. Not retrying on error
|
|
@@ -64,7 +64,7 @@ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSy
|
|
|
64
64
|
} else {
|
|
65
65
|
backoff.reset();
|
|
66
66
|
cdnBypass = true;
|
|
67
|
-
|
|
67
|
+
__handleDefinitionUpdateCall();
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
});
|
|
@@ -79,7 +79,7 @@ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSy
|
|
|
79
79
|
*
|
|
80
80
|
* @param changeNumber - change number of the notification
|
|
81
81
|
*/
|
|
82
|
-
put({ changeNumber, pcn, type }: ISplitUpdateData, payload?:
|
|
82
|
+
put({ changeNumber, pcn, type }: ISplitUpdateData, payload?: IDefinition | IRBSegment) {
|
|
83
83
|
const currentChangeNumber = cache.getChangeNumber();
|
|
84
84
|
|
|
85
85
|
if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
|
|
@@ -93,7 +93,7 @@ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSy
|
|
|
93
93
|
instantUpdate = { payload, changeNumber, type };
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
if (backoff.timeoutID || !isHandlingEvent)
|
|
96
|
+
if (backoff.timeoutID || !isHandlingEvent) __handleDefinitionUpdateCall();
|
|
97
97
|
backoff.reset();
|
|
98
98
|
},
|
|
99
99
|
stop() {
|
|
@@ -128,10 +128,10 @@ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSy
|
|
|
128
128
|
* @param splitName - name of split to kill
|
|
129
129
|
* @param defaultTreatment - default treatment value
|
|
130
130
|
*/
|
|
131
|
-
|
|
132
|
-
if (storage.
|
|
131
|
+
killDefinition({ changeNumber, splitName, defaultTreatment }: ISplitKillData) {
|
|
132
|
+
if (storage.definitions.killLocally(splitName, defaultTreatment, changeNumber)) {
|
|
133
133
|
// trigger an SDK_UPDATE if Split was killed locally
|
|
134
|
-
|
|
134
|
+
definitionsEventEmitter.emit(SDK_DEFINITIONS_ARRIVED, true);
|
|
135
135
|
}
|
|
136
136
|
// queues the SplitChanges fetch (only if changeNumber is newer)
|
|
137
137
|
ff.put({ changeNumber } as ISplitUpdateData);
|
|
@@ -6,7 +6,7 @@ export const SECONDS_BEFORE_EXPIRATION = 600;
|
|
|
6
6
|
* emitted on SSE and Authenticate non-recoverable errors, STREAMING_DISABLED control notification and authentication with pushEnabled false
|
|
7
7
|
* triggers `handleNonRetryableError` call
|
|
8
8
|
*/
|
|
9
|
-
export const
|
|
9
|
+
export const PUSH_NON_RETRYABLE_ERROR = 'PUSH_NON_RETRYABLE_ERROR';
|
|
10
10
|
/**
|
|
11
11
|
* emitted on SSE and Authenticate recoverable errors
|
|
12
12
|
* triggers `handleRetryableError` call
|
|
@@ -19,7 +19,7 @@ export const PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR';
|
|
|
19
19
|
export const PUSH_SUBSYSTEM_UP = 'PUSH_SUBSYSTEM_UP';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* emitted on STREAMING_PAUSED control notification, OCCUPANCY equal to 0,
|
|
22
|
+
* emitted on STREAMING_PAUSED control notification, OCCUPANCY equal to 0, PUSH_NON_RETRYABLE_ERROR and PUSH_RETRYABLE_ERROR events.
|
|
23
23
|
* triggers `startPolling` and `stopWorkers` calls
|
|
24
24
|
*/
|
|
25
25
|
export const PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { algorithms } from '../../utils/decompress';
|
|
2
2
|
import { decodeFromBase64 } from '../../utils/base64';
|
|
3
3
|
import { hash } from '../../utils/murmur3/murmur3';
|
|
4
|
-
import { Compression, IMembershipMSUpdateData
|
|
5
|
-
import { IRBSegment,
|
|
4
|
+
import { Compression, IMembershipMSUpdateData } from './SSEHandler/types';
|
|
5
|
+
import { IRBSegment, IDefinition } from '../../dtos/types';
|
|
6
6
|
|
|
7
7
|
const GZIP = 1;
|
|
8
8
|
const ZLIB = 2;
|
|
@@ -35,20 +35,20 @@ function decompress(data: string, compression: Compression) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Decode, decompress and parse the provided 'data' into
|
|
38
|
+
* Decode, decompress and parse the provided 'data' into an object of type T
|
|
39
39
|
*
|
|
40
40
|
* @param data - base64 encoded string
|
|
41
41
|
* @param compression - 1 GZIP, 2 ZLIB
|
|
42
42
|
* @param avoidPrecisionLoss - true as default, set it as false if dont need to avoid precission loss
|
|
43
|
-
* @returns
|
|
43
|
+
* @returns parsed object
|
|
44
44
|
* @throws if data string cannot be decoded, decompressed or parsed
|
|
45
45
|
*/
|
|
46
|
-
export function
|
|
47
|
-
const
|
|
48
|
-
let
|
|
49
|
-
// replace numbers to strings, to avoid losing precision
|
|
50
|
-
if (avoidPrecisionLoss)
|
|
51
|
-
return JSON.parse(
|
|
46
|
+
export function parseCompressedData<T>(data: string, compression: Compression, avoidPrecisionLoss = true): T {
|
|
47
|
+
const binData = decompress(data, compression);
|
|
48
|
+
let str = Uint8ArrayToString(binData);
|
|
49
|
+
// replace numbers to strings, to avoid losing precision (e.g., 64-bit IDs in KeyList)
|
|
50
|
+
if (avoidPrecisionLoss) str = str.replace(/\d+/g, '"$&"');
|
|
51
|
+
return JSON.parse(str) as T;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/**
|
|
@@ -82,9 +82,9 @@ export function isInBitmap(bitmap: Uint8Array, hash64hex: string) {
|
|
|
82
82
|
/**
|
|
83
83
|
* Parse feature flags notifications for instant feature flag updates
|
|
84
84
|
*/
|
|
85
|
-
export function parseFFUpdatePayload(compression: Compression, data: string):
|
|
85
|
+
export function parseFFUpdatePayload(compression: Compression, data: string): IDefinition | IRBSegment | undefined {
|
|
86
86
|
return compression > 0 ?
|
|
87
|
-
|
|
87
|
+
parseCompressedData<IDefinition | IRBSegment>(data, compression, false) :
|
|
88
88
|
JSON.parse(decodeFromBase64(data));
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -6,17 +6,17 @@ import { Backoff } from '../../utils/Backoff';
|
|
|
6
6
|
import { SSEHandlerFactory } from './SSEHandler';
|
|
7
7
|
import { MySegmentsUpdateWorker } from './UpdateWorkers/MySegmentsUpdateWorker';
|
|
8
8
|
import { SegmentsUpdateWorker } from './UpdateWorkers/SegmentsUpdateWorker';
|
|
9
|
-
import {
|
|
9
|
+
import { DefinitionsUpdateWorker } from './UpdateWorkers/DefinitionsUpdateWorker';
|
|
10
10
|
import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
11
11
|
import { forOwn } from '../../utils/lang';
|
|
12
12
|
import { SSEClient } from './SSEClient';
|
|
13
13
|
import { checkIfServerSide, getMatching } from '../../utils/key';
|
|
14
|
-
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE,
|
|
14
|
+
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NON_RETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
15
15
|
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
|
|
16
16
|
import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
|
|
17
|
-
import { getDelay, isInBitmap, parseBitmap,
|
|
17
|
+
import { getDelay, isInBitmap, parseBitmap, parseCompressedData } from './parseUtils';
|
|
18
18
|
import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
|
|
19
|
-
import {
|
|
19
|
+
import { IJwtCredentialV2 } from './AuthClient/types';
|
|
20
20
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
21
21
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
22
22
|
|
|
@@ -55,8 +55,8 @@ export function pushManagerFactory(
|
|
|
55
55
|
// init workers
|
|
56
56
|
// MySegmentsUpdateWorker (client-side) are initiated in `add` method
|
|
57
57
|
const segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask as ISegmentsSyncTask, storage.segments);
|
|
58
|
-
// For server-side we pass the segmentsSyncTask, used by
|
|
59
|
-
const
|
|
58
|
+
// For server-side we pass the segmentsSyncTask, used by DefinitionsUpdateWorker to fetch new segments
|
|
59
|
+
const definitionsUpdateWorker = DefinitionsUpdateWorker(log, storage, pollingManager.definitionsSyncTask, readiness.definitions, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
|
|
60
60
|
|
|
61
61
|
// [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
|
|
62
62
|
const userKeyHashes: Record<string, string> = {};
|
|
@@ -67,10 +67,10 @@ export function pushManagerFactory(
|
|
|
67
67
|
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
68
68
|
let connectForNewClient = false;
|
|
69
69
|
|
|
70
|
-
// flag that indicates if `stop/disconnectPush` was called, either by the SyncManager, when the client is destroyed, or due to a
|
|
70
|
+
// flag that indicates if `stop/disconnectPush` was called, either by the SyncManager, when the client is destroyed, or due to a PUSH_NON_RETRYABLE_ERROR error.
|
|
71
71
|
// It is used to halt the `connectPush` process if it was in progress.
|
|
72
72
|
let disconnected: boolean | undefined;
|
|
73
|
-
// flag that indicates a
|
|
73
|
+
// flag that indicates a PUSH_NON_RETRYABLE_ERROR, condition with which starting pushManager again is ignored.
|
|
74
74
|
// true if STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE or Auth errors.
|
|
75
75
|
let disabled: boolean | undefined; // `disabled` implies `disconnected === true`
|
|
76
76
|
|
|
@@ -81,7 +81,7 @@ export function pushManagerFactory(
|
|
|
81
81
|
let timeoutIdTokenRefresh: ReturnType<typeof setTimeout>;
|
|
82
82
|
let timeoutIdSseOpen: ReturnType<typeof setTimeout>;
|
|
83
83
|
|
|
84
|
-
function scheduleTokenRefreshAndSse(authData:
|
|
84
|
+
function scheduleTokenRefreshAndSse(authData: IJwtCredentialV2) {
|
|
85
85
|
// clear scheduled tasks if exist
|
|
86
86
|
if (timeoutIdTokenRefresh) clearTimeout(timeoutIdTokenRefresh);
|
|
87
87
|
if (timeoutIdSseOpen) clearTimeout(timeoutIdSseOpen);
|
|
@@ -117,11 +117,11 @@ export function pushManagerFactory(
|
|
|
117
117
|
function (authData) {
|
|
118
118
|
if (disconnected) return;
|
|
119
119
|
|
|
120
|
-
// 'pushEnabled: false' is handled as a
|
|
120
|
+
// 'pushEnabled: false' is handled as a PUSH_NON_RETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
121
121
|
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
122
122
|
if (!authData.pushEnabled) {
|
|
123
123
|
log.info(STREAMING_DISABLED);
|
|
124
|
-
pushEmitter.emit(
|
|
124
|
+
pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -140,7 +140,7 @@ export function pushManagerFactory(
|
|
|
140
140
|
// Handle 4XX HTTP errors: 401 (invalid SDK Key) or 400 (using incorrect SDK Key, i.e., client-side SDK Key on server-side)
|
|
141
141
|
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
142
142
|
telemetryTracker.streamingEvent(AUTH_REJECTION);
|
|
143
|
-
pushEmitter.emit(
|
|
143
|
+
pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -168,7 +168,7 @@ export function pushManagerFactory(
|
|
|
168
168
|
|
|
169
169
|
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
170
170
|
function stopWorkers() {
|
|
171
|
-
|
|
171
|
+
definitionsUpdateWorker.stop();
|
|
172
172
|
if (userKey) forOwn(clients, ({ worker }) => worker.stop());
|
|
173
173
|
else segmentsUpdateWorker!.stop();
|
|
174
174
|
}
|
|
@@ -183,7 +183,7 @@ export function pushManagerFactory(
|
|
|
183
183
|
|
|
184
184
|
/** Fallback to polling without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
185
185
|
|
|
186
|
-
pushEmitter.on(
|
|
186
|
+
pushEmitter.on(PUSH_NON_RETRYABLE_ERROR, function handleNonRetryableError() {
|
|
187
187
|
disabled = true;
|
|
188
188
|
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
189
189
|
disconnectPush();
|
|
@@ -218,9 +218,9 @@ export function pushManagerFactory(
|
|
|
218
218
|
|
|
219
219
|
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
220
220
|
|
|
221
|
-
pushEmitter.on(SPLIT_KILL,
|
|
222
|
-
pushEmitter.on(SPLIT_UPDATE,
|
|
223
|
-
pushEmitter.on(RB_SEGMENT_UPDATE,
|
|
221
|
+
pushEmitter.on(SPLIT_KILL, definitionsUpdateWorker.killDefinition);
|
|
222
|
+
pushEmitter.on(SPLIT_UPDATE, definitionsUpdateWorker.put);
|
|
223
|
+
pushEmitter.on(RB_SEGMENT_UPDATE, definitionsUpdateWorker.put);
|
|
224
224
|
|
|
225
225
|
function handleMySegmentsUpdate(parsedData: IMembershipMSUpdateData | IMembershipLSUpdateData) {
|
|
226
226
|
switch (parsedData.u) {
|
|
@@ -243,7 +243,7 @@ export function pushManagerFactory(
|
|
|
243
243
|
case UpdateStrategy.KeyList: {
|
|
244
244
|
let keyList: KeyList, added: Set<string>, removed: Set<string>;
|
|
245
245
|
try {
|
|
246
|
-
keyList =
|
|
246
|
+
keyList = parseCompressedData<KeyList>(parsedData.d!, parsedData.c!);
|
|
247
247
|
added = new Set(keyList.a);
|
|
248
248
|
removed = new Set(keyList.r);
|
|
249
249
|
} catch (e) {
|
|
@@ -7,7 +7,7 @@ import { ControlType } from './constants';
|
|
|
7
7
|
// Internal SDK events, subscribed by SyncManager and PushManager
|
|
8
8
|
export type PUSH_SUBSYSTEM_UP = 'PUSH_SUBSYSTEM_UP'
|
|
9
9
|
export type PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN'
|
|
10
|
-
export type
|
|
10
|
+
export type PUSH_NON_RETRYABLE_ERROR = 'PUSH_NON_RETRYABLE_ERROR'
|
|
11
11
|
export type PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR'
|
|
12
12
|
|
|
13
13
|
// Update-type push notifications, handled by NotificationProcessor
|
|
@@ -22,7 +22,7 @@ export type RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
|
|
|
22
22
|
export type CONTROL = 'CONTROL';
|
|
23
23
|
export type OCCUPANCY = 'OCCUPANCY';
|
|
24
24
|
|
|
25
|
-
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN |
|
|
25
|
+
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NON_RETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | RB_SEGMENT_UPDATE | ControlType.STREAMING_RESET
|
|
26
26
|
|
|
27
27
|
type IParsedData<T extends IPushEvent> =
|
|
28
28
|
T extends MEMBERSHIPS_MS_UPDATE ? IMembershipMSUpdateData :
|
|
@@ -3,20 +3,20 @@ import SplitIO from '../../../types/splitio';
|
|
|
3
3
|
import { submitterFactory } from './submitter';
|
|
4
4
|
import { ImpressionsPayload } from './types';
|
|
5
5
|
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
6
|
-
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
6
|
+
import { EntityType, ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Converts `impressions` data from cache into request payload.
|
|
10
10
|
*/
|
|
11
|
-
export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.ImpressionDTO[]): ImpressionsPayload {
|
|
11
|
+
export function fromImpressionsCollector(sendLabels: boolean, entityType: EntityType | undefined, data: SplitIO.ImpressionDTO[]): ImpressionsPayload {
|
|
12
12
|
let groupedByFeature = groupBy(data, 'feature');
|
|
13
13
|
let dto: ImpressionsPayload = [];
|
|
14
14
|
|
|
15
15
|
forOwn(groupedByFeature, (value, name) => {
|
|
16
16
|
dto.push({
|
|
17
|
-
f: name, //
|
|
17
|
+
f: name, // Definition type
|
|
18
18
|
i: value.map(entry => { // Key Impressions
|
|
19
|
-
|
|
19
|
+
return {
|
|
20
20
|
k: entry.keyName, // Key
|
|
21
21
|
t: entry.treatment, // Treatment
|
|
22
22
|
m: entry.time, // Timestamp
|
|
@@ -24,10 +24,9 @@ export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.Impr
|
|
|
24
24
|
r: sendLabels ? entry.label : undefined, // Rule
|
|
25
25
|
b: entry.bucketingKey, // Bucketing Key
|
|
26
26
|
pt: entry.pt, // Previous time
|
|
27
|
-
properties: entry.properties // Properties
|
|
27
|
+
properties: entry.properties, // Properties
|
|
28
|
+
et: entityType, // Definition type
|
|
28
29
|
};
|
|
29
|
-
|
|
30
|
-
return keyImpression;
|
|
31
30
|
})
|
|
32
31
|
});
|
|
33
32
|
});
|
|
@@ -43,11 +42,12 @@ export function impressionsSubmitterFactory(params: ISdkFactoryContextSync) {
|
|
|
43
42
|
const {
|
|
44
43
|
settings: { log, scheduler: { impressionsRefreshRate }, core: { labelsEnabled } },
|
|
45
44
|
splitApi: { postTestImpressionsBulk },
|
|
46
|
-
storage: { impressions }
|
|
45
|
+
storage: { impressions },
|
|
46
|
+
entityType
|
|
47
47
|
} = params;
|
|
48
48
|
|
|
49
49
|
// retry impressions only once.
|
|
50
|
-
const syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, fromImpressionsCollector.bind(undefined, labelsEnabled), 1);
|
|
50
|
+
const syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, fromImpressionsCollector.bind(undefined, labelsEnabled, entityType), 1);
|
|
51
51
|
|
|
52
52
|
// register impressions submitter to be executed when impressions cache is full
|
|
53
53
|
impressions.setOnFullQueueCb(() => {
|
|
@@ -119,7 +119,7 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
|
|
|
119
119
|
const { storage: { telemetry }, platform: { now } } = params;
|
|
120
120
|
if (!telemetry || !now) return; // No submitter created if telemetry cache is not defined
|
|
121
121
|
|
|
122
|
-
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness
|
|
122
|
+
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness } = params;
|
|
123
123
|
const stopTimer = timer(now);
|
|
124
124
|
|
|
125
125
|
const submitter = firstPushWindowDecorator(
|
|
@@ -135,7 +135,6 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
|
|
|
135
135
|
telemetry.recordTimeUntilReadyFromCache(stopTimer());
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
sdkReadinessManager.incInternalReadyCbCount();
|
|
139
138
|
readiness.gate.once(SDK_READY, () => {
|
|
140
139
|
telemetry.recordTimeUntilReady(stopTimer());
|
|
141
140
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { IMetadata } from '../../dtos/types';
|
|
3
3
|
import SplitIO from '../../../types/splitio';
|
|
4
4
|
import { ISyncTask } from '../types';
|
|
5
|
+
import { EntityType } from '../../sdkFactory/types';
|
|
5
6
|
|
|
6
7
|
type ImpressionPayload = {
|
|
7
8
|
/** Matching Key */
|
|
@@ -20,6 +21,8 @@ type ImpressionPayload = {
|
|
|
20
21
|
pt?: number;
|
|
21
22
|
/** Stringified JSON object with properties */
|
|
22
23
|
properties?: string;
|
|
24
|
+
/** Definition type */
|
|
25
|
+
et?: EntityType,
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
export type ImpressionsPayload = {
|
|
@@ -9,8 +9,10 @@ import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '..
|
|
|
9
9
|
import { isConsentGranted } from '../consent';
|
|
10
10
|
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
11
11
|
import { ISdkFactoryContextSync } from '../sdkFactory/types';
|
|
12
|
-
import {
|
|
13
|
-
import { usesSegmentsSync } from '../storages/
|
|
12
|
+
import { SDK_DEFINITIONS_CACHE_LOADED } from '../readiness/constants';
|
|
13
|
+
import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
|
|
14
|
+
import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
|
|
15
|
+
import { IDefinitionChangesFetcher } from './polling/fetchers/types';
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Online SyncManager factory.
|
|
@@ -19,10 +21,12 @@ import { usesSegmentsSync } from '../storages/AbstractSplitsCacheSync';
|
|
|
19
21
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
20
22
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
21
23
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
24
|
+
* @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
|
|
22
25
|
*/
|
|
23
26
|
export function syncManagerOnlineFactory(
|
|
24
|
-
pollingManagerFactory?: (params: ISdkFactoryContextSync) => IPollingManager,
|
|
27
|
+
pollingManagerFactory?: (params: ISdkFactoryContextSync, definitionChangesFetcher: IDefinitionChangesFetcher) => IPollingManager,
|
|
25
28
|
pushManagerFactory?: (params: ISdkFactoryContextSync, pollingManager: IPollingManager) => IPushManager | undefined,
|
|
29
|
+
definitionChangesFetcherFactory = splitChangesFetcherFactory
|
|
26
30
|
): (params: ISdkFactoryContextSync) => ISyncManagerCS {
|
|
27
31
|
|
|
28
32
|
/**
|
|
@@ -33,7 +37,7 @@ export function syncManagerOnlineFactory(
|
|
|
33
37
|
const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker, storage, readiness } = params;
|
|
34
38
|
|
|
35
39
|
/** Polling Manager */
|
|
36
|
-
const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
40
|
+
const pollingManager = pollingManagerFactory && pollingManagerFactory(params, definitionChangesFetcherFactory(params));
|
|
37
41
|
|
|
38
42
|
/** Push Manager */
|
|
39
43
|
const pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
@@ -98,7 +102,7 @@ export function syncManagerOnlineFactory(
|
|
|
98
102
|
if (startFirstTime) {
|
|
99
103
|
// Emits SDK_READY_FROM_CACHE
|
|
100
104
|
if (!cacheMetadata.initialCacheLoad) {
|
|
101
|
-
readiness.
|
|
105
|
+
readiness.definitions.emit(SDK_DEFINITIONS_CACHE_LOADED, cacheMetadata);
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
}
|