@splitsoftware/splitio-commons 2.0.3-rc.0 → 2.1.0-rc.0
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 +0 -4
- package/README.md +2 -2
- package/cjs/evaluator/index.js +0 -2
- package/cjs/listeners/browser.js +6 -4
- package/cjs/listeners/node.js +2 -2
- package/cjs/sdkClient/client.js +13 -13
- package/cjs/sdkClient/sdkClient.js +1 -1
- package/cjs/sdkFactory/index.js +14 -9
- package/cjs/sdkManager/index.js +1 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +0 -7
- package/cjs/storages/AbstractSplitsCacheSync.js +0 -7
- package/cjs/storages/KeyBuilderCS.js +3 -0
- package/cjs/storages/dataLoader.js +3 -2
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +1 -57
- package/cjs/storages/inLocalStorage/index.js +8 -7
- package/cjs/storages/inLocalStorage/validateCache.js +80 -0
- package/cjs/storages/inMemory/InMemoryStorage.js +3 -3
- package/cjs/storages/inMemory/InMemoryStorageCS.js +3 -4
- package/cjs/storages/inRedis/index.js +13 -9
- package/cjs/storages/pluggable/index.js +21 -16
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +1 -10
- package/cjs/sync/streaming/pushManager.js +8 -6
- package/cjs/sync/submitters/impressionCountsSubmitter.js +4 -2
- package/cjs/sync/submitters/submitterManager.js +6 -3
- package/cjs/sync/syncManagerOnline.js +10 -4
- package/cjs/trackers/eventTracker.js +1 -1
- package/cjs/trackers/impressionsTracker.js +19 -18
- package/cjs/trackers/strategy/strategyDebug.js +11 -4
- package/cjs/trackers/strategy/strategyNone.js +16 -11
- package/cjs/trackers/strategy/strategyOptimized.js +21 -11
- package/cjs/utils/settingsValidation/index.js +1 -1
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/evaluator/index.js +0 -2
- package/esm/listeners/browser.js +3 -1
- package/esm/listeners/node.js +2 -2
- package/esm/sdkClient/client.js +13 -13
- package/esm/sdkClient/sdkClient.js +1 -1
- package/esm/sdkFactory/index.js +15 -10
- package/esm/sdkManager/index.js +1 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +0 -7
- package/esm/storages/AbstractSplitsCacheSync.js +0 -7
- package/esm/storages/KeyBuilderCS.js +3 -0
- package/esm/storages/dataLoader.js +2 -1
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +1 -57
- package/esm/storages/inLocalStorage/index.js +9 -8
- package/esm/storages/inLocalStorage/validateCache.js +76 -0
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -5
- package/esm/storages/inRedis/index.js +14 -10
- package/esm/storages/pluggable/index.js +22 -17
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
- package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -11
- package/esm/sync/streaming/pushManager.js +8 -6
- package/esm/sync/submitters/impressionCountsSubmitter.js +4 -2
- package/esm/sync/submitters/submitterManager.js +6 -3
- package/esm/sync/syncManagerOnline.js +10 -4
- package/esm/trackers/eventTracker.js +1 -1
- package/esm/trackers/impressionsTracker.js +19 -18
- package/esm/trackers/strategy/strategyDebug.js +11 -4
- package/esm/trackers/strategy/strategyNone.js +16 -11
- package/esm/trackers/strategy/strategyOptimized.js +21 -11
- package/esm/utils/settingsValidation/index.js +1 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +1 -2
- package/src/evaluator/index.ts +0 -2
- package/src/evaluator/types.ts +1 -1
- package/src/listeners/browser.ts +3 -1
- package/src/listeners/node.ts +2 -2
- package/src/sdkClient/client.ts +11 -11
- package/src/sdkClient/sdkClient.ts +1 -1
- package/src/sdkFactory/index.ts +16 -11
- package/src/sdkFactory/types.ts +1 -1
- package/src/sdkManager/index.ts +1 -2
- package/src/storages/AbstractSplitsCacheAsync.ts +0 -8
- package/src/storages/AbstractSplitsCacheSync.ts +0 -8
- package/src/storages/KeyBuilderCS.ts +4 -0
- package/src/storages/dataLoader.ts +3 -1
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +1 -66
- package/src/storages/inLocalStorage/index.ts +12 -13
- package/src/storages/inLocalStorage/validateCache.ts +92 -0
- package/src/storages/inMemory/InMemoryStorage.ts +4 -4
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -5
- package/src/storages/inRedis/index.ts +10 -10
- package/src/storages/pluggable/index.ts +22 -17
- package/src/storages/types.ts +3 -6
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +6 -5
- package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -11
- package/src/sync/streaming/pushManager.ts +8 -6
- package/src/sync/submitters/impressionCountsSubmitter.ts +4 -2
- package/src/sync/submitters/submitterManager.ts +4 -3
- package/src/sync/submitters/uniqueKeysSubmitter.ts +3 -2
- package/src/sync/syncManagerOnline.ts +11 -5
- package/src/trackers/eventTracker.ts +1 -1
- package/src/trackers/impressionsTracker.ts +19 -18
- package/src/trackers/strategy/strategyDebug.ts +11 -4
- package/src/trackers/strategy/strategyNone.ts +17 -11
- package/src/trackers/strategy/strategyOptimized.ts +20 -10
- package/src/trackers/types.ts +8 -2
- package/src/utils/lang/index.ts +1 -1
- package/src/utils/settingsValidation/index.ts +1 -1
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/index.d.ts +1 -1
- package/types/splitio.d.ts +26 -6
- package/cjs/utils/constants/browser.js +0 -5
- package/esm/utils/constants/browser.js +0 -2
- package/src/utils/constants/browser.ts +0 -2
|
@@ -9,11 +9,16 @@ import SplitIO from '../../types/splitio';
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
|
|
12
|
+
*
|
|
13
|
+
* @param impressionsCache - cache to save impressions
|
|
14
|
+
* @param metadata - runtime metadata (ip, hostname and version)
|
|
15
|
+
* @param impressionListener - optional impression listener
|
|
16
|
+
* @param integrationsManager - optional integrations manager
|
|
17
|
+
* @param strategy - strategy for impressions tracking.
|
|
12
18
|
*/
|
|
13
19
|
export function impressionsTrackerFactory(
|
|
14
20
|
settings: ISettings,
|
|
15
21
|
impressionsCache: IImpressionsCacheBase,
|
|
16
|
-
noneStrategy: IStrategy,
|
|
17
22
|
strategy: IStrategy,
|
|
18
23
|
whenInit: (cb: () => void) => void,
|
|
19
24
|
integrationsManager?: IImpressionsHandler,
|
|
@@ -23,44 +28,40 @@ export function impressionsTrackerFactory(
|
|
|
23
28
|
const { log, impressionListener, runtime: { ip, hostname }, version } = settings;
|
|
24
29
|
|
|
25
30
|
return {
|
|
26
|
-
track(impressions:
|
|
31
|
+
track(impressions: SplitIO.ImpressionDTO[], attributes?: SplitIO.Attributes) {
|
|
27
32
|
if (settings.userConsent === CONSENT_DECLINED) return;
|
|
28
33
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
noneStrategy.process(impression) :
|
|
32
|
-
strategy.process(impression);
|
|
33
|
-
});
|
|
34
|
+
const impressionsCount = impressions.length;
|
|
35
|
+
const { impressionsToStore, impressionsToListener, deduped } = strategy.process(impressions);
|
|
34
36
|
|
|
35
|
-
const
|
|
36
|
-
const impressionsToStoreLength = impressionsToStore.length;
|
|
37
|
+
const impressionsToListenerCount = impressionsToListener.length;
|
|
37
38
|
|
|
38
|
-
if (
|
|
39
|
-
const res = impressionsCache.track(impressionsToStore
|
|
39
|
+
if (impressionsToStore.length > 0) {
|
|
40
|
+
const res = impressionsCache.track(impressionsToStore);
|
|
40
41
|
|
|
41
42
|
// If we're on an async storage, handle error and log it.
|
|
42
43
|
if (thenable(res)) {
|
|
43
44
|
res.then(() => {
|
|
44
|
-
log.info(IMPRESSIONS_TRACKER_SUCCESS, [
|
|
45
|
+
log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]);
|
|
45
46
|
}).catch(err => {
|
|
46
|
-
log.error(ERROR_IMPRESSIONS_TRACKER, [
|
|
47
|
+
log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]);
|
|
47
48
|
});
|
|
48
49
|
} else {
|
|
49
50
|
// Record when impressionsCache is sync only (standalone mode)
|
|
50
51
|
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
51
52
|
if (telemetryCache) {
|
|
52
|
-
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(QUEUED,
|
|
53
|
-
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(DEDUPED,
|
|
53
|
+
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(QUEUED, impressionsToStore.length);
|
|
54
|
+
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(DEDUPED, deduped);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
// @TODO next block might be handled by the integration manager. In that case, the metadata object doesn't need to be passed in the constructor
|
|
59
60
|
if (impressionListener || integrationsManager) {
|
|
60
|
-
for (let i = 0; i <
|
|
61
|
+
for (let i = 0; i < impressionsToListenerCount; i++) {
|
|
61
62
|
const impressionData: SplitIO.ImpressionData = {
|
|
62
|
-
// copy of impression, to avoid unexpected
|
|
63
|
-
impression: objectAssign({},
|
|
63
|
+
// copy of impression, to avoid unexpected behavior if modified by integrations or impressionListener
|
|
64
|
+
impression: objectAssign({}, impressionsToListener[i]),
|
|
64
65
|
attributes,
|
|
65
66
|
ip,
|
|
66
67
|
hostname,
|
|
@@ -6,16 +6,23 @@ import { IStrategy } from '../types';
|
|
|
6
6
|
* Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
7
7
|
*
|
|
8
8
|
* @param impressionsObserver - impression observer. Previous time (pt property) is included in impression instances
|
|
9
|
-
* @returns
|
|
9
|
+
* @returns IStrategyResult
|
|
10
10
|
*/
|
|
11
11
|
export function strategyDebugFactory(
|
|
12
12
|
impressionsObserver: IImpressionObserver
|
|
13
13
|
): IStrategy {
|
|
14
14
|
|
|
15
15
|
return {
|
|
16
|
-
process(
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
process(impressions: SplitIO.ImpressionDTO[]) {
|
|
17
|
+
impressions.forEach((impression) => {
|
|
18
|
+
// Adds previous time if it is enabled
|
|
19
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
impressionsToStore: impressions,
|
|
23
|
+
impressionsToListener: impressions,
|
|
24
|
+
deduped: 0
|
|
25
|
+
};
|
|
19
26
|
}
|
|
20
27
|
};
|
|
21
28
|
}
|
|
@@ -5,24 +5,30 @@ import { IStrategy, IUniqueKeysTracker } from '../types';
|
|
|
5
5
|
/**
|
|
6
6
|
* None strategy for impressions tracker.
|
|
7
7
|
*
|
|
8
|
-
* @param
|
|
8
|
+
* @param impressionsCounter - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
9
9
|
* @param uniqueKeysTracker - unique keys tracker in charge of tracking the unique keys per split.
|
|
10
|
-
* @returns
|
|
10
|
+
* @returns IStrategyResult
|
|
11
11
|
*/
|
|
12
12
|
export function strategyNoneFactory(
|
|
13
|
-
|
|
13
|
+
impressionsCounter: IImpressionCountsCacheBase,
|
|
14
14
|
uniqueKeysTracker: IUniqueKeysTracker
|
|
15
15
|
): IStrategy {
|
|
16
16
|
|
|
17
17
|
return {
|
|
18
|
-
process(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
process(impressions: SplitIO.ImpressionDTO[]) {
|
|
19
|
+
impressions.forEach((impression) => {
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
// Increments impression counter per featureName
|
|
22
|
+
impressionsCounter.track(impression.feature, now, 1);
|
|
23
|
+
// Keep track by unique key
|
|
24
|
+
uniqueKeysTracker.track(impression.keyName, impression.feature);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
impressionsToStore: [],
|
|
29
|
+
impressionsToListener: impressions,
|
|
30
|
+
deduped: 0
|
|
31
|
+
};
|
|
26
32
|
}
|
|
27
33
|
};
|
|
28
34
|
}
|
|
@@ -8,25 +8,35 @@ import { IStrategy } from '../types';
|
|
|
8
8
|
* Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
9
9
|
*
|
|
10
10
|
* @param impressionsObserver - impression observer. previous time (pt property) is included in impression instances
|
|
11
|
-
* @param
|
|
12
|
-
* @returns
|
|
11
|
+
* @param impressionsCounter - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
12
|
+
* @returns IStrategyResult
|
|
13
13
|
*/
|
|
14
14
|
export function strategyOptimizedFactory(
|
|
15
15
|
impressionsObserver: IImpressionObserver,
|
|
16
|
-
|
|
16
|
+
impressionsCounter: IImpressionCountsCacheBase,
|
|
17
17
|
): IStrategy {
|
|
18
18
|
|
|
19
19
|
return {
|
|
20
|
-
process(
|
|
21
|
-
|
|
20
|
+
process(impressions: SplitIO.ImpressionDTO[]) {
|
|
21
|
+
const impressionsToStore: SplitIO.ImpressionDTO[] = [];
|
|
22
|
+
impressions.forEach((impression) => {
|
|
23
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
const now = Date.now();
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
// Increments impression counter per featureName
|
|
28
|
+
if (impression.pt) impressionsCounter.track(impression.feature, now, 1);
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// Checks if the impression should be added in queue to be sent
|
|
31
|
+
if (!impression.pt || impression.pt < truncateTimeFrame(now)) {
|
|
32
|
+
impressionsToStore.push(impression);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
impressionsToStore: impressionsToStore,
|
|
37
|
+
impressionsToListener: impressions,
|
|
38
|
+
deduped: impressions.length - impressionsToStore.length
|
|
39
|
+
};
|
|
30
40
|
}
|
|
31
41
|
};
|
|
32
42
|
}
|
package/src/trackers/types.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface IImpressionsHandler {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface IImpressionsTracker {
|
|
21
|
-
track(impressions:
|
|
21
|
+
track(impressions: SplitIO.ImpressionDTO[], attributes?: SplitIO.Attributes): void
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/** Telemetry tracker */
|
|
@@ -70,6 +70,12 @@ export interface IUniqueKeysTracker {
|
|
|
70
70
|
track(key: string, featureName: string): void;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
export interface IStrategyResult {
|
|
74
|
+
impressionsToStore: SplitIO.ImpressionDTO[],
|
|
75
|
+
impressionsToListener: SplitIO.ImpressionDTO[],
|
|
76
|
+
deduped: number
|
|
77
|
+
}
|
|
78
|
+
|
|
73
79
|
export interface IStrategy {
|
|
74
|
-
process(
|
|
80
|
+
process(impressions: SplitIO.ImpressionDTO[]): IStrategyResult
|
|
75
81
|
}
|
package/src/utils/lang/index.ts
CHANGED
|
@@ -120,7 +120,7 @@ export function isBoolean(val: any): boolean {
|
|
|
120
120
|
* Unlike `Number.isFinite`, it also tests Number object instances.
|
|
121
121
|
* Unlike global `isFinite`, it returns false if the value is not a number or Number object instance.
|
|
122
122
|
*/
|
|
123
|
-
export function isFiniteNumber(val: any):
|
|
123
|
+
export function isFiniteNumber(val: any): val is number {
|
|
124
124
|
if (val instanceof Number) val = val.valueOf();
|
|
125
125
|
return typeof val === 'number' ?
|
|
126
126
|
Number.isFinite ? Number.isFinite(val) : isFinite(val) :
|
|
@@ -159,7 +159,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
159
159
|
if (withDefaults.mode === LOCALHOST_MODE && maybeKey === undefined) {
|
|
160
160
|
withDefaults.core.key = 'localhost_key';
|
|
161
161
|
} else {
|
|
162
|
-
// Keeping same
|
|
162
|
+
// Keeping same behavior than JS SDK: if settings key or TT are invalid,
|
|
163
163
|
// `false` value is used as bound key/TT of the default client, which leads to some issues.
|
|
164
164
|
// @ts-ignore, @TODO handle invalid keys as a non-recoverable error?
|
|
165
165
|
withDefaults.core.key = validateKey(log, maybeKey, LOG_PREFIX_CLIENT_INSTANTIATION);
|
|
@@ -8,7 +8,7 @@ import { IStorageFactoryParams, IStorageSync } from '../../../storages/types';
|
|
|
8
8
|
|
|
9
9
|
export function __InLocalStorageMockFactory(params: IStorageFactoryParams): IStorageSync {
|
|
10
10
|
const result = InMemoryStorageCSFactory(params);
|
|
11
|
-
result.
|
|
11
|
+
result.validateCache = () => true; // to emit SDK_READY_FROM_CACHE
|
|
12
12
|
return result;
|
|
13
13
|
}
|
|
14
14
|
__InLocalStorageMockFactory.type = STORAGE_MEMORY;
|
package/types/index.d.ts
CHANGED
package/types/splitio.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Type definitions for Split Software SDKs
|
|
2
|
-
// Project:
|
|
2
|
+
// Project: https://www.split.io/
|
|
3
3
|
|
|
4
4
|
import { RedisOptions } from 'ioredis';
|
|
5
5
|
import { RequestOptions } from 'http';
|
|
@@ -862,10 +862,6 @@ declare namespace SplitIO {
|
|
|
862
862
|
* The default treatment of the feature flag.
|
|
863
863
|
*/
|
|
864
864
|
defaultTreatment: string;
|
|
865
|
-
/**
|
|
866
|
-
* Whether the feature flag has impressions tracking enabled or not.
|
|
867
|
-
*/
|
|
868
|
-
trackImpressions: boolean;
|
|
869
865
|
};
|
|
870
866
|
/**
|
|
871
867
|
* A promise that resolves to a feature flag view or null if the feature flag is not found.
|
|
@@ -910,6 +906,18 @@ declare namespace SplitIO {
|
|
|
910
906
|
* @defaultValue `'SPLITIO'`
|
|
911
907
|
*/
|
|
912
908
|
prefix?: string;
|
|
909
|
+
/**
|
|
910
|
+
* Number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
|
|
911
|
+
*
|
|
912
|
+
* @defaultValue `10`
|
|
913
|
+
*/
|
|
914
|
+
expirationDays?: number;
|
|
915
|
+
/**
|
|
916
|
+
* Optional settings to clear the cache. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
|
|
917
|
+
*
|
|
918
|
+
* @defaultValue `false`
|
|
919
|
+
*/
|
|
920
|
+
clearOnInit?: boolean;
|
|
913
921
|
}
|
|
914
922
|
/**
|
|
915
923
|
* Storage for asynchronous (consumer) SDK.
|
|
@@ -1233,11 +1241,23 @@ declare namespace SplitIO {
|
|
|
1233
1241
|
*/
|
|
1234
1242
|
type?: BrowserStorage;
|
|
1235
1243
|
/**
|
|
1236
|
-
* Optional prefix to prevent any kind of data collision between SDK versions.
|
|
1244
|
+
* Optional prefix to prevent any kind of data collision between SDK versions when using 'LOCALSTORAGE'.
|
|
1237
1245
|
*
|
|
1238
1246
|
* @defaultValue `'SPLITIO'`
|
|
1239
1247
|
*/
|
|
1240
1248
|
prefix?: string;
|
|
1249
|
+
/**
|
|
1250
|
+
* Optional settings for the 'LOCALSTORAGE' storage type. It specifies the number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
|
|
1251
|
+
*
|
|
1252
|
+
* @defaultValue `10`
|
|
1253
|
+
*/
|
|
1254
|
+
expirationDays?: number;
|
|
1255
|
+
/**
|
|
1256
|
+
* Optional settings for the 'LOCALSTORAGE' storage type. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
|
|
1257
|
+
*
|
|
1258
|
+
* @defaultValue `false`
|
|
1259
|
+
*/
|
|
1260
|
+
clearOnInit?: boolean;
|
|
1241
1261
|
};
|
|
1242
1262
|
}
|
|
1243
1263
|
/**
|