@splitsoftware/splitio-commons 1.17.1-rc.2 → 1.17.1-rc.3
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/readiness/readinessManager.js +7 -5
- package/cjs/sdkClient/sdkClientMethodCS.js +7 -4
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +7 -4
- package/cjs/sdkFactory/index.js +30 -9
- package/cjs/storages/dataLoader.js +10 -11
- package/cjs/storages/inLocalStorage/index.js +5 -3
- package/cjs/storages/inRedis/RedisAdapter.js +1 -1
- package/cjs/storages/pluggable/index.js +37 -32
- package/cjs/trackers/eventTracker.js +11 -9
- package/cjs/trackers/impressionsTracker.js +15 -13
- package/cjs/trackers/uniqueKeysTracker.js +5 -3
- package/esm/readiness/readinessManager.js +7 -5
- package/esm/sdkClient/sdkClientMethodCS.js +7 -4
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +7 -4
- package/esm/sdkFactory/index.js +30 -9
- package/esm/storages/dataLoader.js +10 -11
- package/esm/storages/inLocalStorage/index.js +5 -3
- package/esm/storages/inRedis/RedisAdapter.js +1 -1
- package/esm/storages/pluggable/index.js +37 -32
- package/esm/trackers/eventTracker.js +11 -9
- package/esm/trackers/impressionsTracker.js +15 -13
- package/esm/trackers/uniqueKeysTracker.js +5 -3
- package/package.json +1 -1
- package/src/readiness/readinessManager.ts +9 -7
- package/src/readiness/types.ts +1 -0
- package/src/sdkClient/sdkClientMethodCS.ts +5 -2
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +5 -2
- package/src/sdkFactory/index.ts +32 -10
- package/src/sdkFactory/types.ts +3 -0
- package/src/storages/dataLoader.ts +12 -13
- package/src/storages/inLocalStorage/index.ts +6 -4
- package/src/storages/inRedis/RedisAdapter.ts +1 -1
- package/src/storages/pluggable/index.ts +38 -33
- package/src/storages/types.ts +1 -0
- package/src/trackers/eventTracker.ts +10 -7
- package/src/trackers/impressionsTracker.ts +12 -9
- package/src/trackers/types.ts +1 -0
- package/src/trackers/uniqueKeysTracker.ts +6 -4
- package/types/readiness/types.d.ts +1 -0
- package/types/sdkFactory/types.d.ts +2 -0
- package/types/storages/dataLoader.d.ts +2 -2
- package/types/storages/types.d.ts +1 -0
- package/types/trackers/eventTracker.d.ts +1 -1
- package/types/trackers/impressionsTracker.d.ts +1 -1
- package/types/trackers/types.d.ts +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IPluggableStorageWrapper,
|
|
1
|
+
import { IPluggableStorageWrapper, IStorageAsyncFactory, IStorageFactoryParams, ITelemetryCacheAsync } from '../types';
|
|
2
2
|
|
|
3
3
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
4
4
|
import { SplitsCachePluggable } from './SplitsCachePluggable';
|
|
@@ -62,11 +62,12 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
62
62
|
|
|
63
63
|
const prefix = validatePrefix(options.prefix);
|
|
64
64
|
|
|
65
|
-
function PluggableStorageFactory(params: IStorageFactoryParams)
|
|
65
|
+
function PluggableStorageFactory(params: IStorageFactoryParams) {
|
|
66
66
|
const { onReadyCb, settings, settings: { log, mode, sync: { impressionsMode }, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
|
|
67
67
|
const metadata = metadataBuilder(settings);
|
|
68
68
|
const keys = new KeyBuilderSS(prefix, metadata);
|
|
69
69
|
const wrapper = wrapperAdapter(log, options.wrapper);
|
|
70
|
+
let connectPromise: Promise<void>;
|
|
70
71
|
|
|
71
72
|
const isSyncronizer = mode === undefined; // If mode is not defined, the synchronizer is running
|
|
72
73
|
const isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
|
|
@@ -89,35 +90,6 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
89
90
|
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
|
|
90
91
|
undefined;
|
|
91
92
|
|
|
92
|
-
// Connects to wrapper and emits SDK_READY event on main client
|
|
93
|
-
const connectPromise = wrapper.connect().then(() => {
|
|
94
|
-
if (isSyncronizer) {
|
|
95
|
-
// In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
|
|
96
|
-
return wrapper.get(keys.buildHashKey()).then((hash) => {
|
|
97
|
-
const currentHash = getStorageHash(settings);
|
|
98
|
-
if (hash !== currentHash) {
|
|
99
|
-
log.info(LOG_PREFIX + 'Storage HASH has changed (SDK key, flags filter criteria or flags spec version was modified). Clearing cache');
|
|
100
|
-
return wrapper.getKeysByPrefix(`${keys.prefix}.`).then(storageKeys => {
|
|
101
|
-
return Promise.all(storageKeys.map(storageKey => wrapper.del(storageKey)));
|
|
102
|
-
}).then(() => wrapper.set(keys.buildHashKey(), currentHash));
|
|
103
|
-
}
|
|
104
|
-
}).then(() => {
|
|
105
|
-
onReadyCb();
|
|
106
|
-
});
|
|
107
|
-
} else {
|
|
108
|
-
// Start periodic flush of async storages if not running synchronizer (producer mode)
|
|
109
|
-
if (impressionCountsCache && (impressionCountsCache as ImpressionCountsCachePluggable).start) (impressionCountsCache as ImpressionCountsCachePluggable).start();
|
|
110
|
-
if (uniqueKeysCache && (uniqueKeysCache as UniqueKeysCachePluggable).start) (uniqueKeysCache as UniqueKeysCachePluggable).start();
|
|
111
|
-
if (telemetry && (telemetry as ITelemetryCacheAsync).recordConfig) (telemetry as ITelemetryCacheAsync).recordConfig();
|
|
112
|
-
|
|
113
|
-
onReadyCb();
|
|
114
|
-
}
|
|
115
|
-
}).catch((e) => {
|
|
116
|
-
e = e || new Error('Error connecting wrapper');
|
|
117
|
-
onReadyCb(e);
|
|
118
|
-
return e; // Propagate error for shared clients
|
|
119
|
-
});
|
|
120
|
-
|
|
121
93
|
return {
|
|
122
94
|
splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
123
95
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
@@ -127,6 +99,39 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
127
99
|
telemetry,
|
|
128
100
|
uniqueKeys: uniqueKeysCache,
|
|
129
101
|
|
|
102
|
+
init() {
|
|
103
|
+
if (connectPromise) return connectPromise;
|
|
104
|
+
|
|
105
|
+
// Connects to wrapper and emits SDK_READY event on main client
|
|
106
|
+
return connectPromise = wrapper.connect().then(() => {
|
|
107
|
+
if (isSyncronizer) {
|
|
108
|
+
// In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
|
|
109
|
+
return wrapper.get(keys.buildHashKey()).then((hash) => {
|
|
110
|
+
const currentHash = getStorageHash(settings);
|
|
111
|
+
if (hash !== currentHash) {
|
|
112
|
+
log.info(LOG_PREFIX + 'Storage HASH has changed (SDK key, flags filter criteria or flags spec version was modified). Clearing cache');
|
|
113
|
+
return wrapper.getKeysByPrefix(`${keys.prefix}.`).then(storageKeys => {
|
|
114
|
+
return Promise.all(storageKeys.map(storageKey => wrapper.del(storageKey)));
|
|
115
|
+
}).then(() => wrapper.set(keys.buildHashKey(), currentHash));
|
|
116
|
+
}
|
|
117
|
+
}).then(() => {
|
|
118
|
+
onReadyCb();
|
|
119
|
+
});
|
|
120
|
+
} else {
|
|
121
|
+
// Start periodic flush of async storages if not running synchronizer (producer mode)
|
|
122
|
+
if (impressionCountsCache && (impressionCountsCache as ImpressionCountsCachePluggable).start) (impressionCountsCache as ImpressionCountsCachePluggable).start();
|
|
123
|
+
if (uniqueKeysCache && (uniqueKeysCache as UniqueKeysCachePluggable).start) (uniqueKeysCache as UniqueKeysCachePluggable).start();
|
|
124
|
+
if (telemetry && (telemetry as ITelemetryCacheAsync).recordConfig) (telemetry as ITelemetryCacheAsync).recordConfig();
|
|
125
|
+
|
|
126
|
+
onReadyCb();
|
|
127
|
+
}
|
|
128
|
+
}).catch((e) => {
|
|
129
|
+
e = e || new Error('Error connecting wrapper');
|
|
130
|
+
onReadyCb(e);
|
|
131
|
+
return e; // Propagate error for shared clients
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
|
|
130
135
|
// Stop periodic flush and disconnect the underlying storage
|
|
131
136
|
destroy() {
|
|
132
137
|
return Promise.all(isSyncronizer ? [] : [
|
|
@@ -136,8 +141,8 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
136
141
|
},
|
|
137
142
|
|
|
138
143
|
// emits SDK_READY event on shared clients and returns a reference to the storage
|
|
139
|
-
shared(_, onReadyCb) {
|
|
140
|
-
|
|
144
|
+
shared(_: string, onReadyCb: (error?: any) => void) {
|
|
145
|
+
this.init().then(onReadyCb);
|
|
141
146
|
|
|
142
147
|
return {
|
|
143
148
|
...this,
|
package/src/storages/types.ts
CHANGED
|
@@ -462,6 +462,7 @@ export interface IStorageBase<
|
|
|
462
462
|
events: TEventsCache,
|
|
463
463
|
telemetry?: TTelemetryCache,
|
|
464
464
|
uniqueKeys?: TUniqueKeysCache,
|
|
465
|
+
init?: () => void | Promise<void>,
|
|
465
466
|
destroy(): void | Promise<void>,
|
|
466
467
|
shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this
|
|
467
468
|
}
|
|
@@ -16,6 +16,7 @@ import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
|
16
16
|
export function eventTrackerFactory(
|
|
17
17
|
settings: ISettings,
|
|
18
18
|
eventsCache: IEventsCacheBase,
|
|
19
|
+
whenInit: (cb: () => void) => void,
|
|
19
20
|
integrationsManager?: IEventsHandler,
|
|
20
21
|
telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync
|
|
21
22
|
): IEventTracker {
|
|
@@ -32,13 +33,15 @@ export function eventTrackerFactory(
|
|
|
32
33
|
log.info(EVENTS_TRACKER_SUCCESS, [msg]);
|
|
33
34
|
if (integrationsManager) {
|
|
34
35
|
// Wrap in a timeout because we don't want it to be blocking.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
whenInit(() => {
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
// copy of event, to avoid unexpected behaviour if modified by integrations
|
|
39
|
+
const eventDataCopy = objectAssign({}, eventData);
|
|
40
|
+
if (properties) eventDataCopy.properties = objectAssign({}, properties);
|
|
41
|
+
// integrationsManager does not throw errors (they are internally handled by each integration module)
|
|
42
|
+
integrationsManager.handleEvent(eventDataCopy);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
42
45
|
}
|
|
43
46
|
} else {
|
|
44
47
|
log.error(ERROR_EVENTS_TRACKER, [msg]);
|
|
@@ -19,6 +19,7 @@ export function impressionsTrackerFactory(
|
|
|
19
19
|
settings: ISettings,
|
|
20
20
|
impressionsCache: IImpressionsCacheBase,
|
|
21
21
|
strategy: IStrategy,
|
|
22
|
+
whenInit: (cb: () => void) => void,
|
|
22
23
|
integrationsManager?: IImpressionsHandler,
|
|
23
24
|
telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync,
|
|
24
25
|
): IImpressionsTracker {
|
|
@@ -67,16 +68,18 @@ export function impressionsTrackerFactory(
|
|
|
67
68
|
};
|
|
68
69
|
|
|
69
70
|
// Wrap in a timeout because we don't want it to be blocking.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
whenInit(() => {
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
// integrationsManager.handleImpression does not throw errors
|
|
74
|
+
if (integrationsManager) integrationsManager.handleImpression(impressionData);
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
try { // @ts-ignore. An exception on the listeners should not break the SDK.
|
|
77
|
+
if (impressionListener) impressionListener.logImpression(impressionData);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
log.error(ERROR_IMPRESSIONS_LISTENER, [err]);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
}
|
package/src/trackers/types.ts
CHANGED
|
@@ -25,10 +25,6 @@ export function uniqueKeysTrackerFactory(
|
|
|
25
25
|
): IUniqueKeysTracker {
|
|
26
26
|
let intervalId: any;
|
|
27
27
|
|
|
28
|
-
if (filterAdapter.refreshRate) {
|
|
29
|
-
intervalId = setInterval(filterAdapter.clear, filterAdapter.refreshRate);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
28
|
return {
|
|
33
29
|
|
|
34
30
|
track(key: string, featureName: string): void {
|
|
@@ -39,6 +35,12 @@ export function uniqueKeysTrackerFactory(
|
|
|
39
35
|
uniqueKeysCache.track(key, featureName);
|
|
40
36
|
},
|
|
41
37
|
|
|
38
|
+
start(): void {
|
|
39
|
+
if (filterAdapter.refreshRate) {
|
|
40
|
+
intervalId = setInterval(filterAdapter.clear, filterAdapter.refreshRate);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
42
44
|
stop(): void {
|
|
43
45
|
clearInterval(intervalId);
|
|
44
46
|
}
|
|
@@ -48,6 +48,7 @@ export interface ISdkFactoryContext {
|
|
|
48
48
|
splitApi?: ISplitApi;
|
|
49
49
|
syncManager?: ISyncManager;
|
|
50
50
|
clients: Record<string, IBasicClient>;
|
|
51
|
+
whenInit(cb: () => void): void;
|
|
51
52
|
}
|
|
52
53
|
export interface ISdkFactoryContextSync extends ISdkFactoryContext {
|
|
53
54
|
storage: IStorageSync;
|
|
@@ -63,6 +64,7 @@ export interface ISdkFactoryContextAsync extends ISdkFactoryContext {
|
|
|
63
64
|
* Object parameter with the modules required to create an SDK factory instance
|
|
64
65
|
*/
|
|
65
66
|
export interface ISdkFactoryParams {
|
|
67
|
+
isPure?: boolean;
|
|
66
68
|
settings: ISettings;
|
|
67
69
|
platform: IPlatform;
|
|
68
70
|
storageFactory: (params: IStorageFactoryParams) => IStorageSync | IStorageAsync;
|
|
@@ -17,5 +17,5 @@ export declare function loadData(preloadedData: SplitIO.PreloadedData, storage:
|
|
|
17
17
|
splits?: ISplitsCacheSync;
|
|
18
18
|
segments: ISegmentsCacheSync;
|
|
19
19
|
largeSegments?: ISegmentsCacheSync;
|
|
20
|
-
},
|
|
21
|
-
export declare function getSnapshot(storage: IStorageSync, userKeys?:
|
|
20
|
+
}, matchingKey?: string): void;
|
|
21
|
+
export declare function getSnapshot(storage: IStorageSync, userKeys?: SplitIO.SplitKey[]): SplitIO.PreloadedData;
|
|
@@ -382,6 +382,7 @@ export interface IStorageBase<TSplitsCache extends ISplitsCacheBase, TSegmentsCa
|
|
|
382
382
|
events: TEventsCache;
|
|
383
383
|
telemetry?: TTelemetryCache;
|
|
384
384
|
uniqueKeys?: TUniqueKeysCache;
|
|
385
|
+
init?: () => void | Promise<void>;
|
|
385
386
|
destroy(): void | Promise<void>;
|
|
386
387
|
shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this;
|
|
387
388
|
}
|
|
@@ -7,4 +7,4 @@ import { ISettings } from '../types';
|
|
|
7
7
|
* @param eventsCache cache to save events
|
|
8
8
|
* @param integrationsManager optional event handler used for integrations
|
|
9
9
|
*/
|
|
10
|
-
export declare function eventTrackerFactory(settings: ISettings, eventsCache: IEventsCacheBase, integrationsManager?: IEventsHandler, telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync): IEventTracker;
|
|
10
|
+
export declare function eventTrackerFactory(settings: ISettings, eventsCache: IEventsCacheBase, whenInit: (cb: () => void) => void, integrationsManager?: IEventsHandler, telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync): IEventTracker;
|
|
@@ -10,4 +10,4 @@ import { ISettings } from '../types';
|
|
|
10
10
|
* @param integrationsManager optional integrations manager
|
|
11
11
|
* @param strategy strategy for impressions tracking.
|
|
12
12
|
*/
|
|
13
|
-
export declare function impressionsTrackerFactory(settings: ISettings, impressionsCache: IImpressionsCacheBase, strategy: IStrategy, integrationsManager?: IImpressionsHandler, telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync): IImpressionsTracker;
|
|
13
|
+
export declare function impressionsTrackerFactory(settings: ISettings, impressionsCache: IImpressionsCacheBase, strategy: IStrategy, whenInit: (cb: () => void) => void, integrationsManager?: IImpressionsHandler, telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync): IImpressionsTracker;
|