@splitsoftware/splitio-commons 1.2.1-rc.1 → 1.2.1-rc.12
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/cjs/consent/index.js +10 -0
- package/cjs/consent/sdkUserConsent.js +58 -0
- package/cjs/evaluator/Engine.js +6 -6
- package/cjs/evaluator/combiners/and.js +1 -1
- package/cjs/evaluator/combiners/ifelseif.js +2 -2
- package/cjs/evaluator/condition/engineUtils.js +2 -2
- package/cjs/evaluator/condition/index.js +4 -4
- package/cjs/evaluator/index.js +5 -5
- package/cjs/evaluator/matchers/cont_all.js +1 -1
- package/cjs/evaluator/matchers/cont_any.js +1 -1
- package/cjs/evaluator/matchers/cont_str.js +1 -1
- package/cjs/evaluator/matchers/dependency.js +1 -1
- package/cjs/evaluator/matchers/eq_set.js +1 -1
- package/cjs/evaluator/matchers/ew.js +1 -1
- package/cjs/evaluator/matchers/part_of.js +1 -1
- package/cjs/evaluator/matchers/segment.js +1 -1
- package/cjs/evaluator/matchers/sw.js +1 -1
- package/cjs/evaluator/matchers/whitelist.js +1 -1
- package/cjs/evaluator/matchersTransform/index.js +12 -12
- package/cjs/evaluator/parser/index.js +6 -6
- package/cjs/evaluator/treatments/index.js +1 -1
- package/cjs/evaluator/value/index.js +1 -1
- package/cjs/evaluator/value/sanitize.js +4 -4
- package/cjs/integrations/browser.js +3 -3
- package/cjs/integrations/ga/GaToSplit.js +14 -14
- package/cjs/integrations/ga/GoogleAnalyticsToSplit.js +5 -3
- package/cjs/integrations/ga/SplitToGa.js +1 -1
- package/cjs/integrations/ga/SplitToGoogleAnalytics.js +4 -2
- package/cjs/listeners/browser.js +15 -11
- package/cjs/listeners/node.js +1 -1
- package/cjs/logger/constants.js +9 -3
- package/cjs/logger/index.js +2 -2
- package/cjs/logger/messages/debug.js +4 -4
- package/cjs/logger/messages/error.js +5 -4
- package/cjs/logger/messages/info.js +8 -5
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/logger/sdkLogger.js +1 -1
- package/cjs/readiness/readinessManager.js +2 -2
- package/cjs/readiness/sdkReadinessManager.js +4 -4
- package/cjs/sdkClient/client.js +12 -11
- package/cjs/sdkClient/clientAttributesDecoration.js +4 -4
- package/cjs/sdkClient/clientCS.js +3 -3
- package/cjs/sdkClient/clientInputValidation.js +20 -22
- package/cjs/sdkClient/sdkClient.js +6 -9
- package/cjs/sdkClient/sdkClientMethod.js +1 -1
- package/cjs/sdkClient/sdkClientMethodCS.js +7 -13
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +8 -18
- package/cjs/sdkFactory/index.js +16 -13
- package/cjs/sdkManager/index.js +11 -11
- package/cjs/services/splitApi.js +3 -2
- package/cjs/services/splitHttpClient.js +2 -2
- package/cjs/storages/KeyBuilder.js +2 -6
- package/cjs/storages/KeyBuilderCS.js +13 -3
- package/cjs/storages/KeyBuilderSS.js +1 -1
- package/cjs/storages/findLatencyIndex.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +24 -4
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +12 -12
- package/cjs/storages/inLocalStorage/index.js +4 -4
- package/cjs/storages/inMemory/AttributesCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +1 -1
- package/cjs/storages/inMemory/InMemoryStorageCS.js +1 -1
- package/cjs/storages/inMemory/LatenciesCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +2 -2
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +5 -5
- package/cjs/storages/inRedis/LatenciesCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RedisAdapter.js +24 -11
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +3 -3
- package/cjs/storages/inRedis/index.js +1 -1
- package/cjs/storages/pluggable/SegmentsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/SplitsCachePluggable.js +3 -3
- package/cjs/storages/pluggable/inMemoryWrapper.js +4 -4
- package/cjs/storages/pluggable/index.js +6 -6
- package/cjs/sync/offline/LocalhostFromFile.js +1 -1
- package/cjs/sync/offline/LocalhostFromObject.js +1 -1
- package/cjs/sync/offline/splitsParser/parseCondition.js +1 -1
- package/cjs/sync/offline/splitsParser/splitsParserFromFile.js +13 -13
- package/cjs/sync/offline/splitsParser/splitsParserFromSettings.js +3 -3
- package/cjs/sync/offline/syncManagerOffline.js +1 -1
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -2
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +6 -6
- package/cjs/sync/polling/pollingManagerSS.js +3 -3
- package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +1 -1
- package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +1 -1
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +1 -1
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +2 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -2
- package/cjs/sync/streaming/AuthClient/index.js +3 -3
- package/cjs/sync/streaming/SSEClient/index.js +2 -1
- package/cjs/sync/streaming/SSEHandler/NotificationParser.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +3 -3
- package/cjs/sync/streaming/mySegmentsV2utils.js +1 -1
- package/cjs/sync/streaming/pushManager.js +24 -17
- package/cjs/sync/submitters/eventsSyncTask.js +17 -5
- package/cjs/sync/submitters/impressionCountsSyncTask.js +1 -1
- package/cjs/sync/submitters/impressionsSyncTask.js +15 -3
- package/cjs/sync/submitters/metricsSyncTask.js +3 -3
- package/cjs/sync/submitters/submitterManager.js +4 -4
- package/cjs/sync/submitters/submitterSyncTask.js +1 -1
- package/cjs/sync/syncManagerOnline.js +12 -8
- package/cjs/trackers/eventTracker.js +11 -4
- package/cjs/trackers/impressionObserver/impressionObserverCS.js +1 -1
- package/cjs/trackers/impressionObserver/impressionObserverSS.js +1 -1
- package/cjs/trackers/impressionObserver/utils.js +8 -1
- package/cjs/trackers/impressionsTracker.js +9 -8
- package/cjs/utils/MinEvents.js +2 -1
- package/cjs/utils/constants/index.js +5 -1
- package/cjs/utils/inputValidation/apiKey.js +1 -1
- package/cjs/utils/inputValidation/attribute.js +4 -4
- package/cjs/utils/inputValidation/attributes.js +2 -2
- package/cjs/utils/inputValidation/event.js +1 -1
- package/cjs/utils/inputValidation/eventProperties.js +5 -5
- package/cjs/utils/inputValidation/eventValue.js +1 -1
- package/cjs/utils/inputValidation/key.js +6 -5
- package/cjs/utils/inputValidation/preloadedData.js +8 -8
- package/cjs/utils/inputValidation/split.js +1 -1
- package/cjs/utils/inputValidation/splits.js +2 -2
- package/cjs/utils/inputValidation/trafficType.js +1 -1
- package/cjs/utils/inputValidation/trafficTypeExistance.js +1 -1
- package/cjs/utils/jwt/index.js +1 -1
- package/cjs/utils/key/index.js +3 -3
- package/cjs/utils/lang/index.js +13 -4
- package/cjs/utils/lang/maps.js +16 -2
- package/cjs/utils/murmur3/common.js +1 -1
- package/cjs/utils/murmur3/murmur3.js +10 -10
- package/cjs/utils/murmur3/murmur3_128.js +1 -1
- package/cjs/utils/murmur3/murmur3_128_x86.js +37 -37
- package/cjs/utils/murmur3/murmur3_64.js +1 -1
- package/cjs/utils/settingsValidation/consent.js +16 -0
- package/cjs/utils/settingsValidation/impressionsMode.js +6 -6
- package/cjs/utils/settingsValidation/index.js +32 -14
- package/cjs/utils/settingsValidation/integrations/configurable.js +1 -1
- package/cjs/utils/settingsValidation/integrations/pluggable.js +1 -1
- package/cjs/utils/settingsValidation/localhost/builtin.js +2 -2
- package/cjs/utils/settingsValidation/logger/builtinLogger.js +3 -3
- package/cjs/utils/settingsValidation/logger/commons.js +1 -1
- package/cjs/utils/settingsValidation/logger/pluggableLogger.js +1 -1
- package/cjs/utils/settingsValidation/runtime.js +11 -0
- package/cjs/utils/settingsValidation/splitFilters.js +1 -1
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/cjs/utils/timeTracker/index.js +3 -3
- package/esm/consent/index.js +6 -0
- package/esm/consent/sdkUserConsent.js +54 -0
- package/esm/integrations/ga/GoogleAnalyticsToSplit.js +4 -2
- package/esm/integrations/ga/SplitToGoogleAnalytics.js +4 -2
- package/esm/listeners/browser.js +14 -10
- package/esm/logger/constants.js +6 -2
- package/esm/logger/messages/debug.js +3 -3
- package/esm/logger/messages/error.js +4 -3
- package/esm/logger/messages/info.js +7 -4
- package/esm/sdkClient/client.js +3 -2
- package/esm/sdkClient/clientCS.js +1 -1
- package/esm/sdkClient/clientInputValidation.js +6 -8
- package/esm/sdkClient/sdkClient.js +4 -7
- package/esm/sdkClient/sdkClientMethodCS.js +3 -9
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +3 -13
- package/esm/sdkFactory/index.js +10 -7
- package/esm/services/splitApi.js +2 -1
- package/esm/storages/KeyBuilder.js +2 -6
- package/esm/storages/KeyBuilderCS.js +11 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -3
- package/esm/storages/inLocalStorage/index.js +1 -1
- package/esm/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
- package/esm/storages/inMemory/InMemoryStorage.js +1 -1
- package/esm/storages/inMemory/InMemoryStorageCS.js +1 -1
- package/esm/storages/inRedis/RedisAdapter.js +15 -2
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/sync/offline/splitsParser/splitsParserFromFile.js +1 -1
- package/esm/sync/polling/fetchers/segmentChangesFetcher.js +2 -2
- package/esm/sync/streaming/SSEClient/index.js +2 -1
- package/esm/sync/streaming/pushManager.js +9 -2
- package/esm/sync/submitters/eventsSyncTask.js +18 -6
- package/esm/sync/submitters/impressionsSyncTask.js +13 -1
- package/esm/sync/syncManagerOnline.js +11 -7
- package/esm/trackers/eventTracker.js +8 -1
- package/esm/trackers/impressionObserver/utils.js +7 -1
- package/esm/trackers/impressionsTracker.js +6 -5
- package/esm/utils/constants/index.js +4 -0
- package/esm/utils/inputValidation/attributes.js +1 -1
- package/esm/utils/inputValidation/key.js +2 -1
- package/esm/utils/lang/index.js +12 -4
- package/esm/utils/lang/maps.js +14 -1
- package/esm/utils/settingsValidation/consent.js +12 -0
- package/esm/utils/settingsValidation/impressionsMode.js +7 -7
- package/esm/utils/settingsValidation/index.js +28 -10
- package/esm/utils/settingsValidation/runtime.js +7 -0
- package/package.json +8 -8
- package/src/consent/index.ts +8 -0
- package/src/consent/sdkUserConsent.ts +58 -0
- package/src/evaluator/parser/index.ts +1 -1
- package/src/evaluator/types.ts +2 -2
- package/src/evaluator/value/index.ts +2 -2
- package/src/evaluator/value/sanitize.ts +2 -2
- package/src/integrations/ga/GoogleAnalyticsToSplit.ts +7 -4
- package/src/integrations/ga/SplitToGoogleAnalytics.ts +7 -4
- package/src/integrations/pluggable.ts +2 -2
- package/src/integrations/types.ts +5 -0
- package/src/listeners/browser.ts +13 -9
- package/src/logger/constants.ts +6 -2
- package/src/logger/messages/debug.ts +3 -3
- package/src/logger/messages/error.ts +4 -3
- package/src/logger/messages/info.ts +7 -4
- package/src/logger/types.ts +4 -0
- package/src/sdkClient/client.ts +5 -5
- package/src/sdkClient/clientCS.ts +1 -1
- package/src/sdkClient/clientInputValidation.ts +8 -7
- package/src/sdkClient/sdkClient.ts +6 -9
- package/src/sdkClient/sdkClientMethod.ts +2 -2
- package/src/sdkClient/sdkClientMethodCS.ts +5 -11
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +6 -16
- package/src/sdkFactory/index.ts +11 -8
- package/src/sdkFactory/types.ts +14 -3
- package/src/storages/KeyBuilder.ts +2 -6
- package/src/storages/KeyBuilderCS.ts +13 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +23 -3
- package/src/storages/inLocalStorage/index.ts +1 -1
- package/src/storages/inMemory/ImpressionsCacheInMemory.ts +22 -1
- package/src/storages/inMemory/InMemoryStorage.ts +1 -1
- package/src/storages/inMemory/InMemoryStorageCS.ts +1 -1
- package/src/storages/inRedis/RedisAdapter.ts +8 -2
- package/src/storages/pluggable/index.ts +2 -2
- package/src/storages/types.ts +6 -2
- package/src/sync/offline/splitsParser/splitsParserFromFile.ts +1 -1
- package/src/sync/streaming/SSEClient/index.ts +2 -1
- package/src/sync/streaming/pushManager.ts +11 -2
- package/src/sync/submitters/eventsSyncTask.ts +19 -6
- package/src/sync/submitters/impressionsSyncTask.ts +16 -1
- package/src/sync/syncManagerOnline.ts +13 -7
- package/src/sync/types.ts +4 -1
- package/src/trackers/eventTracker.ts +11 -3
- package/src/trackers/impressionObserver/utils.ts +8 -1
- package/src/trackers/impressionsTracker.ts +7 -8
- package/src/types.ts +22 -1
- package/src/utils/constants/index.ts +5 -0
- package/src/utils/inputValidation/attributes.ts +1 -2
- package/src/utils/lang/index.ts +15 -4
- package/src/utils/lang/maps.ts +15 -1
- package/src/utils/settingsValidation/consent.ts +16 -0
- package/src/utils/settingsValidation/impressionsMode.ts +8 -8
- package/src/utils/settingsValidation/index.ts +29 -10
- package/src/utils/settingsValidation/runtime.ts +9 -0
- package/src/utils/settingsValidation/types.ts +12 -6
- package/types/consent/index.d.ts +2 -0
- package/types/consent/sdkUserConsent.d.ts +13 -0
- package/types/evaluator/types.d.ts +2 -2
- package/types/evaluator/value/index.d.ts +1 -1
- package/types/evaluator/value/sanitize.d.ts +1 -1
- package/types/integrations/ga/GoogleAnalyticsToSplit.d.ts +2 -2
- package/types/integrations/ga/SplitToGoogleAnalytics.d.ts +2 -3
- package/types/integrations/types.d.ts +4 -0
- package/types/logger/constants.d.ts +6 -2
- package/types/logger/types.d.ts +4 -0
- package/types/sdkClient/client.d.ts +2 -2
- package/types/sdkClient/clientAttributesDecoration.d.ts +1 -1
- package/types/sdkClient/clientInputValidation.d.ts +2 -3
- package/types/sdkClient/sdkClient.d.ts +2 -2
- package/types/sdkClient/sdkClientMethod.d.ts +2 -2
- package/types/sdkClient/sdkClientMethodCS.d.ts +2 -2
- package/types/sdkClient/sdkClientMethodCSWithTT.d.ts +2 -2
- package/types/sdkFactory/types.d.ts +12 -3
- package/types/sdkFactory/userConsentProps.d.ts +6 -0
- package/types/storages/KeyBuilderCS.d.ts +2 -0
- package/types/storages/inMemory/ImpressionsCacheInMemory.d.ts +9 -0
- package/types/storages/inRedis/RedisAdapter.d.ts +1 -1
- package/types/storages/types.d.ts +3 -1
- package/types/sync/types.d.ts +3 -0
- package/types/trackers/eventTracker.d.ts +2 -2
- package/types/trackers/impressionObserver/utils.d.ts +4 -0
- package/types/trackers/impressionsTracker.d.ts +2 -3
- package/types/types.d.ts +22 -1
- package/types/utils/consent.d.ts +2 -0
- package/types/utils/constants/index.d.ts +3 -0
- package/types/utils/lang/index.d.ts +6 -1
- package/types/utils/lang/maps.d.ts +7 -0
- package/types/utils/settingsValidation/consent.d.ts +6 -0
- package/types/utils/settingsValidation/impressionsMode.d.ts +1 -1
- package/types/utils/settingsValidation/runtime/browser.d.ts +2 -0
- package/types/utils/settingsValidation/runtime/node.d.ts +2 -0
- package/types/utils/settingsValidation/runtime.d.ts +2 -0
- package/types/utils/settingsValidation/types.d.ts +12 -6
- package/types/utils/settingsValidation/userConsent.d.ts +5 -0
- package/cjs/sdkClient/types.js +0 -2
- package/esm/sdkClient/types.js +0 -1
- package/src/sdkClient/types.ts +0 -21
|
@@ -25,6 +25,6 @@ export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: Sp
|
|
|
25
25
|
// Key is bound to the `track` method. Same thing happens with trafficType but only if provided
|
|
26
26
|
track: trafficType ? clientCS.track.bind(clientCS, key, trafficType) : clientCS.track.bind(clientCS, key),
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
isClientSide: true
|
|
29
29
|
}) as SplitIO.ICsClient;
|
|
30
30
|
}
|
|
@@ -15,14 +15,17 @@ import { startsWith } from '../utils/lang';
|
|
|
15
15
|
import { CONTROL, CONTROL_WITH_CONFIG } from '../utils/constants';
|
|
16
16
|
import { IReadinessManager } from '../readiness/types';
|
|
17
17
|
import { MaybeThenable } from '../dtos/types';
|
|
18
|
-
import { SplitIO } from '../types';
|
|
19
|
-
import {
|
|
18
|
+
import { ISettings, SplitIO } from '../types';
|
|
19
|
+
import { isStorageSync } from '../trackers/impressionObserver/utils';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Decorator that validates the input before actually executing the client methods.
|
|
23
23
|
* We should "guard" the client here, while not polluting the "real" implementation of those methods.
|
|
24
24
|
*/
|
|
25
|
-
export function clientInputValidationDecorator<TClient extends SplitIO.IClient | SplitIO.IAsyncClient>(
|
|
25
|
+
export function clientInputValidationDecorator<TClient extends SplitIO.IClient | SplitIO.IAsyncClient>(settings: ISettings, client: TClient, readinessManager: IReadinessManager): TClient {
|
|
26
|
+
|
|
27
|
+
const log = settings.log;
|
|
28
|
+
const isSync = isStorageSync(settings);
|
|
26
29
|
|
|
27
30
|
/**
|
|
28
31
|
* Avoid repeating this validations code
|
|
@@ -47,8 +50,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
|
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
function wrapResult<T>(value: T): MaybeThenable<T> {
|
|
50
|
-
|
|
51
|
-
return Promise.resolve(value);
|
|
53
|
+
return isSync ? value : Promise.resolve(value);
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
function getTreatment(maybeKey: SplitIO.SplitKey, maybeSplit: string, maybeAttributes?: SplitIO.Attributes) {
|
|
@@ -108,8 +110,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
|
|
|
108
110
|
if (isOperational && key && tt && event && eventValue !== false && properties !== false) { // @ts-expect-error
|
|
109
111
|
return client.track(key, tt, event, eventValue, properties, size);
|
|
110
112
|
} else {
|
|
111
|
-
|
|
112
|
-
return Promise.resolve(false);
|
|
113
|
+
return isSync ? false : Promise.resolve(false);
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { IStatusInterface, SplitIO } from '../types';
|
|
3
|
-
import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE } from '../utils/constants';
|
|
4
3
|
import { releaseApiKey } from '../utils/inputValidation/apiKey';
|
|
5
4
|
import { clientFactory } from './client';
|
|
6
5
|
import { clientInputValidationDecorator } from './clientInputValidation';
|
|
7
|
-
import {
|
|
6
|
+
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Creates an Sdk client, i.e., a base client with status and destroy interface
|
|
11
10
|
*/
|
|
12
|
-
export function sdkClientFactory(params:
|
|
13
|
-
const { sdkReadinessManager, syncManager, storage, signalListener, settings
|
|
11
|
+
export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: boolean): SplitIO.IClient | SplitIO.IAsyncClient {
|
|
12
|
+
const { sdkReadinessManager, syncManager, storage, signalListener, settings } = params;
|
|
14
13
|
|
|
15
14
|
return objectAssign(
|
|
16
15
|
// Proto-linkage of the readiness Event Emitter
|
|
@@ -18,11 +17,9 @@ export function sdkClientFactory(params: ISdkClientFactoryParams): SplitIO.IClie
|
|
|
18
17
|
|
|
19
18
|
// Client API (getTreatment* & track methods)
|
|
20
19
|
clientInputValidationDecorator(
|
|
21
|
-
settings
|
|
20
|
+
settings,
|
|
22
21
|
clientFactory(params),
|
|
23
|
-
sdkReadinessManager.readinessManager
|
|
24
|
-
// storage is async if and only if mode is consumer or partial consumer
|
|
25
|
-
[CONSUMER_MODE, CONSUMER_PARTIAL_MODE].indexOf(settings.mode) === -1 ? true : false,
|
|
22
|
+
sdkReadinessManager.readinessManager
|
|
26
23
|
),
|
|
27
24
|
|
|
28
25
|
// Sdk destroy
|
|
@@ -38,7 +35,7 @@ export function sdkClientFactory(params: ISdkClientFactoryParams): SplitIO.IClie
|
|
|
38
35
|
signalListener && signalListener.stop();
|
|
39
36
|
|
|
40
37
|
// Release the API Key if it is the main client
|
|
41
|
-
if (!
|
|
38
|
+
if (!isSharedClient) releaseApiKey(settings.core.authorizationKey);
|
|
42
39
|
|
|
43
40
|
// Cleanup storage
|
|
44
41
|
return storage.destroy();
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ISdkClientFactoryParams } from './types';
|
|
2
1
|
import { SplitIO } from '../types';
|
|
3
2
|
import { sdkClientFactory } from './sdkClient';
|
|
4
3
|
import { RETRIEVE_CLIENT_DEFAULT } from '../logger/constants';
|
|
4
|
+
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Factory of client method for server-side SDKs (ISDK and IAsyncSDK)
|
|
8
8
|
*/
|
|
9
|
-
export function sdkClientMethodFactory(params:
|
|
9
|
+
export function sdkClientMethodFactory(params: ISdkFactoryContext): () => SplitIO.IClient | SplitIO.IAsyncClient {
|
|
10
10
|
const log = params.settings.log;
|
|
11
11
|
const clientInstance = sdkClientFactory(params);
|
|
12
12
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { clientCSDecorator } from './clientCS';
|
|
2
|
-
import { ISdkClientFactoryParams } from './types';
|
|
3
2
|
import { SplitIO } from '../types';
|
|
4
3
|
import { validateKey } from '../utils/inputValidation/key';
|
|
5
4
|
import { getMatching, keyParser } from '../utils/key';
|
|
@@ -8,6 +7,7 @@ import { ISyncManagerCS } from '../sync/types';
|
|
|
8
7
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
9
8
|
import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } from '../logger/constants';
|
|
10
9
|
import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
10
|
+
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
11
11
|
|
|
12
12
|
function buildInstanceId(key: SplitIO.SplitKey) {
|
|
13
13
|
// @ts-ignore
|
|
@@ -20,18 +20,13 @@ const method = 'Client instantiation';
|
|
|
20
20
|
* Factory of client method for the client-side API variant where TT is ignored and thus
|
|
21
21
|
* clients don't have a binded TT for the track method.
|
|
22
22
|
*/
|
|
23
|
-
export function sdkClientMethodCSFactory(params:
|
|
23
|
+
export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey) => SplitIO.ICsClient {
|
|
24
24
|
const { storage, syncManager, sdkReadinessManager, settings: { core: { key }, startup: { readyTimeout }, log } } = params;
|
|
25
25
|
|
|
26
|
-
// Keeping similar behaviour as in the isomorphic JS SDK: if settings key is invalid,
|
|
27
|
-
// `false` value is used as binded key of the default client, but trafficType is ignored
|
|
28
|
-
// @TODO handle as a non-recoverable error
|
|
29
|
-
const validKey = validateKey(log, key, method);
|
|
30
|
-
|
|
31
26
|
const mainClientInstance = clientCSDecorator(
|
|
32
27
|
log,
|
|
33
|
-
sdkClientFactory(params) as SplitIO.IClient,
|
|
34
|
-
|
|
28
|
+
sdkClientFactory(params) as SplitIO.IClient,
|
|
29
|
+
key
|
|
35
30
|
);
|
|
36
31
|
|
|
37
32
|
const parsedDefaultKey = keyParser(key);
|
|
@@ -81,8 +76,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?
|
|
|
81
76
|
storage: sharedStorage || storage,
|
|
82
77
|
syncManager: sharedSyncManager,
|
|
83
78
|
signalListener: undefined, // only the main client "destroy" method stops the signal listener
|
|
84
|
-
|
|
85
|
-
})) as SplitIO.IClient,
|
|
79
|
+
}), true) as SplitIO.IClient,
|
|
86
80
|
validKey
|
|
87
81
|
);
|
|
88
82
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { clientCSDecorator } from './clientCS';
|
|
2
|
-
import { ISdkClientFactoryParams } from './types';
|
|
3
2
|
import { SplitIO } from '../types';
|
|
4
3
|
import { validateKey } from '../utils/inputValidation/key';
|
|
5
4
|
import { validateTrafficType } from '../utils/inputValidation/trafficType';
|
|
@@ -9,6 +8,7 @@ import { ISyncManagerCS } from '../sync/types';
|
|
|
9
8
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
10
9
|
import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } from '../logger/constants';
|
|
11
10
|
import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
11
|
+
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
12
12
|
|
|
13
13
|
function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) {
|
|
14
14
|
// @ts-ignore
|
|
@@ -22,23 +22,14 @@ const method = 'Client instantiation';
|
|
|
22
22
|
* where clients can have a binded TT for the track method, which is provided via the settings
|
|
23
23
|
* (default client) or the client method (shared clients).
|
|
24
24
|
*/
|
|
25
|
-
export function sdkClientMethodCSFactory(params:
|
|
25
|
+
export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient {
|
|
26
26
|
const { storage, syncManager, sdkReadinessManager, settings: { core: { key, trafficType }, startup: { readyTimeout }, log } } = params;
|
|
27
27
|
|
|
28
|
-
// Keeping the behaviour as in the isomorphic JS SDK: if settings key or TT are invalid,
|
|
29
|
-
// `false` value is used as binded key/TT of the default client, which leads to several issues.
|
|
30
|
-
// @TODO update when supporting non-recoverable errors
|
|
31
|
-
const validKey = validateKey(log, key, method);
|
|
32
|
-
let validTrafficType;
|
|
33
|
-
if (trafficType !== undefined) {
|
|
34
|
-
validTrafficType = validateTrafficType(log, trafficType, method);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
28
|
const mainClientInstance = clientCSDecorator(
|
|
38
29
|
log,
|
|
39
|
-
sdkClientFactory(params) as SplitIO.IClient,
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
sdkClientFactory(params) as SplitIO.IClient,
|
|
31
|
+
key,
|
|
32
|
+
trafficType
|
|
42
33
|
);
|
|
43
34
|
|
|
44
35
|
const parsedDefaultKey = keyParser(key);
|
|
@@ -95,8 +86,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?
|
|
|
95
86
|
storage: sharedStorage || storage,
|
|
96
87
|
syncManager: sharedSyncManager,
|
|
97
88
|
signalListener: undefined, // only the main client "destroy" method stops the signal listener
|
|
98
|
-
|
|
99
|
-
})) as SplitIO.IClient,
|
|
89
|
+
}), true) as SplitIO.IClient,
|
|
100
90
|
validKey,
|
|
101
91
|
validTrafficType
|
|
102
92
|
);
|
package/src/sdkFactory/index.ts
CHANGED
|
@@ -12,14 +12,15 @@ import { createLoggerAPI } from '../logger/sdkLogger';
|
|
|
12
12
|
import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
13
13
|
import { metadataBuilder } from '../storages/metadataBuilder';
|
|
14
14
|
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
15
|
+
import { objectAssign } from '../utils/lang/objectAssign';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Modular SDK factory
|
|
18
19
|
*/
|
|
19
20
|
export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.ISDK | SplitIO.IAsyncSDK {
|
|
20
21
|
|
|
21
|
-
const { settings, platform, storageFactory, splitApiFactory,
|
|
22
|
-
syncManagerFactory, SignalListener, impressionsObserverFactory,
|
|
22
|
+
const { settings, platform, storageFactory, splitApiFactory, extraProps,
|
|
23
|
+
syncManagerFactory, SignalListener, impressionsObserverFactory,
|
|
23
24
|
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory } = params;
|
|
24
25
|
const log = settings.log;
|
|
25
26
|
|
|
@@ -33,6 +34,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
33
34
|
|
|
34
35
|
// @TODO consider passing the settings object, so that each storage access only what it needs
|
|
35
36
|
const storageFactoryParams: IStorageFactoryParams = {
|
|
37
|
+
impressionsQueueSize: settings.scheduler.impressionsQueueSize,
|
|
36
38
|
eventsQueueSize: settings.scheduler.eventsQueueSize,
|
|
37
39
|
optimize: shouldBeOptimized(settings),
|
|
38
40
|
|
|
@@ -72,14 +74,15 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
72
74
|
|
|
73
75
|
// trackers
|
|
74
76
|
const observer = impressionsObserverFactory && impressionsObserverFactory();
|
|
75
|
-
const impressionsTracker = impressionsTrackerFactory(
|
|
76
|
-
const eventTracker = eventTrackerFactory(
|
|
77
|
+
const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, integrationsManager, observer, storage.impressionCounts);
|
|
78
|
+
const eventTracker = eventTrackerFactory(settings, storage.events, integrationsManager);
|
|
77
79
|
|
|
78
80
|
// signal listener
|
|
79
81
|
const signalListener = SignalListener && new SignalListener(syncManager, settings, storage, splitApi);
|
|
80
82
|
|
|
81
83
|
// Sdk client and manager
|
|
82
|
-
const
|
|
84
|
+
const ctx = { eventTracker, impressionsTracker, sdkReadinessManager, settings, storage, syncManager, signalListener };
|
|
85
|
+
const clientMethod = sdkClientMethodFactory(ctx);
|
|
83
86
|
const managerInstance = sdkManagerFactory(log, storage.splits, sdkReadinessManager);
|
|
84
87
|
|
|
85
88
|
syncManager && syncManager.start();
|
|
@@ -87,12 +90,12 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
87
90
|
|
|
88
91
|
log.info(NEW_FACTORY);
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
// @ts-ignore
|
|
94
|
+
return objectAssign({
|
|
91
95
|
// Split evaluation and event tracking engine
|
|
92
96
|
client: clientMethod,
|
|
93
97
|
|
|
94
98
|
// Manager API to explore available information
|
|
95
|
-
// @ts-ignore
|
|
96
99
|
manager() {
|
|
97
100
|
log.debug(RETRIEVE_MANAGER);
|
|
98
101
|
return managerInstance;
|
|
@@ -102,5 +105,5 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
102
105
|
Logger: createLoggerAPI(settings.log),
|
|
103
106
|
|
|
104
107
|
settings,
|
|
105
|
-
};
|
|
108
|
+
}, extraProps && extraProps(ctx));
|
|
106
109
|
}
|
package/src/sdkFactory/types.ts
CHANGED
|
@@ -2,13 +2,23 @@ import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/
|
|
|
2
2
|
import { ISignalListener } from '../listeners/types';
|
|
3
3
|
import { ILogger } from '../logger/types';
|
|
4
4
|
import { ISdkReadinessManager } from '../readiness/types';
|
|
5
|
-
import { ISdkClientFactoryParams } from '../sdkClient/types';
|
|
6
5
|
import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
|
|
7
6
|
import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
|
|
8
7
|
import { ISyncManager, ISyncManagerFactoryParams } from '../sync/types';
|
|
9
8
|
import { IImpressionObserver } from '../trackers/impressionObserver/types';
|
|
9
|
+
import { IImpressionsTracker, IEventTracker } from '../trackers/types';
|
|
10
10
|
import { SplitIO, ISettings, IEventEmitter } from '../types';
|
|
11
11
|
|
|
12
|
+
export interface ISdkFactoryContext {
|
|
13
|
+
storage: IStorageSync | IStorageAsync,
|
|
14
|
+
sdkReadinessManager: ISdkReadinessManager,
|
|
15
|
+
settings: ISettings
|
|
16
|
+
impressionsTracker: IImpressionsTracker,
|
|
17
|
+
eventTracker: IEventTracker,
|
|
18
|
+
signalListener?: ISignalListener
|
|
19
|
+
syncManager?: ISyncManager,
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
/**
|
|
13
23
|
* Environment related dependencies.
|
|
14
24
|
* These getters are called a fixed number of times per factory instantiation.
|
|
@@ -53,7 +63,7 @@ export interface ISdkFactoryParams {
|
|
|
53
63
|
|
|
54
64
|
// Sdk client method factory (ISDK::client method).
|
|
55
65
|
// It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
|
|
56
|
-
sdkClientMethodFactory: (params:
|
|
66
|
+
sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
|
|
57
67
|
|
|
58
68
|
// Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
|
|
59
69
|
// Pass only if `syncManager` (used by Node listener) and `splitApi` (used by Browser listener) are passed.
|
|
@@ -64,10 +74,11 @@ export interface ISdkFactoryParams {
|
|
|
64
74
|
serviceApi: ISplitApi | undefined) => ISignalListener, // Used by BrowserSignalListener
|
|
65
75
|
|
|
66
76
|
// @TODO review impressionListener and integrations interfaces. What about handling impressionListener as an integration ?
|
|
67
|
-
impressionListener?: SplitIO.IImpressionListener,
|
|
68
77
|
integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined,
|
|
69
78
|
|
|
70
79
|
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
71
80
|
impressionsObserverFactory?: () => IImpressionObserver
|
|
72
81
|
|
|
82
|
+
// Optional function to assign additional properties to the factory instance
|
|
83
|
+
extraProps?: (params: ISdkFactoryContext) => object
|
|
73
84
|
}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { startsWith } from '../utils/lang';
|
|
2
2
|
|
|
3
3
|
const everythingAtTheEnd = /[^.]+$/;
|
|
4
4
|
|
|
5
5
|
const DEFAULT_PREFIX = 'SPLITIO';
|
|
6
6
|
|
|
7
7
|
export function validatePrefix(prefix: unknown) {
|
|
8
|
-
return prefix
|
|
9
|
-
endsWith(prefix, '.' + DEFAULT_PREFIX) ?
|
|
10
|
-
prefix : // suffix already appended
|
|
11
|
-
prefix + '.' + DEFAULT_PREFIX : // append suffix
|
|
12
|
-
DEFAULT_PREFIX; // use default prefix if none is provided
|
|
8
|
+
return prefix ? prefix + '.SPLITIO' : 'SPLITIO';
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
export class KeyBuilder {
|
|
@@ -16,10 +16,22 @@ export class KeyBuilderCS extends KeyBuilder {
|
|
|
16
16
|
* @override
|
|
17
17
|
*/
|
|
18
18
|
buildSegmentNameKey(segmentName: string) {
|
|
19
|
-
return `${this.
|
|
19
|
+
return `${this.prefix}.${this.matchingKey}.segment.${segmentName}`;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
extractSegmentName(builtSegmentKeyName: string) {
|
|
23
|
+
const prefix = `${this.prefix}.${this.matchingKey}.segment.`;
|
|
24
|
+
|
|
25
|
+
if (startsWith(builtSegmentKeyName, prefix))
|
|
26
|
+
return builtSegmentKeyName.substr(prefix.length);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
|
|
30
|
+
buildOldSegmentNameKey(segmentName: string) {
|
|
31
|
+
return `${this.matchingKey}.${this.prefix}.segment.${segmentName}`;
|
|
32
|
+
}
|
|
33
|
+
// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
|
|
34
|
+
extractOldSegmentKey(builtSegmentKeyName: string) {
|
|
23
35
|
const prefix = `${this.matchingKey}.${this.prefix}.segment.`;
|
|
24
36
|
|
|
25
37
|
if (startsWith(builtSegmentKeyName, prefix))
|
|
@@ -67,9 +67,29 @@ export class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
|
|
|
67
67
|
|
|
68
68
|
// Scan current values from localStorage
|
|
69
69
|
const storedSegmentNames = Object.keys(localStorage).reduce((accum, key) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (
|
|
70
|
+
let segmentName = this.keys.extractSegmentName(key);
|
|
71
|
+
|
|
72
|
+
if (segmentName) {
|
|
73
|
+
accum.push(segmentName);
|
|
74
|
+
} else {
|
|
75
|
+
// @BREAKING: This is only to clean up "old" keys. Remove this whole else code block.
|
|
76
|
+
segmentName = this.keys.extractOldSegmentKey(key);
|
|
77
|
+
|
|
78
|
+
if (segmentName) { // this was an old segment key, let's clean up.
|
|
79
|
+
const newSegmentKey = this.keys.buildSegmentNameKey(segmentName);
|
|
80
|
+
try {
|
|
81
|
+
// If the new format key is not there, create it.
|
|
82
|
+
if (!localStorage.getItem(newSegmentKey) && names.indexOf(segmentName) > -1) {
|
|
83
|
+
localStorage.setItem(newSegmentKey, DEFINED);
|
|
84
|
+
// we are migrating a segment, let's track it.
|
|
85
|
+
accum.push(segmentName);
|
|
86
|
+
}
|
|
87
|
+
localStorage.removeItem(key); // we migrated the current key, let's delete it.
|
|
88
|
+
} catch (e) {
|
|
89
|
+
this.log.error(e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
73
93
|
|
|
74
94
|
return accum;
|
|
75
95
|
}, [] as string[]);
|
|
@@ -40,7 +40,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
40
40
|
return {
|
|
41
41
|
splits: new SplitsCacheInLocal(log, keys, expirationTimestamp, params.splitFiltersValidation),
|
|
42
42
|
segments: new MySegmentsCacheInLocal(log, keys),
|
|
43
|
-
impressions: new ImpressionsCacheInMemory(),
|
|
43
|
+
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
44
44
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
45
45
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
46
46
|
|
|
@@ -3,13 +3,34 @@ import { ImpressionDTO } from '../../types';
|
|
|
3
3
|
|
|
4
4
|
export class ImpressionsCacheInMemory implements IImpressionsCacheSync {
|
|
5
5
|
|
|
6
|
-
private
|
|
6
|
+
private onFullQueue?: () => void;
|
|
7
|
+
private readonly maxQueue: number;
|
|
8
|
+
private queue: ImpressionDTO[];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param impressionsQueueSize number of queued impressions to call onFullQueueCb.
|
|
13
|
+
* Default value is 0, that means no maximum value, in case we want to avoid this being triggered.
|
|
14
|
+
*/
|
|
15
|
+
constructor(impressionsQueueSize: number = 0) {
|
|
16
|
+
this.maxQueue = impressionsQueueSize;
|
|
17
|
+
this.queue = [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setOnFullQueueCb(cb: () => void) {
|
|
21
|
+
this.onFullQueue = cb;
|
|
22
|
+
}
|
|
7
23
|
|
|
8
24
|
/**
|
|
9
25
|
* Store impressions in sequential order
|
|
10
26
|
*/
|
|
11
27
|
track(data: ImpressionDTO[]) {
|
|
12
28
|
this.queue.push(...data);
|
|
29
|
+
|
|
30
|
+
// Check if the cache queue is full and we need to flush it.
|
|
31
|
+
if (this.maxQueue > 0 && this.queue.length >= this.maxQueue && this.onFullQueue) {
|
|
32
|
+
this.onFullQueue();
|
|
33
|
+
}
|
|
13
34
|
}
|
|
14
35
|
|
|
15
36
|
/**
|
|
@@ -16,7 +16,7 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
|
|
|
16
16
|
return {
|
|
17
17
|
splits: new SplitsCacheInMemory(),
|
|
18
18
|
segments: new SegmentsCacheInMemory(),
|
|
19
|
-
impressions: new ImpressionsCacheInMemory(),
|
|
19
|
+
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
20
20
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
21
21
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
22
22
|
|
|
@@ -16,7 +16,7 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
16
16
|
return {
|
|
17
17
|
splits: new SplitsCacheInMemory(),
|
|
18
18
|
segments: new MySegmentsCacheInMemory(),
|
|
19
|
-
impressions: new ImpressionsCacheInMemory(),
|
|
19
|
+
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
20
20
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
21
21
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
22
22
|
|
|
@@ -164,6 +164,12 @@ export class RedisAdapter extends ioredis {
|
|
|
164
164
|
} else { // If it IS the string URL, that'll be the first param for ioredis.
|
|
165
165
|
result.unshift(options.url);
|
|
166
166
|
}
|
|
167
|
+
if (options.connectionTimeout) {
|
|
168
|
+
merge(opts, { connectTimeout: options.connectionTimeout });
|
|
169
|
+
}
|
|
170
|
+
if (options.tls) {
|
|
171
|
+
merge(opts, { tls: options.tls });
|
|
172
|
+
}
|
|
167
173
|
|
|
168
174
|
return result;
|
|
169
175
|
}
|
|
@@ -171,9 +177,9 @@ export class RedisAdapter extends ioredis {
|
|
|
171
177
|
/**
|
|
172
178
|
* Parses the options into what we care about.
|
|
173
179
|
*/
|
|
174
|
-
static _defineOptions({ connectionTimeout, operationTimeout, url, host, port, db, pass }: Record<string, any>) {
|
|
180
|
+
static _defineOptions({ connectionTimeout, operationTimeout, url, host, port, db, pass, tls }: Record<string, any>) {
|
|
175
181
|
const parsedOptions = {
|
|
176
|
-
connectionTimeout, operationTimeout, url, host, port, db, pass
|
|
182
|
+
connectionTimeout, operationTimeout, url, host, port, db, pass, tls
|
|
177
183
|
};
|
|
178
184
|
|
|
179
185
|
return merge({}, DEFAULT_OPTIONS, parsedOptions);
|
|
@@ -63,7 +63,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
63
63
|
|
|
64
64
|
const prefix = validatePrefix(options.prefix);
|
|
65
65
|
|
|
66
|
-
function PluggableStorageFactory({ log, metadata, onReadyCb, mode, eventsQueueSize, optimize }: IStorageFactoryParams): IStorageAsync {
|
|
66
|
+
function PluggableStorageFactory({ log, metadata, onReadyCb, mode, eventsQueueSize, impressionsQueueSize, optimize }: IStorageFactoryParams): IStorageAsync {
|
|
67
67
|
const keys = new KeyBuilderSS(prefix, metadata);
|
|
68
68
|
const wrapper = wrapperAdapter(log, options.wrapper);
|
|
69
69
|
const isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
|
|
@@ -74,7 +74,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
74
74
|
return {
|
|
75
75
|
splits: new SplitsCachePluggable(log, keys, wrapper),
|
|
76
76
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
77
|
-
impressions: isPartialConsumer ? new ImpressionsCacheInMemory() : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
77
|
+
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
78
78
|
impressionCounts: optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
79
79
|
events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
|
|
80
80
|
// @TODO add telemetry cache when required
|
package/src/storages/types.ts
CHANGED
|
@@ -298,7 +298,7 @@ export interface IRecorderCacheProducerSync<T> {
|
|
|
298
298
|
// @TODO names are inconsistent with spec
|
|
299
299
|
/* Checks if cache is empty. Returns true if the cache was just created or cleared */
|
|
300
300
|
isEmpty(): boolean
|
|
301
|
-
/*
|
|
301
|
+
/* Clears cache data */
|
|
302
302
|
clear(): void
|
|
303
303
|
/* Gets cache data */
|
|
304
304
|
state(): T
|
|
@@ -307,10 +307,13 @@ export interface IRecorderCacheProducerSync<T> {
|
|
|
307
307
|
|
|
308
308
|
export interface IImpressionsCacheSync extends IImpressionsCacheBase, IRecorderCacheProducerSync<ImpressionDTO[]> {
|
|
309
309
|
track(data: ImpressionDTO[]): void
|
|
310
|
+
/* Registers callback for full queue */
|
|
311
|
+
setOnFullQueueCb(cb: () => void): void
|
|
310
312
|
}
|
|
311
313
|
|
|
312
314
|
export interface IEventsCacheSync extends IEventsCacheBase, IRecorderCacheProducerSync<SplitIO.EventData[]> {
|
|
313
315
|
track(data: SplitIO.EventData, size?: number): boolean
|
|
316
|
+
/* Registers callback for full queue */
|
|
314
317
|
setOnFullQueueCb(cb: () => void): void
|
|
315
318
|
}
|
|
316
319
|
|
|
@@ -423,6 +426,7 @@ export type DataLoader = (storage: IStorageSync, matchingKey: string) => void
|
|
|
423
426
|
|
|
424
427
|
export interface IStorageFactoryParams {
|
|
425
428
|
log: ILogger,
|
|
429
|
+
impressionsQueueSize?: number,
|
|
426
430
|
eventsQueueSize?: number,
|
|
427
431
|
optimize?: boolean /* whether create the `impressionCounts` cache (OPTIMIZED impression mode) or not (DEBUG impression mode) */,
|
|
428
432
|
|
|
@@ -443,7 +447,7 @@ export interface IStorageFactoryParams {
|
|
|
443
447
|
export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
|
|
444
448
|
|
|
445
449
|
export type IStorageSyncFactory = {
|
|
446
|
-
type: StorageType,
|
|
450
|
+
readonly type: StorageType,
|
|
447
451
|
(params: IStorageFactoryParams): IStorageSync
|
|
448
452
|
}
|
|
449
453
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IEventSourceConstructor } from '../../../services/types';
|
|
2
2
|
import { ISettings } from '../../../types';
|
|
3
|
+
import { isString } from '../../../utils/lang';
|
|
3
4
|
import { IAuthTokenPushEnabled } from '../AuthClient/types';
|
|
4
5
|
import { ISSEClient, ISseEventHandler } from './types';
|
|
5
6
|
|
|
@@ -15,7 +16,7 @@ const CONTROL_CHANNEL_REGEX = /^control_/;
|
|
|
15
16
|
*/
|
|
16
17
|
function buildSSEHeaders(settings: ISettings) {
|
|
17
18
|
const headers: Record<string, string> = {
|
|
18
|
-
SplitSDKClientKey: settings.core.authorizationKey.slice(-4),
|
|
19
|
+
SplitSDKClientKey: isString(settings.core.authorizationKey) ? settings.core.authorizationKey.slice(-4) : '',
|
|
19
20
|
SplitSDKVersion: settings.version,
|
|
20
21
|
};
|
|
21
22
|
|
|
@@ -71,6 +71,7 @@ export function pushManagerFactory(
|
|
|
71
71
|
// It is used to halt the `connectPush` process if it was in progress.
|
|
72
72
|
let disconnected: boolean | undefined;
|
|
73
73
|
// flag that indicates a PUSH_NONRETRYABLE_ERROR, condition with which starting pushManager again is ignored.
|
|
74
|
+
// true if STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE or Auth errors.
|
|
74
75
|
let disabled: boolean | undefined; // `disabled` implies `disconnected === true`
|
|
75
76
|
|
|
76
77
|
/** PushManager functions related to initialization */
|
|
@@ -296,12 +297,15 @@ export function pushManagerFactory(
|
|
|
296
297
|
// Expose Event Emitter functionality and Event constants
|
|
297
298
|
Object.create(pushEmitter),
|
|
298
299
|
{
|
|
299
|
-
// Stop/pause push mode
|
|
300
|
+
// Stop/pause push mode.
|
|
301
|
+
// It doesn't emit events. Neither PUSH_SUBSYSTEM_DOWN to start polling.
|
|
300
302
|
stop() {
|
|
301
303
|
disconnectPush(); // `handleNonRetryableError` cannot be used as `stop`, because it emits PUSH_SUBSYSTEM_DOWN event, which starts polling.
|
|
302
304
|
if (userKey) this.remove(userKey); // Necessary to properly resume streaming in client-side (e.g., RN SDK transition to foreground).
|
|
303
305
|
},
|
|
304
|
-
|
|
306
|
+
|
|
307
|
+
// Start/resume push mode.
|
|
308
|
+
// It eventually emits PUSH_SUBSYSTEM_DOWN, that starts polling, or PUSH_SUBSYSTEM_UP, that executes a syncAll
|
|
305
309
|
start() {
|
|
306
310
|
// Guard condition to avoid calling `connectPush` again if the `start` method is called multiple times or if push has been disabled.
|
|
307
311
|
if (disabled || disconnected === false) return;
|
|
@@ -311,6 +315,11 @@ export function pushManagerFactory(
|
|
|
311
315
|
else setTimeout(connectPush); // server-side runs in next cycle as in client-side, for consistency with client-side
|
|
312
316
|
},
|
|
313
317
|
|
|
318
|
+
// true/false if start or stop was called last respectively
|
|
319
|
+
isRunning(){
|
|
320
|
+
return disconnected === false;
|
|
321
|
+
},
|
|
322
|
+
|
|
314
323
|
// [Only for client-side]
|
|
315
324
|
add(userKey: string, mySegmentsSyncTask: ISegmentsSyncTask) {
|
|
316
325
|
const hash = hashUserKey(userKey);
|