@splitsoftware/splitio-commons 1.17.1-rc.3 → 1.17.1-rc.4
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 +4 -3
- package/cjs/readiness/readinessManager.js +13 -4
- package/cjs/sdkClient/sdkClientMethodCS.js +3 -7
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +3 -7
- package/cjs/sdkFactory/index.js +8 -13
- package/cjs/storages/{AbstractSegmentsCacheSync.js → AbstractMySegmentsCacheSync.js} +15 -17
- package/cjs/storages/AbstractSplitsCacheAsync.js +7 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +7 -0
- package/cjs/storages/dataLoader.js +32 -64
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +5 -5
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +9 -1
- package/cjs/storages/inLocalStorage/index.js +1 -6
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -17
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +5 -5
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +13 -27
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -1
- package/cjs/storages/inRedis/RedisAdapter.js +1 -1
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +13 -19
- package/cjs/storages/pluggable/SegmentsCachePluggable.js +11 -32
- package/cjs/storages/pluggable/index.js +32 -37
- package/cjs/sync/offline/syncManagerOffline.js +18 -11
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +7 -2
- package/cjs/sync/polling/pollingManagerSS.js +3 -3
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +12 -28
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +10 -1
- package/cjs/sync/syncManagerOnline.js +20 -21
- package/cjs/trackers/eventTracker.js +1 -1
- package/cjs/trackers/impressionsTracker.js +1 -1
- package/cjs/utils/settingsValidation/storage/storageCS.js +12 -1
- package/esm/readiness/readinessManager.js +13 -4
- package/esm/sdkClient/sdkClientMethodCS.js +3 -7
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +3 -7
- package/esm/sdkFactory/index.js +9 -14
- package/esm/storages/{AbstractSegmentsCacheSync.js → AbstractMySegmentsCacheSync.js} +14 -16
- package/esm/storages/AbstractSplitsCacheAsync.js +7 -0
- package/esm/storages/AbstractSplitsCacheSync.js +7 -0
- package/esm/storages/dataLoader.js +30 -61
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +5 -5
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +9 -1
- package/esm/storages/inLocalStorage/index.js +2 -7
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -17
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +5 -5
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +13 -27
- package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -1
- package/esm/storages/inRedis/RedisAdapter.js +1 -1
- package/esm/storages/inRedis/SegmentsCacheInRedis.js +13 -19
- package/esm/storages/pluggable/SegmentsCachePluggable.js +11 -32
- package/esm/storages/pluggable/index.js +32 -37
- package/esm/sync/offline/syncManagerOffline.js +18 -11
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +8 -3
- package/esm/sync/polling/pollingManagerSS.js +3 -3
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +12 -28
- package/esm/sync/polling/updaters/splitChangesUpdater.js +11 -2
- package/esm/sync/syncManagerOnline.js +20 -21
- package/esm/trackers/eventTracker.js +1 -1
- package/esm/trackers/impressionsTracker.js +1 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +10 -0
- package/package.json +1 -1
- package/src/readiness/readinessManager.ts +11 -4
- package/src/readiness/types.ts +2 -0
- package/src/sdkClient/sdkClientMethodCS.ts +1 -6
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +1 -6
- package/src/sdkFactory/index.ts +9 -15
- package/src/sdkFactory/types.ts +1 -2
- package/src/storages/{AbstractSegmentsCacheSync.ts → AbstractMySegmentsCacheSync.ts} +13 -28
- package/src/storages/AbstractSplitsCacheAsync.ts +8 -0
- package/src/storages/AbstractSplitsCacheSync.ts +8 -0
- package/src/storages/dataLoader.ts +32 -62
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +5 -5
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +10 -1
- package/src/storages/inLocalStorage/index.ts +2 -8
- package/src/storages/inMemory/InMemoryStorageCS.ts +5 -20
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +5 -5
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +12 -26
- package/src/storages/inMemory/SplitsCacheInMemory.ts +0 -1
- package/src/storages/inRedis/RedisAdapter.ts +1 -1
- package/src/storages/inRedis/SegmentsCacheInRedis.ts +13 -22
- package/src/storages/pluggable/SegmentsCachePluggable.ts +11 -35
- package/src/storages/pluggable/index.ts +33 -38
- package/src/storages/types.ts +9 -11
- package/src/sync/offline/syncManagerOffline.ts +21 -13
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +7 -3
- package/src/sync/polling/pollingManagerSS.ts +2 -3
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +13 -29
- package/src/sync/polling/updaters/splitChangesUpdater.ts +11 -3
- package/src/sync/syncManagerOnline.ts +17 -17
- package/src/sync/types.ts +1 -1
- package/src/trackers/eventTracker.ts +1 -1
- package/src/trackers/impressionsTracker.ts +1 -1
- package/src/types.ts +8 -9
- package/src/utils/settingsValidation/storage/storageCS.ts +13 -0
- package/types/readiness/types.d.ts +2 -0
- package/types/sdkFactory/types.d.ts +1 -2
- package/types/storages/AbstractSplitsCacheAsync.d.ts +5 -0
- package/types/storages/AbstractSplitsCacheSync.d.ts +5 -0
- package/types/storages/dataLoader.d.ts +6 -17
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +5 -5
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +6 -0
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +5 -5
- package/types/storages/inMemory/SegmentsCacheInMemory.d.ts +5 -7
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +0 -1
- package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +6 -3
- package/types/storages/pluggable/SegmentsCachePluggable.d.ts +4 -16
- package/types/storages/types.d.ts +7 -11
- package/types/sync/types.d.ts +1 -1
- package/types/types.d.ts +8 -8
- package/types/utils/settingsValidation/storage/storageCS.d.ts +5 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IPluggableStorageWrapper, IStorageAsyncFactory, IStorageFactoryParams, ITelemetryCacheAsync } from '../types';
|
|
1
|
+
import { IPluggableStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams, ITelemetryCacheAsync } from '../types';
|
|
2
2
|
|
|
3
3
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
4
4
|
import { SplitsCachePluggable } from './SplitsCachePluggable';
|
|
@@ -62,12 +62,11 @@ 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): IStorageAsync {
|
|
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>;
|
|
71
70
|
|
|
72
71
|
const isSyncronizer = mode === undefined; // If mode is not defined, the synchronizer is running
|
|
73
72
|
const isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
|
|
@@ -90,6 +89,35 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
90
89
|
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
|
|
91
90
|
undefined;
|
|
92
91
|
|
|
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
|
+
|
|
93
121
|
return {
|
|
94
122
|
splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
95
123
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
@@ -99,39 +127,6 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
99
127
|
telemetry,
|
|
100
128
|
uniqueKeys: uniqueKeysCache,
|
|
101
129
|
|
|
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
|
-
|
|
135
130
|
// Stop periodic flush and disconnect the underlying storage
|
|
136
131
|
destroy() {
|
|
137
132
|
return Promise.all(isSyncronizer ? [] : [
|
|
@@ -141,8 +136,8 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
141
136
|
},
|
|
142
137
|
|
|
143
138
|
// emits SDK_READY event on shared clients and returns a reference to the storage
|
|
144
|
-
shared(_
|
|
145
|
-
|
|
139
|
+
shared(_, onReadyCb) {
|
|
140
|
+
connectPromise.then(onReadyCb);
|
|
146
141
|
|
|
147
142
|
return {
|
|
148
143
|
...this,
|
package/src/storages/types.ts
CHANGED
|
@@ -208,6 +208,8 @@ export interface ISplitsCacheBase {
|
|
|
208
208
|
// only for Client-Side. Returns true if the storage is not synchronized yet (getChangeNumber() === -1) or contains a FF using segments or large segments
|
|
209
209
|
usesSegments(): MaybeThenable<boolean>,
|
|
210
210
|
clear(): MaybeThenable<boolean | void>,
|
|
211
|
+
// should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
|
|
212
|
+
checkCache(): MaybeThenable<boolean>,
|
|
211
213
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>,
|
|
212
214
|
getNamesByFlagSets(flagSets: string[]): MaybeThenable<ISet<string>[]>
|
|
213
215
|
}
|
|
@@ -224,6 +226,7 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
|
|
|
224
226
|
trafficTypeExists(trafficType: string): boolean,
|
|
225
227
|
usesSegments(): boolean,
|
|
226
228
|
clear(): void,
|
|
229
|
+
checkCache(): boolean,
|
|
227
230
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
|
|
228
231
|
getNamesByFlagSets(flagSets: string[]): ISet<string>[]
|
|
229
232
|
}
|
|
@@ -240,6 +243,7 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
|
|
|
240
243
|
trafficTypeExists(trafficType: string): Promise<boolean>,
|
|
241
244
|
usesSegments(): Promise<boolean>,
|
|
242
245
|
clear(): Promise<boolean | void>,
|
|
246
|
+
checkCache(): Promise<boolean>,
|
|
243
247
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
|
|
244
248
|
getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>
|
|
245
249
|
}
|
|
@@ -247,38 +251,32 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
|
|
|
247
251
|
/** Segments cache */
|
|
248
252
|
|
|
249
253
|
export interface ISegmentsCacheBase {
|
|
250
|
-
addToSegment(name: string, segmentKeys: string[]): MaybeThenable<boolean | void> // different signature on Server and Client-Side
|
|
251
|
-
removeFromSegment(name: string, segmentKeys: string[]): MaybeThenable<boolean | void> // different signature on Server and Client-Side
|
|
252
254
|
isInSegment(name: string, key?: string): MaybeThenable<boolean> // different signature on Server and Client-Side
|
|
253
255
|
registerSegments(names: string[]): MaybeThenable<boolean | void> // only for Server-Side
|
|
254
256
|
getRegisteredSegments(): MaybeThenable<string[]> // only for Server-Side
|
|
255
|
-
setChangeNumber(name: string, changeNumber: number): MaybeThenable<boolean | void> // only for Server-Side
|
|
256
257
|
getChangeNumber(name: string): MaybeThenable<number> // only for Server-Side
|
|
258
|
+
update(name: string, addedKeys: string[], removedKeys: string[], changeNumber: number): MaybeThenable<boolean> // only for Server-Side
|
|
257
259
|
clear(): MaybeThenable<boolean | void>
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
// Same API for both variants: SegmentsCache and MySegmentsCache (client-side API)
|
|
261
263
|
export interface ISegmentsCacheSync extends ISegmentsCacheBase {
|
|
262
|
-
addToSegment(name: string, segmentKeys?: string[]): boolean
|
|
263
|
-
removeFromSegment(name: string, segmentKeys?: string[]): boolean
|
|
264
264
|
isInSegment(name: string, key?: string): boolean
|
|
265
265
|
registerSegments(names: string[]): boolean
|
|
266
266
|
getRegisteredSegments(): string[]
|
|
267
267
|
getKeysCount(): number // only used for telemetry
|
|
268
|
-
setChangeNumber(name: string, changeNumber: number): boolean | void
|
|
269
268
|
getChangeNumber(name?: string): number
|
|
269
|
+
update(name: string, addedKeys: string[], removedKeys: string[], changeNumber: number): boolean // only for Server-Side
|
|
270
270
|
resetSegments(segmentsData: MySegmentsData | IMySegmentsResponse): boolean // only for Sync Client-Side
|
|
271
271
|
clear(): void
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
export interface ISegmentsCacheAsync extends ISegmentsCacheBase {
|
|
275
|
-
addToSegment(name: string, segmentKeys: string[]): Promise<boolean | void>
|
|
276
|
-
removeFromSegment(name: string, segmentKeys: string[]): Promise<boolean | void>
|
|
277
275
|
isInSegment(name: string, key: string): Promise<boolean>
|
|
278
276
|
registerSegments(names: string[]): Promise<boolean | void>
|
|
279
277
|
getRegisteredSegments(): Promise<string[]>
|
|
280
|
-
setChangeNumber(name: string, changeNumber: number): Promise<boolean | void>
|
|
281
278
|
getChangeNumber(name: string): Promise<number>
|
|
279
|
+
update(name: string, addedKeys: string[], removedKeys: string[], changeNumber: number): Promise<boolean>
|
|
282
280
|
clear(): Promise<boolean | void>
|
|
283
281
|
}
|
|
284
282
|
|
|
@@ -462,7 +460,6 @@ export interface IStorageBase<
|
|
|
462
460
|
events: TEventsCache,
|
|
463
461
|
telemetry?: TTelemetryCache,
|
|
464
462
|
uniqueKeys?: TUniqueKeysCache,
|
|
465
|
-
init?: () => void | Promise<void>,
|
|
466
463
|
destroy(): void | Promise<void>,
|
|
467
464
|
shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this
|
|
468
465
|
}
|
|
@@ -492,6 +489,8 @@ export interface IStorageAsync extends IStorageBase<
|
|
|
492
489
|
|
|
493
490
|
/** StorageFactory */
|
|
494
491
|
|
|
492
|
+
export type DataLoader = (storage: IStorageSync, matchingKey: string) => void
|
|
493
|
+
|
|
495
494
|
export interface IStorageFactoryParams {
|
|
496
495
|
settings: ISettings,
|
|
497
496
|
/**
|
|
@@ -499,7 +498,6 @@ export interface IStorageFactoryParams {
|
|
|
499
498
|
* It is meant for emitting SDK_READY event in consumer mode, and waiting before using the storage in the synchronizer.
|
|
500
499
|
*/
|
|
501
500
|
onReadyCb: (error?: any) => void,
|
|
502
|
-
onReadyFromCacheCb: (error?: any) => void,
|
|
503
501
|
}
|
|
504
502
|
|
|
505
503
|
export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISyncManagerCS } from '../types';
|
|
2
2
|
import { fromObjectSyncTaskFactory } from './syncTasks/fromObjectSyncTask';
|
|
3
3
|
import { objectAssign } from '../../utils/lang/objectAssign';
|
|
4
4
|
import { ISplitsParser } from './splitsParser/types';
|
|
@@ -29,26 +29,34 @@ export function syncManagerOfflineFactory(
|
|
|
29
29
|
storage,
|
|
30
30
|
}: ISdkFactoryContextSync): ISyncManagerCS {
|
|
31
31
|
|
|
32
|
+
const mainSyncManager = fromObjectSyncTaskFactory(splitsParserFactory(), storage, readiness, settings);
|
|
33
|
+
const mainStart = mainSyncManager.start;
|
|
34
|
+
const sharedStarts: Array<() => void> = [];
|
|
35
|
+
|
|
32
36
|
return objectAssign(
|
|
33
|
-
|
|
37
|
+
mainSyncManager,
|
|
34
38
|
{
|
|
39
|
+
start() {
|
|
40
|
+
mainStart();
|
|
41
|
+
sharedStarts.forEach(cb => cb());
|
|
42
|
+
sharedStarts.length = 0;
|
|
43
|
+
},
|
|
35
44
|
// fake flush, that resolves immediately
|
|
36
45
|
flush,
|
|
37
46
|
|
|
38
47
|
// [Only used for client-side]
|
|
39
|
-
shared(matchingKey: string, readinessManager: IReadinessManager)
|
|
48
|
+
shared(matchingKey: string, readinessManager: IReadinessManager) {
|
|
49
|
+
// In LOCALHOST mode, shared clients are ready in the next event-loop cycle than created
|
|
50
|
+
// SDK_READY cannot be emitted directly because this will not update the readiness status
|
|
51
|
+
function emitSdkReady() {
|
|
52
|
+
readinessManager.segments.emit(SDK_SEGMENTS_ARRIVED); // SDK_SPLITS_ARRIVED emitted by main SyncManager
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (mainSyncManager.isRunning()) setTimeout(emitSdkReady);
|
|
56
|
+
else sharedStarts.push(emitSdkReady);
|
|
57
|
+
|
|
40
58
|
return {
|
|
41
|
-
start() {
|
|
42
|
-
// In LOCALHOST mode, shared clients are ready in the next event-loop cycle than created
|
|
43
|
-
// SDK_READY cannot be emitted directly because this will not update the readiness status
|
|
44
|
-
setTimeout(() => {
|
|
45
|
-
readinessManager.segments.emit(SDK_SEGMENTS_ARRIVED); // SDK_SPLITS_ARRIVED emitted by main SyncManager
|
|
46
|
-
}, 0);
|
|
47
|
-
},
|
|
48
59
|
stop() { },
|
|
49
|
-
isRunning() {
|
|
50
|
-
return true;
|
|
51
|
-
},
|
|
52
60
|
flush,
|
|
53
61
|
};
|
|
54
62
|
}
|
|
@@ -7,7 +7,7 @@ import { syncTaskFactory } from '../../syncTask';
|
|
|
7
7
|
import { ISyncTask } from '../../types';
|
|
8
8
|
import { ISettings } from '../../../types';
|
|
9
9
|
import { CONTROL } from '../../../utils/constants';
|
|
10
|
-
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
|
|
10
|
+
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
|
|
11
11
|
import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/constants';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -60,8 +60,12 @@ export function fromObjectUpdaterFactory(
|
|
|
60
60
|
|
|
61
61
|
if (startingUp) {
|
|
62
62
|
startingUp = false;
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
Promise.resolve(splitsCache.checkCache()).then(cacheReady => {
|
|
64
|
+
// Emits SDK_READY_FROM_CACHE
|
|
65
|
+
if (cacheReady) readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
|
|
66
|
+
// Emits SDK_READY
|
|
67
|
+
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
68
|
+
});
|
|
65
69
|
}
|
|
66
70
|
return true;
|
|
67
71
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask';
|
|
2
2
|
import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
|
|
3
3
|
import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types';
|
|
4
|
-
import { thenable } from '../../utils/promise/thenable';
|
|
5
4
|
import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
|
|
6
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
7
6
|
|
|
@@ -29,9 +28,9 @@ export function pollingManagerSSFactory(
|
|
|
29
28
|
log.debug(LOG_PREFIX_SYNC_POLLING + `Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`);
|
|
30
29
|
|
|
31
30
|
const startingUp = splitsSyncTask.start();
|
|
32
|
-
if (
|
|
31
|
+
if (startingUp) {
|
|
33
32
|
startingUp.then(() => {
|
|
34
|
-
segmentsSyncTask.start();
|
|
33
|
+
if (splitsSyncTask.isRunning()) segmentsSyncTask.start();
|
|
35
34
|
});
|
|
36
35
|
}
|
|
37
36
|
},
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { ISegmentChangesFetcher } from '../fetchers/types';
|
|
2
2
|
import { ISegmentsCacheBase } from '../../../storages/types';
|
|
3
3
|
import { IReadinessManager } from '../../../readiness/types';
|
|
4
|
-
import { MaybeThenable } from '../../../dtos/types';
|
|
5
|
-
import { findIndex } from '../../../utils/lang';
|
|
6
4
|
import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
|
|
7
5
|
import { ILogger } from '../../../logger/types';
|
|
8
6
|
import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants';
|
|
9
|
-
import { thenable } from '../../../utils/promise/thenable';
|
|
10
7
|
|
|
11
8
|
type ISegmentChangesUpdater = (fetchOnlyNew?: boolean, segmentName?: string, noCache?: boolean, till?: number) => Promise<boolean>
|
|
12
9
|
|
|
@@ -30,31 +27,22 @@ export function segmentChangesUpdaterFactory(
|
|
|
30
27
|
|
|
31
28
|
let readyOnAlreadyExistentState = true;
|
|
32
29
|
|
|
33
|
-
function updateSegment(segmentName: string, noCache?: boolean, till?: number, fetchOnlyNew?: boolean) {
|
|
30
|
+
function updateSegment(segmentName: string, noCache?: boolean, till?: number, fetchOnlyNew?: boolean): Promise<boolean> {
|
|
34
31
|
log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processing segment ${segmentName}`);
|
|
35
32
|
let sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
|
|
36
33
|
|
|
37
34
|
return sincePromise.then(since => {
|
|
38
35
|
// if fetchOnlyNew flag, avoid processing already fetched segments
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
results.push(segments.setChangeNumber(segmentName, x.till));
|
|
49
|
-
changeNumber = x.till;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
36
|
+
return fetchOnlyNew && since !== -1 ?
|
|
37
|
+
false :
|
|
38
|
+
segmentChangesFetcher(since, segmentName, noCache, till).then((changes) => {
|
|
39
|
+
return Promise.all(changes.map(x => {
|
|
40
|
+
log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
41
|
+
return segments.update(x.name, x.added, x.removed, x.till);
|
|
42
|
+
})).then((updates) => {
|
|
43
|
+
return updates.some(update => update);
|
|
44
|
+
});
|
|
53
45
|
});
|
|
54
|
-
// If at least one storage operation result is a promise, join all in a single promise.
|
|
55
|
-
if (results.some(result => thenable(result))) return Promise.all(results).then(() => changeNumber);
|
|
56
|
-
return changeNumber;
|
|
57
|
-
});
|
|
58
46
|
});
|
|
59
47
|
}
|
|
60
48
|
/**
|
|
@@ -75,16 +63,12 @@ export function segmentChangesUpdaterFactory(
|
|
|
75
63
|
let segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
|
|
76
64
|
|
|
77
65
|
return segmentsPromise.then(segmentNames => {
|
|
78
|
-
// Async fetchers
|
|
79
|
-
const updaters
|
|
80
|
-
|
|
81
|
-
for (let index = 0; index < segmentNames.length; index++) {
|
|
82
|
-
updaters.push(updateSegment(segmentNames[index], noCache, till, fetchOnlyNew));
|
|
83
|
-
}
|
|
66
|
+
// Async fetchers
|
|
67
|
+
const updaters = segmentNames.map(segmentName => updateSegment(segmentName, noCache, till, fetchOnlyNew));
|
|
84
68
|
|
|
85
69
|
return Promise.all(updaters).then(shouldUpdateFlags => {
|
|
86
70
|
// if at least one segment fetch succeeded, mark segments ready
|
|
87
|
-
if (
|
|
71
|
+
if (shouldUpdateFlags.some(update => update) || readyOnAlreadyExistentState) {
|
|
88
72
|
readyOnAlreadyExistentState = false;
|
|
89
73
|
if (readiness) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
90
74
|
}
|
|
@@ -4,7 +4,7 @@ import { ISplitChangesFetcher } from '../fetchers/types';
|
|
|
4
4
|
import { ISplit, ISplitChangesResponse, ISplitFiltersValidation } from '../../../dtos/types';
|
|
5
5
|
import { ISplitsEventEmitter } from '../../../readiness/types';
|
|
6
6
|
import { timeout } from '../../../utils/promise/timeout';
|
|
7
|
-
import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
|
|
7
|
+
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
|
|
8
8
|
import { ILogger } from '../../../logger/types';
|
|
9
9
|
import { SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
|
|
10
10
|
import { startsWith } from '../../../utils/lang';
|
|
@@ -153,8 +153,7 @@ export function splitChangesUpdaterFactory(
|
|
|
153
153
|
*/
|
|
154
154
|
function _splitChangesUpdater(since: number, retry = 0): Promise<boolean> {
|
|
155
155
|
log.debug(SYNC_SPLITS_FETCH, [since]);
|
|
156
|
-
|
|
157
|
-
return Promise.resolve(splitUpdateNotification ?
|
|
156
|
+
const fetcherPromise = Promise.resolve(splitUpdateNotification ?
|
|
158
157
|
{ splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
|
|
159
158
|
splitChangesFetcher(since, noCache, till, _promiseDecorator)
|
|
160
159
|
)
|
|
@@ -201,6 +200,15 @@ export function splitChangesUpdaterFactory(
|
|
|
201
200
|
}
|
|
202
201
|
return false;
|
|
203
202
|
});
|
|
203
|
+
|
|
204
|
+
// After triggering the requests, if we have cached splits information let's notify that to emit SDK_READY_FROM_CACHE.
|
|
205
|
+
// Wrapping in a promise since checkCache can be async.
|
|
206
|
+
if (splitsEventEmitter && startingUp) {
|
|
207
|
+
Promise.resolve(splits.checkCache()).then(isCacheReady => {
|
|
208
|
+
if (isCacheReady) splitsEventEmitter.emit(SDK_SPLITS_CACHE_LOADED);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return fetcherPromise;
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
let sincePromise = Promise.resolve(splits.getChangeNumber()); // `getChangeNumber` never rejects or throws error
|
|
@@ -143,27 +143,27 @@ export function syncManagerOnlineFactory(
|
|
|
143
143
|
|
|
144
144
|
const mySegmentsSyncTask = (pollingManager as IPollingManagerCS).add(matchingKey, readinessManager, storage);
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (pollingManager!.isRunning()) {
|
|
152
|
-
// if doing polling, we must start the periodic fetch of data
|
|
153
|
-
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
154
|
-
} else {
|
|
155
|
-
// if not polling, we must execute the sync task for the initial fetch
|
|
156
|
-
// of segments since `syncAll` was already executed when starting the main client
|
|
157
|
-
mySegmentsSyncTask.execute();
|
|
158
|
-
}
|
|
159
|
-
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
160
|
-
} else {
|
|
146
|
+
if (running) {
|
|
147
|
+
if (syncEnabled) {
|
|
148
|
+
if (pushManager) {
|
|
149
|
+
if (pollingManager!.isRunning()) {
|
|
150
|
+
// if doing polling, we must start the periodic fetch of data
|
|
161
151
|
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
152
|
+
} else {
|
|
153
|
+
// if not polling, we must execute the sync task for the initial fetch
|
|
154
|
+
// of segments since `syncAll` was already executed when starting the main client
|
|
155
|
+
mySegmentsSyncTask.execute();
|
|
162
156
|
}
|
|
157
|
+
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
163
158
|
} else {
|
|
164
|
-
if (
|
|
159
|
+
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
165
160
|
}
|
|
166
|
-
}
|
|
161
|
+
} else {
|
|
162
|
+
if (!readinessManager.isReady()) mySegmentsSyncTask.execute();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
167
|
stop() {
|
|
168
168
|
// check in case `client.destroy()` has been invoked more than once for the same client
|
|
169
169
|
const mySegmentsSyncTask = (pollingManager as IPollingManagerCS).get(matchingKey);
|
package/src/sync/types.ts
CHANGED
|
@@ -44,5 +44,5 @@ export interface ISyncManager extends ITask {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export interface ISyncManagerCS extends ISyncManager {
|
|
47
|
-
shared(matchingKey: string, readinessManager: IReadinessManager, storage: IStorageSync): ISyncManager | undefined
|
|
47
|
+
shared(matchingKey: string, readinessManager: IReadinessManager, storage: IStorageSync): Pick<ISyncManager, 'stop' | 'flush'> | undefined
|
|
48
48
|
}
|
|
@@ -32,8 +32,8 @@ export function eventTrackerFactory(
|
|
|
32
32
|
if (tracked) {
|
|
33
33
|
log.info(EVENTS_TRACKER_SUCCESS, [msg]);
|
|
34
34
|
if (integrationsManager) {
|
|
35
|
-
// Wrap in a timeout because we don't want it to be blocking.
|
|
36
35
|
whenInit(() => {
|
|
36
|
+
// Wrap in a timeout because we don't want it to be blocking.
|
|
37
37
|
setTimeout(() => {
|
|
38
38
|
// copy of event, to avoid unexpected behaviour if modified by integrations
|
|
39
39
|
const eventDataCopy = objectAssign({}, eventData);
|
|
@@ -67,8 +67,8 @@ export function impressionsTrackerFactory(
|
|
|
67
67
|
sdkLanguageVersion: version
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
// Wrap in a timeout because we don't want it to be blocking.
|
|
71
70
|
whenInit(() => {
|
|
71
|
+
// Wrap in a timeout because we don't want it to be blocking.
|
|
72
72
|
setTimeout(() => {
|
|
73
73
|
// integrationsManager.handleImpression does not throw errors
|
|
74
74
|
if (integrationsManager) integrationsManager.handleImpression(impressionData);
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISplitFiltersValidation } from './dtos/types';
|
|
2
2
|
import { IIntegration, IIntegrationFactoryParams } from './integrations/types';
|
|
3
3
|
import { ILogger } from './logger/types';
|
|
4
4
|
import { ISdkFactoryContext } from './sdkFactory/types';
|
|
@@ -98,7 +98,6 @@ export interface ISettings {
|
|
|
98
98
|
eventsFirstPushWindow: number
|
|
99
99
|
},
|
|
100
100
|
readonly storage: IStorageSyncFactory | IStorageAsyncFactory,
|
|
101
|
-
readonly preloadedData?: SplitIO.PreloadedData,
|
|
102
101
|
readonly integrations: Array<{
|
|
103
102
|
readonly type: string,
|
|
104
103
|
(params: IIntegrationFactoryParams): IIntegration | void
|
|
@@ -772,20 +771,21 @@ export namespace SplitIO {
|
|
|
772
771
|
* If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content.
|
|
773
772
|
* @TODO configurable expiration time policy?
|
|
774
773
|
*/
|
|
775
|
-
|
|
774
|
+
lastUpdated: number,
|
|
776
775
|
/**
|
|
777
776
|
* Change number of the preloaded data.
|
|
778
777
|
* If this value is older than the current changeNumber at the storage, the data is not used to update the storage content.
|
|
779
778
|
*/
|
|
780
779
|
since: number,
|
|
781
780
|
/**
|
|
782
|
-
*
|
|
783
|
-
* @TODO rename to flags
|
|
781
|
+
* Map of feature flags to their stringified definitions.
|
|
784
782
|
*/
|
|
785
|
-
splitsData:
|
|
783
|
+
splitsData: {
|
|
784
|
+
[splitName: string]: string
|
|
785
|
+
},
|
|
786
786
|
/**
|
|
787
787
|
* Optional map of user keys to their list of segments.
|
|
788
|
-
* @TODO
|
|
788
|
+
* @TODO remove when releasing first version
|
|
789
789
|
*/
|
|
790
790
|
mySegmentsData?: {
|
|
791
791
|
[key: string]: string[]
|
|
@@ -793,10 +793,9 @@ export namespace SplitIO {
|
|
|
793
793
|
/**
|
|
794
794
|
* Optional map of segments to their stringified definitions.
|
|
795
795
|
* This property is ignored if `mySegmentsData` was provided.
|
|
796
|
-
* @TODO rename to segments
|
|
797
796
|
*/
|
|
798
797
|
segmentsData?: {
|
|
799
|
-
[segmentName: string]: string
|
|
798
|
+
[segmentName: string]: string
|
|
800
799
|
},
|
|
801
800
|
}
|
|
802
801
|
/**
|
|
@@ -3,6 +3,14 @@ import { ISettings, SDKMode } from '../../../types';
|
|
|
3
3
|
import { ILogger } from '../../../logger/types';
|
|
4
4
|
import { ERROR_STORAGE_INVALID } from '../../../logger/constants';
|
|
5
5
|
import { LOCALHOST_MODE, STANDALONE_MODE, STORAGE_PLUGGABLE, STORAGE_LOCALSTORAGE, STORAGE_MEMORY } from '../../../utils/constants';
|
|
6
|
+
import { IStorageFactoryParams, IStorageSync } from '../../../storages/types';
|
|
7
|
+
|
|
8
|
+
export function __InLocalStorageMockFactory(params: IStorageFactoryParams): IStorageSync {
|
|
9
|
+
const result = InMemoryStorageCSFactory(params);
|
|
10
|
+
result.splits.checkCache = () => true; // to emit SDK_READY_FROM_CACHE
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
__InLocalStorageMockFactory.type = STORAGE_MEMORY;
|
|
6
14
|
|
|
7
15
|
/**
|
|
8
16
|
* This function validates `settings.storage` object
|
|
@@ -22,6 +30,11 @@ export function validateStorageCS(settings: { log: ILogger, storage?: any, mode:
|
|
|
22
30
|
log.error(ERROR_STORAGE_INVALID);
|
|
23
31
|
}
|
|
24
32
|
|
|
33
|
+
// In localhost mode with InLocalStorage, fallback to a mock InLocalStorage to emit SDK_READY_FROM_CACHE
|
|
34
|
+
if (mode === LOCALHOST_MODE && storage.type === STORAGE_LOCALSTORAGE) {
|
|
35
|
+
return __InLocalStorageMockFactory;
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
if ([LOCALHOST_MODE, STANDALONE_MODE].indexOf(mode) === -1) {
|
|
26
39
|
// Consumer modes require an async storage
|
|
27
40
|
if (storage.type !== STORAGE_PLUGGABLE) throw new Error('A PluggableStorage instance is required on consumer mode');
|
|
@@ -9,6 +9,8 @@ export interface ISplitsEventEmitter extends IEventEmitter {
|
|
|
9
9
|
once(event: ISplitsEvent, listener: (...args: any[]) => void): this;
|
|
10
10
|
splitsArrived: boolean;
|
|
11
11
|
splitsCacheLoaded: boolean;
|
|
12
|
+
initialized: boolean;
|
|
13
|
+
initCallbacks: (() => void)[];
|
|
12
14
|
}
|
|
13
15
|
/** Segments data emitter */
|
|
14
16
|
declare type SDK_SEGMENTS_ARRIVED = 'state::segments-arrived';
|
|
@@ -48,7 +48,6 @@ export interface ISdkFactoryContext {
|
|
|
48
48
|
splitApi?: ISplitApi;
|
|
49
49
|
syncManager?: ISyncManager;
|
|
50
50
|
clients: Record<string, IBasicClient>;
|
|
51
|
-
whenInit(cb: () => void): void;
|
|
52
51
|
}
|
|
53
52
|
export interface ISdkFactoryContextSync extends ISdkFactoryContext {
|
|
54
53
|
storage: IStorageSync;
|
|
@@ -64,7 +63,7 @@ export interface ISdkFactoryContextAsync extends ISdkFactoryContext {
|
|
|
64
63
|
* Object parameter with the modules required to create an SDK factory instance
|
|
65
64
|
*/
|
|
66
65
|
export interface ISdkFactoryParams {
|
|
67
|
-
|
|
66
|
+
lazyInit?: boolean;
|
|
68
67
|
settings: ISettings;
|
|
69
68
|
platform: IPlatform;
|
|
70
69
|
storageFactory: (params: IStorageFactoryParams) => IStorageSync | IStorageAsync;
|
|
@@ -19,6 +19,11 @@ export declare abstract class AbstractSplitsCacheAsync implements ISplitsCacheAs
|
|
|
19
19
|
abstract trafficTypeExists(trafficType: string): Promise<boolean>;
|
|
20
20
|
abstract clear(): Promise<boolean | void>;
|
|
21
21
|
usesSegments(): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Check if the splits information is already stored in cache.
|
|
24
|
+
* Noop, just keeping the interface. This is used by client-side implementations only.
|
|
25
|
+
*/
|
|
26
|
+
checkCache(): Promise<boolean>;
|
|
22
27
|
/**
|
|
23
28
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
24
29
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -19,6 +19,11 @@ export declare abstract class AbstractSplitsCacheSync implements ISplitsCacheSyn
|
|
|
19
19
|
abstract trafficTypeExists(trafficType: string): boolean;
|
|
20
20
|
abstract usesSegments(): boolean;
|
|
21
21
|
abstract clear(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Check if the splits information is already stored in cache. This data can be preloaded.
|
|
24
|
+
* It is used as condition to emit SDK_SPLITS_CACHE_LOADED, and then SDK_READY_FROM_CACHE.
|
|
25
|
+
*/
|
|
26
|
+
checkCache(): boolean;
|
|
22
27
|
/**
|
|
23
28
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
24
29
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -1,21 +1,10 @@
|
|
|
1
1
|
import { SplitIO } from '../types';
|
|
2
|
-
import {
|
|
2
|
+
import { DataLoader } from './types';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
|
|
4
|
+
* Factory of client-side storage loader
|
|
6
5
|
*
|
|
7
|
-
* @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
|
|
8
|
-
*
|
|
9
|
-
* @
|
|
10
|
-
*
|
|
11
|
-
* @TODO extend to load largeSegments
|
|
12
|
-
* @TODO extend to load data on shared mySegments storages. Be specific when emitting SDK_READY_FROM_CACHE on shared clients. Maybe the serializer should provide the `useSegments` flag.
|
|
13
|
-
* @TODO add logs, and input validation in this module, in favor of size reduction.
|
|
14
|
-
* @TODO unit tests
|
|
6
|
+
* @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
|
|
7
|
+
* and extended with a `mySegmentsData` property.
|
|
8
|
+
* @returns function to preload the storage
|
|
15
9
|
*/
|
|
16
|
-
export declare function
|
|
17
|
-
splits?: ISplitsCacheSync;
|
|
18
|
-
segments: ISegmentsCacheSync;
|
|
19
|
-
largeSegments?: ISegmentsCacheSync;
|
|
20
|
-
}, matchingKey?: string): void;
|
|
21
|
-
export declare function getSnapshot(storage: IStorageSync, userKeys?: SplitIO.SplitKey[]): SplitIO.PreloadedData;
|
|
10
|
+
export declare function dataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoader;
|