@splitsoftware/splitio-commons 3.1.1-rc.2 → 3.1.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 +1 -1
- package/cjs/presets/serverSide.js +1 -1
- package/cjs/sdkClient/client.js +2 -2
- package/cjs/sync/polling/pollingManagerCS.js +84 -79
- package/cjs/sync/polling/pollingManagerSS.js +43 -35
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/cjs/sync/submitters/impressionsSubmitter.js +1 -1
- package/cjs/sync/syncManagerOnline.js +2 -7
- package/esm/presets/serverSide.js +1 -1
- package/esm/sdkClient/client.js +2 -2
- package/esm/sync/polling/pollingManagerCS.js +84 -79
- package/esm/sync/polling/pollingManagerSS.js +43 -35
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/esm/sync/submitters/impressionsSubmitter.js +1 -1
- package/esm/sync/syncManagerOnline.js +2 -7
- package/package.json +1 -1
- package/src/dtos/types.ts +1 -1
- package/src/presets/serverSide.ts +1 -1
- package/src/sdkClient/client.ts +2 -2
- package/src/sync/polling/pollingManagerCS.ts +80 -78
- package/src/sync/polling/pollingManagerSS.ts +49 -45
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
- package/src/sync/submitters/impressionsSubmitter.ts +3 -3
- package/src/sync/submitters/types.ts +2 -2
- package/src/sync/syncManagerOnline.ts +2 -8
- package/types/splitio.d.ts +3 -2
package/CHANGES.txt
CHANGED
|
@@ -9,7 +9,7 @@ var InMemoryStorage_1 = require("../storages/inMemory/InMemoryStorage");
|
|
|
9
9
|
var sdkManager_1 = require("../sdkManager");
|
|
10
10
|
var sdkClientMethod_1 = require("../sdkClient/sdkClientMethod");
|
|
11
11
|
var impressionObserverSS_1 = require("../trackers/impressionObserver/impressionObserverSS");
|
|
12
|
-
var syncManagerOnlineSSFactory = (0, syncManagerOnline_1.syncManagerOnlineFactory)(pollingManagerSS_1.pollingManagerSSFactory, pushManager_1.pushManagerFactory);
|
|
12
|
+
var syncManagerOnlineSSFactory = (0, syncManagerOnline_1.syncManagerOnlineFactory)((0, pollingManagerSS_1.pollingManagerSSFactory)(), pushManager_1.pushManagerFactory);
|
|
13
13
|
exports.serverSideModules = {
|
|
14
14
|
storageFactory: InMemoryStorage_1.InMemoryStorageFactory,
|
|
15
15
|
serviceApiFactory: serviceApi_1.serviceApiFactory,
|
package/cjs/sdkClient/client.js
CHANGED
|
@@ -133,10 +133,10 @@ function clientFactory(params) {
|
|
|
133
133
|
time: Date.now(),
|
|
134
134
|
bucketingKey: bucketingKey,
|
|
135
135
|
label: label,
|
|
136
|
-
changeNumber: definition.changeNumber,
|
|
136
|
+
changeNumber: definition === null || definition === void 0 ? void 0 : definition.changeNumber,
|
|
137
137
|
properties: stringify(options.properties)
|
|
138
138
|
},
|
|
139
|
-
disabled: options.impressionsDisabled || definition.impressionsDisabled
|
|
139
|
+
disabled: options.impressionsDisabled || (definition === null || definition === void 0 ? void 0 : definition.impressionsDisabled)
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
142
|
if (withConfig) {
|
|
@@ -8,93 +8,98 @@ var key_1 = require("../../utils/key");
|
|
|
8
8
|
var constants_1 = require("../../readiness/constants");
|
|
9
9
|
var constants_2 = require("../../logger/constants");
|
|
10
10
|
var AbstractDefinitionsCacheSync_1 = require("../../storages/AbstractDefinitionsCacheSync");
|
|
11
|
+
var splitChangesFetcher_1 = require("./fetchers/splitChangesFetcher");
|
|
11
12
|
/**
|
|
12
13
|
* Expose start / stop mechanism for polling data from services.
|
|
13
14
|
* For client-side API with multiple clients.
|
|
14
15
|
*/
|
|
15
|
-
function pollingManagerCSFactory(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
(0,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (mySegmentsSyncTask.isRunning())
|
|
31
|
-
mySegmentsSyncTask.stop();
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
// smart pausing
|
|
35
|
-
readiness.definitions.on(constants_1.SDK_DEFINITIONS_ARRIVED, function () {
|
|
36
|
-
if (!definitionsSyncTask.isRunning())
|
|
37
|
-
return; // noop if not doing polling
|
|
38
|
-
var usingSegments = (0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage);
|
|
39
|
-
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
40
|
-
log.info(constants_2.POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
41
|
-
if (usingSegments) {
|
|
42
|
-
startMySegmentsSyncTasks();
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
stopMySegmentsSyncTasks();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
function add(matchingKey, readiness, storage) {
|
|
50
|
-
var mySegmentsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
51
|
-
// smart ready
|
|
52
|
-
function smartReady(metadata) {
|
|
53
|
-
if (!readiness.isReady() && !(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
|
|
54
|
-
readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED, metadata);
|
|
16
|
+
function pollingManagerCSFactory(definitionFetcherFactory) {
|
|
17
|
+
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcher_1.splitChangesFetcherFactory; }
|
|
18
|
+
return function (params) {
|
|
19
|
+
var serviceApi = params.serviceApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
20
|
+
var log = settings.log;
|
|
21
|
+
var definitionChangesFetcher = definitionFetcherFactory(params);
|
|
22
|
+
var definitionsSyncTask = (0, definitionsSyncTask_1.definitionsSyncTaskFactory)(definitionChangesFetcher, storage, readiness, settings);
|
|
23
|
+
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
24
|
+
var mySegmentsSyncTasks = {};
|
|
25
|
+
var matchingKey = (0, key_1.getMatching)(settings.core.key);
|
|
26
|
+
var mySegmentsSyncTask = add(matchingKey, readiness, storage);
|
|
27
|
+
function startMySegmentsSyncTasks() {
|
|
28
|
+
(0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
29
|
+
mySegmentsSyncTask.start();
|
|
30
|
+
});
|
|
55
31
|
}
|
|
56
|
-
|
|
57
|
-
setTimeout(smartReady, 0);
|
|
58
|
-
else
|
|
59
|
-
readiness.definitions.once(constants_1.SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
60
|
-
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
61
|
-
return mySegmentsSyncTask;
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
definitionsSyncTask: definitionsSyncTask,
|
|
65
|
-
segmentsSyncTask: mySegmentsSyncTask,
|
|
66
|
-
// Start periodic fetching (polling)
|
|
67
|
-
start: function () {
|
|
68
|
-
log.info(constants_2.POLLING_START);
|
|
69
|
-
definitionsSyncTask.start();
|
|
70
|
-
if ((0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
|
|
71
|
-
startMySegmentsSyncTasks();
|
|
72
|
-
},
|
|
73
|
-
// Stop periodic fetching (polling)
|
|
74
|
-
stop: function () {
|
|
75
|
-
log.info(constants_2.POLLING_STOP);
|
|
76
|
-
if (definitionsSyncTask.isRunning())
|
|
77
|
-
definitionsSyncTask.stop();
|
|
78
|
-
stopMySegmentsSyncTasks();
|
|
79
|
-
},
|
|
80
|
-
// Used by SyncManager to know if running in polling mode.
|
|
81
|
-
isRunning: definitionsSyncTask.isRunning,
|
|
82
|
-
// fetch definitions and segments
|
|
83
|
-
syncAll: function () {
|
|
84
|
-
var promises = [definitionsSyncTask.execute()];
|
|
32
|
+
function stopMySegmentsSyncTasks() {
|
|
85
33
|
(0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
86
|
-
|
|
34
|
+
if (mySegmentsSyncTask.isRunning())
|
|
35
|
+
mySegmentsSyncTask.stop();
|
|
87
36
|
});
|
|
88
|
-
return Promise.all(promises);
|
|
89
|
-
},
|
|
90
|
-
// Support for handling mySegments sync of multiple clients
|
|
91
|
-
add: add,
|
|
92
|
-
remove: function (matchingKey) {
|
|
93
|
-
delete mySegmentsSyncTasks[matchingKey];
|
|
94
|
-
},
|
|
95
|
-
get: function (matchingKey) {
|
|
96
|
-
return mySegmentsSyncTasks[matchingKey];
|
|
97
37
|
}
|
|
38
|
+
// smart pausing
|
|
39
|
+
readiness.definitions.on(constants_1.SDK_DEFINITIONS_ARRIVED, function () {
|
|
40
|
+
if (!definitionsSyncTask.isRunning())
|
|
41
|
+
return; // noop if not doing polling
|
|
42
|
+
var usingSegments = (0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage);
|
|
43
|
+
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
44
|
+
log.info(constants_2.POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
45
|
+
if (usingSegments) {
|
|
46
|
+
startMySegmentsSyncTasks();
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
stopMySegmentsSyncTasks();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
function add(matchingKey, readiness, storage) {
|
|
54
|
+
var mySegmentsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
55
|
+
// smart ready
|
|
56
|
+
function smartReady(metadata) {
|
|
57
|
+
if (!readiness.isReady() && !(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
|
|
58
|
+
readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED, metadata);
|
|
59
|
+
}
|
|
60
|
+
if (!(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
|
|
61
|
+
setTimeout(smartReady, 0);
|
|
62
|
+
else
|
|
63
|
+
readiness.definitions.once(constants_1.SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
64
|
+
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
65
|
+
return mySegmentsSyncTask;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
definitionsSyncTask: definitionsSyncTask,
|
|
69
|
+
segmentsSyncTask: mySegmentsSyncTask,
|
|
70
|
+
// Start periodic fetching (polling)
|
|
71
|
+
start: function () {
|
|
72
|
+
log.info(constants_2.POLLING_START);
|
|
73
|
+
definitionsSyncTask.start();
|
|
74
|
+
if ((0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
|
|
75
|
+
startMySegmentsSyncTasks();
|
|
76
|
+
},
|
|
77
|
+
// Stop periodic fetching (polling)
|
|
78
|
+
stop: function () {
|
|
79
|
+
log.info(constants_2.POLLING_STOP);
|
|
80
|
+
if (definitionsSyncTask.isRunning())
|
|
81
|
+
definitionsSyncTask.stop();
|
|
82
|
+
stopMySegmentsSyncTasks();
|
|
83
|
+
},
|
|
84
|
+
// Used by SyncManager to know if running in polling mode.
|
|
85
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
86
|
+
// fetch definitions and segments
|
|
87
|
+
syncAll: function () {
|
|
88
|
+
var promises = [definitionsSyncTask.execute()];
|
|
89
|
+
(0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
90
|
+
promises.push(mySegmentsSyncTask.execute());
|
|
91
|
+
});
|
|
92
|
+
return Promise.all(promises);
|
|
93
|
+
},
|
|
94
|
+
// Support for handling mySegments sync of multiple clients
|
|
95
|
+
add: add,
|
|
96
|
+
remove: function (matchingKey) {
|
|
97
|
+
delete mySegmentsSyncTasks[matchingKey];
|
|
98
|
+
},
|
|
99
|
+
get: function (matchingKey) {
|
|
100
|
+
return mySegmentsSyncTasks[matchingKey];
|
|
101
|
+
}
|
|
102
|
+
};
|
|
98
103
|
};
|
|
99
104
|
}
|
|
100
105
|
exports.pollingManagerCSFactory = pollingManagerCSFactory;
|
|
@@ -4,46 +4,54 @@ exports.pollingManagerSSFactory = void 0;
|
|
|
4
4
|
var definitionsSyncTask_1 = require("./syncTasks/definitionsSyncTask");
|
|
5
5
|
var segmentsSyncTask_1 = require("./syncTasks/segmentsSyncTask");
|
|
6
6
|
var constants_1 = require("../../logger/constants");
|
|
7
|
+
var segmentChangesFetcher_1 = require("./fetchers/segmentChangesFetcher");
|
|
8
|
+
var splitChangesFetcher_1 = require("./fetchers/splitChangesFetcher");
|
|
7
9
|
/**
|
|
8
10
|
* Expose start / stop mechanism for pulling data from services.
|
|
9
11
|
*/
|
|
10
|
-
function pollingManagerSSFactory(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
function pollingManagerSSFactory(definitionFetcherFactory, segmentFetcherFactory) {
|
|
13
|
+
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcher_1.splitChangesFetcherFactory; }
|
|
14
|
+
if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return (0, segmentChangesFetcher_1.segmentChangesFetcherFactory)(params.serviceApi.fetchSegmentChanges); }; }
|
|
15
|
+
return function (params) {
|
|
16
|
+
var storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
17
|
+
var log = settings.log;
|
|
18
|
+
var definitionChangesFetcher = definitionFetcherFactory(params);
|
|
19
|
+
var segmentChangesFetcher = segmentFetcherFactory(params);
|
|
20
|
+
var segmentsSyncTask = (0, segmentsSyncTask_1.segmentsSyncTaskFactory)(segmentChangesFetcher, storage, readiness, settings);
|
|
21
|
+
var definitionsSyncTask = (0, definitionsSyncTask_1.definitionsSyncTaskFactory)(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
|
|
22
|
+
return {
|
|
23
|
+
definitionsSyncTask: definitionsSyncTask,
|
|
24
|
+
segmentsSyncTask: segmentsSyncTask,
|
|
25
|
+
// Start periodic fetching (polling)
|
|
26
|
+
start: function () {
|
|
27
|
+
log.info(constants_1.POLLING_START);
|
|
28
|
+
log.debug(constants_1.LOG_PREFIX_SYNC_POLLING + "".concat(definitionChangesFetcher.type, " will be refreshed each ").concat(settings.scheduler.featuresRefreshRate, " millis"));
|
|
29
|
+
log.debug(constants_1.LOG_PREFIX_SYNC_POLLING + "segments will be refreshed each ".concat(settings.scheduler.segmentsRefreshRate, " millis"));
|
|
30
|
+
var startingUp = definitionsSyncTask.start();
|
|
31
|
+
if (startingUp) {
|
|
32
|
+
startingUp.then(function () {
|
|
33
|
+
if (definitionsSyncTask.isRunning())
|
|
34
|
+
segmentsSyncTask.start();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
// Stop periodic fetching (polling)
|
|
39
|
+
stop: function () {
|
|
40
|
+
log.info(constants_1.POLLING_STOP);
|
|
41
|
+
if (definitionsSyncTask.isRunning())
|
|
42
|
+
definitionsSyncTask.stop();
|
|
43
|
+
if (segmentsSyncTask.isRunning())
|
|
44
|
+
segmentsSyncTask.stop();
|
|
45
|
+
},
|
|
46
|
+
// Used by SyncManager to know if running in polling mode.
|
|
47
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
48
|
+
syncAll: function () {
|
|
49
|
+
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
50
|
+
return definitionsSyncTask.execute().then(function () {
|
|
51
|
+
return segmentsSyncTask.execute();
|
|
28
52
|
});
|
|
29
53
|
}
|
|
30
|
-
}
|
|
31
|
-
// Stop periodic fetching (polling)
|
|
32
|
-
stop: function () {
|
|
33
|
-
log.info(constants_1.POLLING_STOP);
|
|
34
|
-
if (definitionsSyncTask.isRunning())
|
|
35
|
-
definitionsSyncTask.stop();
|
|
36
|
-
if (segmentsSyncTask.isRunning())
|
|
37
|
-
segmentsSyncTask.stop();
|
|
38
|
-
},
|
|
39
|
-
// Used by SyncManager to know if running in polling mode.
|
|
40
|
-
isRunning: definitionsSyncTask.isRunning,
|
|
41
|
-
syncAll: function () {
|
|
42
|
-
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
43
|
-
return definitionsSyncTask.execute().then(function () {
|
|
44
|
-
return segmentsSyncTask.execute();
|
|
45
|
-
});
|
|
46
|
-
}
|
|
54
|
+
};
|
|
47
55
|
};
|
|
48
56
|
}
|
|
49
57
|
exports.pollingManagerSSFactory = pollingManagerSSFactory;
|
|
@@ -31,7 +31,7 @@ function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, read
|
|
|
31
31
|
false :
|
|
32
32
|
segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then(function (changes) {
|
|
33
33
|
return Promise.all(changes.map(function (x) {
|
|
34
|
-
log.debug("".concat(constants_2.LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
|
|
34
|
+
log.debug("".concat(constants_2.LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with since = ").concat(x.since, " and till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
|
|
35
35
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
36
36
|
})).then(function (updates) {
|
|
37
37
|
return updates.some(function (update) { return update; });
|
|
@@ -23,7 +23,7 @@ function fromImpressionsCollector(sendLabels, data) {
|
|
|
23
23
|
b: entry.bucketingKey,
|
|
24
24
|
pt: entry.pt,
|
|
25
25
|
properties: entry.properties,
|
|
26
|
-
// @
|
|
26
|
+
// @TODO: add entityType to public SplitIO.ImpressionDTO type
|
|
27
27
|
et: entry.entityType, // Definition type
|
|
28
28
|
};
|
|
29
29
|
})
|
|
@@ -8,8 +8,6 @@ var consent_1 = require("../consent");
|
|
|
8
8
|
var constants_3 = require("../utils/constants");
|
|
9
9
|
var constants_4 = require("../readiness/constants");
|
|
10
10
|
var AbstractDefinitionsCacheSync_1 = require("../storages/AbstractDefinitionsCacheSync");
|
|
11
|
-
var splitChangesFetcher_1 = require("./polling/fetchers/splitChangesFetcher");
|
|
12
|
-
var segmentChangesFetcher_1 = require("./polling/fetchers/segmentChangesFetcher");
|
|
13
11
|
/**
|
|
14
12
|
* Online SyncManager factory.
|
|
15
13
|
* Can be used for server-side API, and client-side API with or without multiple clients.
|
|
@@ -17,18 +15,15 @@ var segmentChangesFetcher_1 = require("./polling/fetchers/segmentChangesFetcher"
|
|
|
17
15
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
18
16
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
19
17
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
20
|
-
* @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
|
|
21
18
|
*/
|
|
22
|
-
function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory
|
|
23
|
-
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcher_1.splitChangesFetcherFactory; }
|
|
24
|
-
if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return (0, segmentChangesFetcher_1.segmentChangesFetcherFactory)(params.serviceApi.fetchSegmentChanges); }; }
|
|
19
|
+
function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
25
20
|
/**
|
|
26
21
|
* SyncManager factory for modular SDK
|
|
27
22
|
*/
|
|
28
23
|
return function (params) {
|
|
29
24
|
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker, storage = params.storage, readiness = params.readiness;
|
|
30
25
|
/** Polling Manager */
|
|
31
|
-
var pollingManager = pollingManagerFactory && pollingManagerFactory(params
|
|
26
|
+
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
32
27
|
/** Push Manager */
|
|
33
28
|
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
34
29
|
pushManagerFactory(params, pollingManager) :
|
|
@@ -6,7 +6,7 @@ import { InMemoryStorageFactory } from '../storages/inMemory/InMemoryStorage';
|
|
|
6
6
|
import { sdkManagerFactory } from '../sdkManager';
|
|
7
7
|
import { sdkClientMethodFactory } from '../sdkClient/sdkClientMethod';
|
|
8
8
|
import { impressionObserverSSFactory } from '../trackers/impressionObserver/impressionObserverSS';
|
|
9
|
-
var syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory, pushManagerFactory);
|
|
9
|
+
var syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory(), pushManagerFactory);
|
|
10
10
|
export var serverSideModules = {
|
|
11
11
|
storageFactory: InMemoryStorageFactory,
|
|
12
12
|
serviceApiFactory: serviceApiFactory,
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -129,10 +129,10 @@ export function clientFactory(params) {
|
|
|
129
129
|
time: Date.now(),
|
|
130
130
|
bucketingKey: bucketingKey,
|
|
131
131
|
label: label,
|
|
132
|
-
changeNumber: definition.changeNumber,
|
|
132
|
+
changeNumber: definition === null || definition === void 0 ? void 0 : definition.changeNumber,
|
|
133
133
|
properties: stringify(options.properties)
|
|
134
134
|
},
|
|
135
|
-
disabled: options.impressionsDisabled || definition.impressionsDisabled
|
|
135
|
+
disabled: options.impressionsDisabled || (definition === null || definition === void 0 ? void 0 : definition.impressionsDisabled)
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
138
|
if (withConfig) {
|
|
@@ -5,92 +5,97 @@ import { getMatching } from '../../utils/key';
|
|
|
5
5
|
import { SDK_DEFINITIONS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants';
|
|
6
6
|
import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants';
|
|
7
7
|
import { usesSegmentsSync } from '../../storages/AbstractDefinitionsCacheSync';
|
|
8
|
+
import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
|
|
8
9
|
/**
|
|
9
10
|
* Expose start / stop mechanism for polling data from services.
|
|
10
11
|
* For client-side API with multiple clients.
|
|
11
12
|
*/
|
|
12
|
-
export function pollingManagerCSFactory(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (mySegmentsSyncTask.isRunning())
|
|
28
|
-
mySegmentsSyncTask.stop();
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
// smart pausing
|
|
32
|
-
readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, function () {
|
|
33
|
-
if (!definitionsSyncTask.isRunning())
|
|
34
|
-
return; // noop if not doing polling
|
|
35
|
-
var usingSegments = usesSegmentsSync(storage);
|
|
36
|
-
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
37
|
-
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
38
|
-
if (usingSegments) {
|
|
39
|
-
startMySegmentsSyncTasks();
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
stopMySegmentsSyncTasks();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
function add(matchingKey, readiness, storage) {
|
|
47
|
-
var mySegmentsSyncTask = mySegmentsSyncTaskFactory(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
48
|
-
// smart ready
|
|
49
|
-
function smartReady(metadata) {
|
|
50
|
-
if (!readiness.isReady() && !usesSegmentsSync(storage))
|
|
51
|
-
readiness.segments.emit(SDK_SEGMENTS_ARRIVED, metadata);
|
|
13
|
+
export function pollingManagerCSFactory(definitionFetcherFactory) {
|
|
14
|
+
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcherFactory; }
|
|
15
|
+
return function (params) {
|
|
16
|
+
var serviceApi = params.serviceApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
17
|
+
var log = settings.log;
|
|
18
|
+
var definitionChangesFetcher = definitionFetcherFactory(params);
|
|
19
|
+
var definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings);
|
|
20
|
+
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
21
|
+
var mySegmentsSyncTasks = {};
|
|
22
|
+
var matchingKey = getMatching(settings.core.key);
|
|
23
|
+
var mySegmentsSyncTask = add(matchingKey, readiness, storage);
|
|
24
|
+
function startMySegmentsSyncTasks() {
|
|
25
|
+
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
26
|
+
mySegmentsSyncTask.start();
|
|
27
|
+
});
|
|
52
28
|
}
|
|
53
|
-
|
|
54
|
-
setTimeout(smartReady, 0);
|
|
55
|
-
else
|
|
56
|
-
readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
57
|
-
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
58
|
-
return mySegmentsSyncTask;
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
definitionsSyncTask: definitionsSyncTask,
|
|
62
|
-
segmentsSyncTask: mySegmentsSyncTask,
|
|
63
|
-
// Start periodic fetching (polling)
|
|
64
|
-
start: function () {
|
|
65
|
-
log.info(POLLING_START);
|
|
66
|
-
definitionsSyncTask.start();
|
|
67
|
-
if (usesSegmentsSync(storage))
|
|
68
|
-
startMySegmentsSyncTasks();
|
|
69
|
-
},
|
|
70
|
-
// Stop periodic fetching (polling)
|
|
71
|
-
stop: function () {
|
|
72
|
-
log.info(POLLING_STOP);
|
|
73
|
-
if (definitionsSyncTask.isRunning())
|
|
74
|
-
definitionsSyncTask.stop();
|
|
75
|
-
stopMySegmentsSyncTasks();
|
|
76
|
-
},
|
|
77
|
-
// Used by SyncManager to know if running in polling mode.
|
|
78
|
-
isRunning: definitionsSyncTask.isRunning,
|
|
79
|
-
// fetch definitions and segments
|
|
80
|
-
syncAll: function () {
|
|
81
|
-
var promises = [definitionsSyncTask.execute()];
|
|
29
|
+
function stopMySegmentsSyncTasks() {
|
|
82
30
|
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
83
|
-
|
|
31
|
+
if (mySegmentsSyncTask.isRunning())
|
|
32
|
+
mySegmentsSyncTask.stop();
|
|
84
33
|
});
|
|
85
|
-
return Promise.all(promises);
|
|
86
|
-
},
|
|
87
|
-
// Support for handling mySegments sync of multiple clients
|
|
88
|
-
add: add,
|
|
89
|
-
remove: function (matchingKey) {
|
|
90
|
-
delete mySegmentsSyncTasks[matchingKey];
|
|
91
|
-
},
|
|
92
|
-
get: function (matchingKey) {
|
|
93
|
-
return mySegmentsSyncTasks[matchingKey];
|
|
94
34
|
}
|
|
35
|
+
// smart pausing
|
|
36
|
+
readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, function () {
|
|
37
|
+
if (!definitionsSyncTask.isRunning())
|
|
38
|
+
return; // noop if not doing polling
|
|
39
|
+
var usingSegments = usesSegmentsSync(storage);
|
|
40
|
+
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
41
|
+
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
42
|
+
if (usingSegments) {
|
|
43
|
+
startMySegmentsSyncTasks();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
stopMySegmentsSyncTasks();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
function add(matchingKey, readiness, storage) {
|
|
51
|
+
var mySegmentsSyncTask = mySegmentsSyncTaskFactory(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
52
|
+
// smart ready
|
|
53
|
+
function smartReady(metadata) {
|
|
54
|
+
if (!readiness.isReady() && !usesSegmentsSync(storage))
|
|
55
|
+
readiness.segments.emit(SDK_SEGMENTS_ARRIVED, metadata);
|
|
56
|
+
}
|
|
57
|
+
if (!usesSegmentsSync(storage))
|
|
58
|
+
setTimeout(smartReady, 0);
|
|
59
|
+
else
|
|
60
|
+
readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
61
|
+
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
62
|
+
return mySegmentsSyncTask;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
definitionsSyncTask: definitionsSyncTask,
|
|
66
|
+
segmentsSyncTask: mySegmentsSyncTask,
|
|
67
|
+
// Start periodic fetching (polling)
|
|
68
|
+
start: function () {
|
|
69
|
+
log.info(POLLING_START);
|
|
70
|
+
definitionsSyncTask.start();
|
|
71
|
+
if (usesSegmentsSync(storage))
|
|
72
|
+
startMySegmentsSyncTasks();
|
|
73
|
+
},
|
|
74
|
+
// Stop periodic fetching (polling)
|
|
75
|
+
stop: function () {
|
|
76
|
+
log.info(POLLING_STOP);
|
|
77
|
+
if (definitionsSyncTask.isRunning())
|
|
78
|
+
definitionsSyncTask.stop();
|
|
79
|
+
stopMySegmentsSyncTasks();
|
|
80
|
+
},
|
|
81
|
+
// Used by SyncManager to know if running in polling mode.
|
|
82
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
83
|
+
// fetch definitions and segments
|
|
84
|
+
syncAll: function () {
|
|
85
|
+
var promises = [definitionsSyncTask.execute()];
|
|
86
|
+
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
87
|
+
promises.push(mySegmentsSyncTask.execute());
|
|
88
|
+
});
|
|
89
|
+
return Promise.all(promises);
|
|
90
|
+
},
|
|
91
|
+
// Support for handling mySegments sync of multiple clients
|
|
92
|
+
add: add,
|
|
93
|
+
remove: function (matchingKey) {
|
|
94
|
+
delete mySegmentsSyncTasks[matchingKey];
|
|
95
|
+
},
|
|
96
|
+
get: function (matchingKey) {
|
|
97
|
+
return mySegmentsSyncTasks[matchingKey];
|
|
98
|
+
}
|
|
99
|
+
};
|
|
95
100
|
};
|
|
96
101
|
}
|
|
@@ -1,45 +1,53 @@
|
|
|
1
1
|
import { definitionsSyncTaskFactory } from './syncTasks/definitionsSyncTask';
|
|
2
2
|
import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
|
|
3
3
|
import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
|
|
4
|
+
import { segmentChangesFetcherFactory } from './fetchers/segmentChangesFetcher';
|
|
5
|
+
import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
|
|
4
6
|
/**
|
|
5
7
|
* Expose start / stop mechanism for pulling data from services.
|
|
6
8
|
*/
|
|
7
|
-
export function pollingManagerSSFactory(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
9
|
+
export function pollingManagerSSFactory(definitionFetcherFactory, segmentFetcherFactory) {
|
|
10
|
+
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcherFactory; }
|
|
11
|
+
if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges); }; }
|
|
12
|
+
return function (params) {
|
|
13
|
+
var storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
14
|
+
var log = settings.log;
|
|
15
|
+
var definitionChangesFetcher = definitionFetcherFactory(params);
|
|
16
|
+
var segmentChangesFetcher = segmentFetcherFactory(params);
|
|
17
|
+
var segmentsSyncTask = segmentsSyncTaskFactory(segmentChangesFetcher, storage, readiness, settings);
|
|
18
|
+
var definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
|
|
19
|
+
return {
|
|
20
|
+
definitionsSyncTask: definitionsSyncTask,
|
|
21
|
+
segmentsSyncTask: segmentsSyncTask,
|
|
22
|
+
// Start periodic fetching (polling)
|
|
23
|
+
start: function () {
|
|
24
|
+
log.info(POLLING_START);
|
|
25
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + "".concat(definitionChangesFetcher.type, " will be refreshed each ").concat(settings.scheduler.featuresRefreshRate, " millis"));
|
|
26
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + "segments will be refreshed each ".concat(settings.scheduler.segmentsRefreshRate, " millis"));
|
|
27
|
+
var startingUp = definitionsSyncTask.start();
|
|
28
|
+
if (startingUp) {
|
|
29
|
+
startingUp.then(function () {
|
|
30
|
+
if (definitionsSyncTask.isRunning())
|
|
31
|
+
segmentsSyncTask.start();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
// Stop periodic fetching (polling)
|
|
36
|
+
stop: function () {
|
|
37
|
+
log.info(POLLING_STOP);
|
|
38
|
+
if (definitionsSyncTask.isRunning())
|
|
39
|
+
definitionsSyncTask.stop();
|
|
40
|
+
if (segmentsSyncTask.isRunning())
|
|
41
|
+
segmentsSyncTask.stop();
|
|
42
|
+
},
|
|
43
|
+
// Used by SyncManager to know if running in polling mode.
|
|
44
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
45
|
+
syncAll: function () {
|
|
46
|
+
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
47
|
+
return definitionsSyncTask.execute().then(function () {
|
|
48
|
+
return segmentsSyncTask.execute();
|
|
25
49
|
});
|
|
26
50
|
}
|
|
27
|
-
}
|
|
28
|
-
// Stop periodic fetching (polling)
|
|
29
|
-
stop: function () {
|
|
30
|
-
log.info(POLLING_STOP);
|
|
31
|
-
if (definitionsSyncTask.isRunning())
|
|
32
|
-
definitionsSyncTask.stop();
|
|
33
|
-
if (segmentsSyncTask.isRunning())
|
|
34
|
-
segmentsSyncTask.stop();
|
|
35
|
-
},
|
|
36
|
-
// Used by SyncManager to know if running in polling mode.
|
|
37
|
-
isRunning: definitionsSyncTask.isRunning,
|
|
38
|
-
syncAll: function () {
|
|
39
|
-
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
40
|
-
return definitionsSyncTask.execute().then(function () {
|
|
41
|
-
return segmentsSyncTask.execute();
|
|
42
|
-
});
|
|
43
|
-
}
|
|
51
|
+
};
|
|
44
52
|
};
|
|
45
53
|
}
|
|
@@ -28,7 +28,7 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
28
28
|
false :
|
|
29
29
|
segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then(function (changes) {
|
|
30
30
|
return Promise.all(changes.map(function (x) {
|
|
31
|
-
log.debug("".concat(LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
|
|
31
|
+
log.debug("".concat(LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with since = ").concat(x.since, " and till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
|
|
32
32
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
33
33
|
})).then(function (updates) {
|
|
34
34
|
return updates.some(function (update) { return update; });
|
|
@@ -20,7 +20,7 @@ export function fromImpressionsCollector(sendLabels, data) {
|
|
|
20
20
|
b: entry.bucketingKey,
|
|
21
21
|
pt: entry.pt,
|
|
22
22
|
properties: entry.properties,
|
|
23
|
-
// @
|
|
23
|
+
// @TODO: add entityType to public SplitIO.ImpressionDTO type
|
|
24
24
|
et: entry.entityType, // Definition type
|
|
25
25
|
};
|
|
26
26
|
})
|
|
@@ -5,8 +5,6 @@ import { isConsentGranted } from '../consent';
|
|
|
5
5
|
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
6
6
|
import { SDK_DEFINITIONS_CACHE_LOADED } from '../readiness/constants';
|
|
7
7
|
import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
|
|
8
|
-
import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
|
|
9
|
-
import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesFetcher';
|
|
10
8
|
/**
|
|
11
9
|
* Online SyncManager factory.
|
|
12
10
|
* Can be used for server-side API, and client-side API with or without multiple clients.
|
|
@@ -14,18 +12,15 @@ import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesF
|
|
|
14
12
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
15
13
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
16
14
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
17
|
-
* @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
|
|
18
15
|
*/
|
|
19
|
-
export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory
|
|
20
|
-
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcherFactory; }
|
|
21
|
-
if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges); }; }
|
|
16
|
+
export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
22
17
|
/**
|
|
23
18
|
* SyncManager factory for modular SDK
|
|
24
19
|
*/
|
|
25
20
|
return function (params) {
|
|
26
21
|
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker, storage = params.storage, readiness = params.readiness;
|
|
27
22
|
/** Polling Manager */
|
|
28
|
-
var pollingManager = pollingManagerFactory && pollingManagerFactory(params
|
|
23
|
+
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
29
24
|
/** Push Manager */
|
|
30
25
|
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
31
26
|
pushManagerFactory(params, pollingManager) :
|
package/package.json
CHANGED
package/src/dtos/types.ts
CHANGED
|
@@ -236,7 +236,7 @@ export interface IDefinition extends TargetingEntity {
|
|
|
236
236
|
} | null;
|
|
237
237
|
/** Definition classification. Absent means a feature flag. */
|
|
238
238
|
type?: ConfigType;
|
|
239
|
-
/** Only meaningful when `type === '
|
|
239
|
+
/** Only meaningful when `type === 'ai'`. */
|
|
240
240
|
subtype?: ConfigSubtype;
|
|
241
241
|
}
|
|
242
242
|
|
|
@@ -7,7 +7,7 @@ import { sdkManagerFactory } from '../sdkManager';
|
|
|
7
7
|
import { sdkClientMethodFactory } from '../sdkClient/sdkClientMethod';
|
|
8
8
|
import { impressionObserverSSFactory } from '../trackers/impressionObserver/impressionObserverSS';
|
|
9
9
|
|
|
10
|
-
const syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory, pushManagerFactory);
|
|
10
|
+
const syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory(), pushManagerFactory);
|
|
11
11
|
|
|
12
12
|
export const serverSideModules = {
|
|
13
13
|
storageFactory: InMemoryStorageFactory,
|
package/src/sdkClient/client.ts
CHANGED
|
@@ -161,10 +161,10 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
|
|
|
161
161
|
time: Date.now(),
|
|
162
162
|
bucketingKey,
|
|
163
163
|
label,
|
|
164
|
-
changeNumber: definition
|
|
164
|
+
changeNumber: definition?.changeNumber,
|
|
165
165
|
properties: stringify(options.properties)
|
|
166
166
|
}, // @ts-expect-error impressionsDisabled is not exposed in the public typings yet.
|
|
167
|
-
disabled: options.impressionsDisabled || definition
|
|
167
|
+
disabled: options.impressionsDisabled || definition?.impressionsDisabled
|
|
168
168
|
});
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -10,110 +10,112 @@ import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger
|
|
|
10
10
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
11
11
|
import { usesSegmentsSync } from '../../storages/AbstractDefinitionsCacheSync';
|
|
12
12
|
import { SdkUpdateMetadata } from '../../../types/splitio';
|
|
13
|
-
import {
|
|
13
|
+
import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Expose start / stop mechanism for polling data from services.
|
|
17
17
|
* For client-side API with multiple clients.
|
|
18
18
|
*/
|
|
19
19
|
export function pollingManagerCSFactory(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
): IPollingManagerCS {
|
|
20
|
+
definitionFetcherFactory = splitChangesFetcherFactory,
|
|
21
|
+
): (params: ISdkFactoryContextSync) => IPollingManagerCS {
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
return function (params: ISdkFactoryContextSync): IPollingManagerCS {
|
|
24
|
+
const { serviceApi, storage, readiness, settings } = params;
|
|
25
|
+
const log = settings.log;
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
const definitionChangesFetcher = definitionFetcherFactory(params);
|
|
28
|
+
const definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings);
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
31
|
+
const mySegmentsSyncTasks: Record<string, IMySegmentsSyncTask> = {};
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const matchingKey = getMatching(settings.core.key);
|
|
34
|
+
const mySegmentsSyncTask = add(matchingKey, readiness, storage);
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
function startMySegmentsSyncTasks() {
|
|
37
|
+
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
38
|
+
mySegmentsSyncTask.start();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// smart pausing
|
|
48
|
-
readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, () => {
|
|
49
|
-
if (!definitionsSyncTask.isRunning()) return; // noop if not doing polling
|
|
50
|
-
const usingSegments = usesSegmentsSync(storage);
|
|
51
|
-
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
52
|
-
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
53
|
-
if (usingSegments) {
|
|
54
|
-
startMySegmentsSyncTasks();
|
|
55
|
-
} else {
|
|
56
|
-
stopMySegmentsSyncTasks();
|
|
57
|
-
}
|
|
42
|
+
function stopMySegmentsSyncTasks() {
|
|
43
|
+
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
44
|
+
if (mySegmentsSyncTask.isRunning()) mySegmentsSyncTask.stop();
|
|
45
|
+
});
|
|
58
46
|
}
|
|
59
|
-
});
|
|
60
47
|
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
// smart pausing
|
|
49
|
+
readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, () => {
|
|
50
|
+
if (!definitionsSyncTask.isRunning()) return; // noop if not doing polling
|
|
51
|
+
const usingSegments = usesSegmentsSync(storage);
|
|
52
|
+
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
53
|
+
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
54
|
+
if (usingSegments) {
|
|
55
|
+
startMySegmentsSyncTasks();
|
|
56
|
+
} else {
|
|
57
|
+
stopMySegmentsSyncTasks();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function add(matchingKey: string, readiness: IReadinessManager, storage: IStorageSync) {
|
|
63
|
+
const mySegmentsSyncTask = mySegmentsSyncTaskFactory(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
// smart ready
|
|
66
|
+
function smartReady(metadata: SdkUpdateMetadata) {
|
|
67
|
+
if (!readiness.isReady() && !usesSegmentsSync(storage)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED, metadata);
|
|
68
|
+
}
|
|
69
|
+
if (!usesSegmentsSync(storage)) setTimeout(smartReady, 0);
|
|
70
|
+
else readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
71
|
+
|
|
72
|
+
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
73
|
+
return mySegmentsSyncTask;
|
|
67
74
|
}
|
|
68
|
-
if (!usesSegmentsSync(storage)) setTimeout(smartReady, 0);
|
|
69
|
-
else readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
return {
|
|
77
|
+
definitionsSyncTask,
|
|
78
|
+
segmentsSyncTask: mySegmentsSyncTask,
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
// Start periodic fetching (polling)
|
|
81
|
+
start() {
|
|
82
|
+
log.info(POLLING_START);
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
definitionsSyncTask.start();
|
|
85
|
+
if (usesSegmentsSync(storage)) startMySegmentsSyncTasks();
|
|
86
|
+
},
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
// Stop periodic fetching (polling)
|
|
89
|
+
stop() {
|
|
90
|
+
log.info(POLLING_STOP);
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
if (definitionsSyncTask.isRunning()) definitionsSyncTask.stop();
|
|
93
|
+
stopMySegmentsSyncTasks();
|
|
94
|
+
},
|
|
90
95
|
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
},
|
|
96
|
+
// Used by SyncManager to know if running in polling mode.
|
|
97
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
94
98
|
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
// fetch definitions and segments
|
|
100
|
+
syncAll() {
|
|
101
|
+
const promises = [definitionsSyncTask.execute()];
|
|
102
|
+
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
103
|
+
promises.push(mySegmentsSyncTask.execute());
|
|
104
|
+
});
|
|
105
|
+
return Promise.all(promises);
|
|
106
|
+
},
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const promises = [definitionsSyncTask.execute()];
|
|
101
|
-
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
102
|
-
promises.push(mySegmentsSyncTask.execute());
|
|
103
|
-
});
|
|
104
|
-
return Promise.all(promises);
|
|
105
|
-
},
|
|
108
|
+
// Support for handling mySegments sync of multiple clients
|
|
109
|
+
add,
|
|
106
110
|
|
|
107
|
-
|
|
108
|
-
|
|
111
|
+
remove(matchingKey: string) {
|
|
112
|
+
delete mySegmentsSyncTasks[matchingKey];
|
|
113
|
+
},
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
get(matchingKey: string) {
|
|
116
|
+
return mySegmentsSyncTasks[matchingKey];
|
|
117
|
+
}
|
|
118
|
+
};
|
|
113
119
|
|
|
114
|
-
get(matchingKey: string) {
|
|
115
|
-
return mySegmentsSyncTasks[matchingKey];
|
|
116
|
-
}
|
|
117
120
|
};
|
|
118
|
-
|
|
119
121
|
}
|
|
@@ -3,57 +3,61 @@ import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
|
|
|
3
3
|
import { IPollingManager, ISegmentsSyncTask, IDefinitionsSyncTask } from './types';
|
|
4
4
|
import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
|
|
5
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
6
|
-
import {
|
|
6
|
+
import { segmentChangesFetcherFactory } from './fetchers/segmentChangesFetcher';
|
|
7
|
+
import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Expose start / stop mechanism for pulling data from services.
|
|
10
11
|
*/
|
|
11
12
|
export function pollingManagerSSFactory(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
startingUp.
|
|
36
|
-
|
|
13
|
+
definitionFetcherFactory = splitChangesFetcherFactory,
|
|
14
|
+
segmentFetcherFactory = (params: ISdkFactoryContextSync) => segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges)
|
|
15
|
+
): (params: ISdkFactoryContextSync) => IPollingManager {
|
|
16
|
+
|
|
17
|
+
return function (params: ISdkFactoryContextSync): IPollingManager {
|
|
18
|
+
const { storage, readiness, settings } = params;
|
|
19
|
+
const log = settings.log;
|
|
20
|
+
|
|
21
|
+
const definitionChangesFetcher = definitionFetcherFactory(params);
|
|
22
|
+
const segmentChangesFetcher = segmentFetcherFactory(params);
|
|
23
|
+
const segmentsSyncTask: ISegmentsSyncTask = segmentsSyncTaskFactory(segmentChangesFetcher, storage, readiness, settings);
|
|
24
|
+
const definitionsSyncTask: IDefinitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
definitionsSyncTask,
|
|
28
|
+
segmentsSyncTask,
|
|
29
|
+
|
|
30
|
+
// Start periodic fetching (polling)
|
|
31
|
+
start() {
|
|
32
|
+
log.info(POLLING_START);
|
|
33
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + `${definitionChangesFetcher.type} will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`);
|
|
34
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + `segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`);
|
|
35
|
+
|
|
36
|
+
const startingUp = definitionsSyncTask.start();
|
|
37
|
+
if (startingUp) {
|
|
38
|
+
startingUp.then(() => {
|
|
39
|
+
if (definitionsSyncTask.isRunning()) segmentsSyncTask.start();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// Stop periodic fetching (polling)
|
|
45
|
+
stop() {
|
|
46
|
+
log.info(POLLING_STOP);
|
|
47
|
+
|
|
48
|
+
if (definitionsSyncTask.isRunning()) definitionsSyncTask.stop();
|
|
49
|
+
if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop();
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// Used by SyncManager to know if running in polling mode.
|
|
53
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
54
|
+
|
|
55
|
+
syncAll() {
|
|
56
|
+
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
57
|
+
return definitionsSyncTask.execute().then(() => {
|
|
58
|
+
return segmentsSyncTask.execute();
|
|
37
59
|
});
|
|
38
60
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Stop periodic fetching (polling)
|
|
42
|
-
stop() {
|
|
43
|
-
log.info(POLLING_STOP);
|
|
44
|
-
|
|
45
|
-
if (definitionsSyncTask.isRunning()) definitionsSyncTask.stop();
|
|
46
|
-
if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop();
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
// Used by SyncManager to know if running in polling mode.
|
|
50
|
-
isRunning: definitionsSyncTask.isRunning,
|
|
51
|
-
|
|
52
|
-
syncAll() {
|
|
53
|
-
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
54
|
-
return definitionsSyncTask.execute().then(() => {
|
|
55
|
-
return segmentsSyncTask.execute();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
61
|
+
};
|
|
58
62
|
};
|
|
59
63
|
}
|
|
@@ -47,7 +47,7 @@ export function segmentChangesUpdaterFactory(
|
|
|
47
47
|
false :
|
|
48
48
|
segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then((changes) => {
|
|
49
49
|
return Promise.all(changes.map(x => {
|
|
50
|
-
log.debug(`${LOG_PREFIX_SYNC}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
50
|
+
log.debug(`${LOG_PREFIX_SYNC}Processing ${segmentName} with since = ${x.since} and till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
51
51
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
52
52
|
})).then((updates) => {
|
|
53
53
|
return updates.some(update => update);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { groupBy, forOwn } from '../../utils/lang';
|
|
2
2
|
import SplitIO from '../../../types/splitio';
|
|
3
3
|
import { submitterFactory } from './submitter';
|
|
4
|
-
import { ImpressionsPayload } from './types';
|
|
4
|
+
import { EntityType, ImpressionsPayload } from './types';
|
|
5
5
|
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
6
6
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Converts `impressions` data from cache into request payload.
|
|
10
10
|
*/
|
|
11
|
-
export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.ImpressionDTO[]): ImpressionsPayload {
|
|
11
|
+
export function fromImpressionsCollector(sendLabels: boolean, data: (SplitIO.ImpressionDTO & { entityType?: EntityType })[]): ImpressionsPayload {
|
|
12
12
|
let groupedByFeature = groupBy(data, 'feature');
|
|
13
13
|
let dto: ImpressionsPayload = [];
|
|
14
14
|
|
|
@@ -25,7 +25,7 @@ export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.Impr
|
|
|
25
25
|
b: entry.bucketingKey, // Bucketing Key
|
|
26
26
|
pt: entry.pt, // Previous time
|
|
27
27
|
properties: entry.properties, // Properties
|
|
28
|
-
// @
|
|
28
|
+
// @TODO: add entityType to public SplitIO.ImpressionDTO type
|
|
29
29
|
et: entry.entityType, // Definition type
|
|
30
30
|
};
|
|
31
31
|
})
|
|
@@ -3,7 +3,7 @@ import { IMetadata } from '../../dtos/types';
|
|
|
3
3
|
import SplitIO from '../../../types/splitio';
|
|
4
4
|
import { ISyncTask } from '../types';
|
|
5
5
|
|
|
6
|
-
type EntityType = 'config' | 'flag' | 'ai-config';
|
|
6
|
+
export type EntityType = 'config' | 'flag' | 'ai-config';
|
|
7
7
|
|
|
8
8
|
type ImpressionPayload = {
|
|
9
9
|
/** Matching Key */
|
|
@@ -15,7 +15,7 @@ type ImpressionPayload = {
|
|
|
15
15
|
/** Timestamp */
|
|
16
16
|
m: number;
|
|
17
17
|
/** Change number */
|
|
18
|
-
c
|
|
18
|
+
c?: number;
|
|
19
19
|
/** Rule label */
|
|
20
20
|
r?: string;
|
|
21
21
|
/** Previous time */
|
|
@@ -11,9 +11,6 @@ import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
|
11
11
|
import { ISdkFactoryContextSync } from '../sdkFactory/types';
|
|
12
12
|
import { SDK_DEFINITIONS_CACHE_LOADED } from '../readiness/constants';
|
|
13
13
|
import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
|
|
14
|
-
import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
|
|
15
|
-
import { IDefinitionChangesFetcher, ISegmentChangesFetcher } from './polling/fetchers/types';
|
|
16
|
-
import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesFetcher';
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
16
|
* Online SyncManager factory.
|
|
@@ -22,13 +19,10 @@ import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesF
|
|
|
22
19
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
23
20
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
24
21
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
25
|
-
* @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
|
|
26
22
|
*/
|
|
27
23
|
export function syncManagerOnlineFactory(
|
|
28
|
-
pollingManagerFactory?: (params: ISdkFactoryContextSync
|
|
24
|
+
pollingManagerFactory?: (params: ISdkFactoryContextSync) => IPollingManager,
|
|
29
25
|
pushManagerFactory?: (params: ISdkFactoryContextSync, pollingManager: IPollingManager) => IPushManager | undefined,
|
|
30
|
-
definitionFetcherFactory = splitChangesFetcherFactory,
|
|
31
|
-
segmentFetcherFactory = (params: ISdkFactoryContextSync) => segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges)
|
|
32
26
|
): (params: ISdkFactoryContextSync) => ISyncManagerCS {
|
|
33
27
|
|
|
34
28
|
/**
|
|
@@ -39,7 +33,7 @@ export function syncManagerOnlineFactory(
|
|
|
39
33
|
const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker, storage, readiness } = params;
|
|
40
34
|
|
|
41
35
|
/** Polling Manager */
|
|
42
|
-
const pollingManager = pollingManagerFactory && pollingManagerFactory(params
|
|
36
|
+
const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
43
37
|
|
|
44
38
|
/** Push Manager */
|
|
45
39
|
const pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
package/types/splitio.d.ts
CHANGED
|
@@ -1031,9 +1031,10 @@ declare namespace SplitIO {
|
|
|
1031
1031
|
*/
|
|
1032
1032
|
label: string;
|
|
1033
1033
|
/**
|
|
1034
|
-
* Version of the feature flag
|
|
1034
|
+
* Version of the feature flag.
|
|
1035
|
+
* Undefined if the feature flag was not found, for example, if the label is 'not ready', 'exception' or 'definition not found'.
|
|
1035
1036
|
*/
|
|
1036
|
-
changeNumber
|
|
1037
|
+
changeNumber?: number;
|
|
1037
1038
|
/**
|
|
1038
1039
|
* Previous time
|
|
1039
1040
|
*/
|