@splitsoftware/splitio-commons 1.3.1 → 1.3.2-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/consent/sdkUserConsent.js +1 -1
- package/cjs/listeners/browser.js +5 -4
- package/cjs/logger/constants.js +2 -1
- package/cjs/logger/messages/error.js +2 -1
- package/cjs/logger/messages/info.js +3 -3
- package/cjs/logger/messages/warn.js +2 -2
- package/cjs/sdkClient/client.js +17 -3
- package/cjs/sdkClient/sdkClient.js +4 -1
- package/cjs/sdkFactory/index.js +16 -19
- package/cjs/services/splitApi.js +15 -14
- package/cjs/services/splitHttpClient.js +4 -1
- package/cjs/storages/AbstractSegmentsCacheSync.js +0 -5
- package/cjs/storages/KeyBuilderSS.js +12 -19
- package/cjs/storages/findLatencyIndex.js +11 -6
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +13 -1
- package/cjs/storages/inLocalStorage/index.js +4 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +2 -0
- package/cjs/storages/inMemory/InMemoryStorageCS.js +3 -0
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +6 -0
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +6 -0
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +165 -0
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +29 -0
- package/cjs/storages/inRedis/index.js +2 -4
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +27 -0
- package/cjs/storages/pluggable/index.js +2 -1
- package/cjs/sync/polling/pollingManagerCS.js +1 -1
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +2 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +0 -3
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -8
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +3 -6
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +20 -13
- package/cjs/sync/streaming/SSEHandler/index.js +21 -15
- package/cjs/sync/streaming/pushManager.js +7 -4
- package/cjs/sync/submitters/eventsSubmitter.js +28 -0
- package/cjs/sync/submitters/{impressionCountsSyncTask.js → impressionCountsSubmitter.js} +10 -7
- package/cjs/sync/submitters/{impressionsSyncTask.js → impressionsSubmitter.js} +8 -8
- package/cjs/sync/submitters/submitter.js +66 -0
- package/cjs/sync/submitters/submitterManager.js +12 -10
- package/cjs/sync/submitters/telemetrySubmitter.js +128 -0
- package/cjs/sync/syncManagerOnline.js +6 -2
- package/cjs/trackers/eventTracker.js +5 -1
- package/cjs/trackers/impressionsTracker.js +9 -1
- package/cjs/trackers/telemetryTracker.js +65 -0
- package/cjs/utils/constants/index.js +40 -1
- package/cjs/utils/inputValidation/apiKey.js +12 -11
- package/cjs/utils/settingsValidation/index.js +35 -11
- package/cjs/utils/settingsValidation/url.js +4 -0
- package/cjs/utils/timeTracker/index.js +1 -0
- package/cjs/utils/timeTracker/timer.js +2 -2
- package/esm/consent/sdkUserConsent.js +1 -1
- package/esm/listeners/browser.js +3 -2
- package/esm/logger/constants.js +1 -0
- package/esm/logger/messages/error.js +2 -1
- package/esm/logger/messages/info.js +3 -3
- package/esm/logger/messages/warn.js +2 -2
- package/esm/sdkClient/client.js +18 -4
- package/esm/sdkClient/sdkClient.js +4 -1
- package/esm/sdkFactory/index.js +16 -19
- package/esm/services/splitApi.js +15 -14
- package/esm/services/splitHttpClient.js +4 -1
- package/esm/storages/AbstractSegmentsCacheSync.js +0 -5
- package/esm/storages/KeyBuilderSS.js +12 -19
- package/esm/storages/findLatencyIndex.js +11 -6
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +13 -1
- package/esm/storages/inLocalStorage/index.js +5 -2
- package/esm/storages/inMemory/InMemoryStorage.js +3 -1
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -1
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +6 -0
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +6 -0
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +161 -0
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +26 -0
- package/esm/storages/inRedis/index.js +2 -4
- package/esm/storages/pluggable/TelemetryCachePluggable.js +24 -0
- package/esm/storages/pluggable/index.js +2 -1
- package/esm/sync/polling/pollingManagerCS.js +1 -1
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +2 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +0 -3
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -8
- package/esm/sync/polling/updaters/splitChangesUpdater.js +3 -6
- package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +8 -1
- package/esm/sync/streaming/SSEHandler/index.js +21 -15
- package/esm/sync/streaming/pushManager.js +7 -4
- package/esm/sync/submitters/eventsSubmitter.js +24 -0
- package/esm/sync/submitters/{impressionCountsSyncTask.js → impressionCountsSubmitter.js} +8 -5
- package/esm/sync/submitters/{impressionsSyncTask.js → impressionsSubmitter.js} +6 -6
- package/esm/sync/submitters/submitter.js +61 -0
- package/esm/sync/submitters/submitterManager.js +12 -10
- package/esm/sync/submitters/telemetrySubmitter.js +122 -0
- package/esm/sync/syncManagerOnline.js +6 -2
- package/esm/trackers/eventTracker.js +6 -2
- package/esm/trackers/impressionsTracker.js +10 -2
- package/esm/trackers/telemetryTracker.js +61 -0
- package/esm/utils/constants/index.js +38 -0
- package/esm/utils/inputValidation/apiKey.js +2 -1
- package/esm/utils/settingsValidation/index.js +34 -10
- package/esm/utils/settingsValidation/url.js +4 -0
- package/esm/utils/timeTracker/index.js +1 -0
- package/esm/utils/timeTracker/timer.js +2 -2
- package/package.json +1 -1
- package/src/consent/sdkUserConsent.ts +1 -1
- package/src/listeners/browser.ts +3 -2
- package/src/logger/constants.ts +1 -0
- package/src/logger/messages/error.ts +2 -1
- package/src/logger/messages/info.ts +3 -3
- package/src/logger/messages/warn.ts +2 -2
- package/src/sdkClient/client.ts +23 -4
- package/src/sdkClient/sdkClient.ts +4 -1
- package/src/sdkFactory/index.ts +22 -24
- package/src/sdkFactory/types.ts +32 -15
- package/src/services/splitApi.ts +17 -14
- package/src/services/splitHttpClient.ts +6 -3
- package/src/services/types.ts +7 -5
- package/src/storages/AbstractSegmentsCacheSync.ts +8 -3
- package/src/storages/KeyBuilderSS.ts +13 -50
- package/src/storages/findLatencyIndex.ts +12 -3
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +13 -1
- package/src/storages/inLocalStorage/index.ts +5 -2
- package/src/storages/inMemory/InMemoryStorage.ts +3 -1
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -1
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +8 -0
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +6 -0
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +210 -0
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +29 -0
- package/src/storages/inRedis/index.ts +2 -4
- package/src/storages/pluggable/TelemetryCachePluggable.ts +26 -0
- package/src/storages/pluggable/index.ts +2 -1
- package/src/storages/types.ts +84 -32
- package/src/sync/offline/syncManagerOffline.ts +4 -3
- package/src/sync/polling/pollingManagerCS.ts +3 -3
- package/src/sync/polling/pollingManagerSS.ts +2 -2
- package/src/sync/polling/syncTasks/splitsSyncTask.ts +2 -0
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +0 -4
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +2 -10
- package/src/sync/polling/updaters/splitChangesUpdater.ts +3 -6
- package/src/sync/streaming/SSEHandler/NotificationKeeper.ts +11 -1
- package/src/sync/streaming/SSEHandler/index.ts +21 -14
- package/src/sync/streaming/pushManager.ts +11 -7
- package/src/sync/submitters/eventsSubmitter.ts +35 -0
- package/src/sync/submitters/{impressionCountsSyncTask.ts → impressionCountsSubmitter.ts} +15 -15
- package/src/sync/submitters/{impressionsSyncTask.ts → impressionsSubmitter.ts} +12 -16
- package/src/sync/submitters/{submitterSyncTask.ts → submitter.ts} +34 -16
- package/src/sync/submitters/submitterManager.ts +14 -11
- package/src/sync/submitters/telemetrySubmitter.ts +143 -0
- package/src/sync/submitters/types.ts +123 -0
- package/src/sync/syncManagerOnline.ts +13 -7
- package/src/sync/types.ts +0 -15
- package/src/trackers/eventTracker.ts +7 -3
- package/src/trackers/impressionsTracker.ts +11 -3
- package/src/trackers/telemetryTracker.ts +63 -0
- package/src/trackers/types.ts +24 -0
- package/src/types.ts +35 -6
- package/src/utils/constants/index.ts +45 -0
- package/src/utils/inputValidation/apiKey.ts +2 -1
- package/src/utils/settingsValidation/index.ts +35 -11
- package/src/utils/settingsValidation/url.ts +4 -0
- package/src/utils/timeTracker/index.ts +1 -1
- package/src/utils/timeTracker/timer.ts +3 -3
- package/types/logger/constants.d.ts +1 -0
- package/types/sdkFactory/types.d.ts +29 -14
- package/types/services/splitApi.d.ts +2 -1
- package/types/services/types.d.ts +8 -5
- package/types/storages/AbstractSegmentsCacheSync.d.ts +7 -3
- package/types/storages/KeyBuilderSS.d.ts +3 -3
- package/types/storages/findLatencyIndex.d.ts +7 -1
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +2 -0
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +2 -0
- package/types/storages/inMemory/SegmentsCacheInMemory.d.ts +1 -0
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -2
- package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +3 -3
- package/types/storages/pluggable/TelemetryCachePluggable.d.ts +2 -2
- package/types/storages/types.d.ts +71 -22
- package/types/sync/offline/syncManagerOffline.d.ts +3 -2
- package/types/sync/polling/pollingManagerCS.d.ts +2 -2
- package/types/sync/polling/pollingManagerSS.d.ts +2 -2
- package/types/sync/polling/syncTasks/splitsSyncTask.d.ts +1 -1
- package/types/sync/polling/updaters/splitChangesUpdater.d.ts +1 -1
- package/types/sync/streaming/SSEHandler/NotificationKeeper.d.ts +2 -1
- package/types/sync/streaming/SSEHandler/index.d.ts +2 -1
- package/types/sync/streaming/pushManager.d.ts +2 -2
- package/types/sync/submitters/eventsSubmitter.d.ts +5 -0
- package/types/sync/submitters/impressionCountsSubmitter.d.ts +10 -0
- package/types/sync/submitters/impressionsSubmitter.d.ts +11 -0
- package/types/sync/submitters/submitter.d.ts +12 -0
- package/types/sync/submitters/submitterManager.d.ts +2 -2
- package/types/sync/submitters/telemetrySubmitter.d.ts +24 -0
- package/types/sync/submitters/telemetrySyncTask.d.ts +0 -27
- package/types/sync/submitters/types.d.ts +107 -0
- package/types/sync/syncManagerOnline.d.ts +3 -2
- package/types/sync/types.d.ts +0 -13
- package/types/trackers/eventTracker.d.ts +2 -2
- package/types/trackers/impressionsTracker.d.ts +2 -2
- package/types/trackers/telemetryTracker.d.ts +2 -3
- package/types/trackers/types.d.ts +22 -0
- package/types/types.d.ts +33 -4
- package/types/utils/constants/index.d.ts +37 -0
- package/types/utils/inputValidation/apiKey.d.ts +1 -0
- package/types/utils/settingsValidation/index.d.ts +40 -0
- package/types/utils/timeTracker/index.d.ts +1 -1
- package/types/utils/timeTracker/timer.d.ts +1 -1
- package/cjs/storages/inMemory/CountsCacheInMemory.js +0 -38
- package/cjs/storages/inMemory/LatenciesCacheInMemory.js +0 -43
- package/cjs/storages/inRedis/CountsCacheInRedis.js +0 -16
- package/cjs/storages/inRedis/LatenciesCacheInRedis.js +0 -18
- package/cjs/sync/submitters/eventsSyncTask.js +0 -44
- package/cjs/sync/submitters/metricsSyncTask.js +0 -31
- package/cjs/sync/submitters/submitterSyncTask.js +0 -44
- package/esm/storages/inMemory/CountsCacheInMemory.js +0 -35
- package/esm/storages/inMemory/LatenciesCacheInMemory.js +0 -40
- package/esm/storages/inRedis/CountsCacheInRedis.js +0 -13
- package/esm/storages/inRedis/LatenciesCacheInRedis.js +0 -15
- package/esm/sync/submitters/eventsSyncTask.js +0 -40
- package/esm/sync/submitters/metricsSyncTask.js +0 -26
- package/esm/sync/submitters/submitterSyncTask.js +0 -40
- package/src/storages/inMemory/CountsCacheInMemory.ts +0 -37
- package/src/storages/inMemory/LatenciesCacheInMemory.ts +0 -45
- package/src/storages/inRedis/CountsCacheInRedis.ts +0 -20
- package/src/storages/inRedis/LatenciesCacheInRedis.ts +0 -23
- package/src/sync/submitters/eventsSyncTask.ts +0 -57
- package/src/sync/submitters/metricsSyncTask.ts +0 -49
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TelemetryCacheInMemory = exports.shouldRecordTelemetry = void 0;
|
|
4
|
+
var findLatencyIndex_1 = require("../findLatencyIndex");
|
|
5
|
+
var MAX_STREAMING_EVENTS = 20;
|
|
6
|
+
var MAX_TAGS = 10;
|
|
7
|
+
function newBuckets() {
|
|
8
|
+
// MAX_LATENCY_BUCKET_COUNT (length) is 23;
|
|
9
|
+
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
10
|
+
}
|
|
11
|
+
var ACCEPTANCE_RANGE = 0.001;
|
|
12
|
+
/**
|
|
13
|
+
* Used on client-side. 0.1% of instances will track telemetry
|
|
14
|
+
*/
|
|
15
|
+
function shouldRecordTelemetry() {
|
|
16
|
+
return Math.random() <= ACCEPTANCE_RANGE;
|
|
17
|
+
}
|
|
18
|
+
exports.shouldRecordTelemetry = shouldRecordTelemetry;
|
|
19
|
+
var TelemetryCacheInMemory = /** @class */ (function () {
|
|
20
|
+
function TelemetryCacheInMemory() {
|
|
21
|
+
this.notReadyUsage = 0;
|
|
22
|
+
this.impressionStats = [0, 0, 0];
|
|
23
|
+
this.eventStats = [0, 0];
|
|
24
|
+
// @ts-expect-error
|
|
25
|
+
this.lastSync = {};
|
|
26
|
+
// @ts-expect-error
|
|
27
|
+
this.httpErrors = {};
|
|
28
|
+
// @ts-expect-error
|
|
29
|
+
this.httpLatencies = {};
|
|
30
|
+
this.authRejections = 0;
|
|
31
|
+
this.tokenRefreshes = 0;
|
|
32
|
+
this.streamingEvents = [];
|
|
33
|
+
this.tags = [];
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
this.exceptions = {};
|
|
36
|
+
// @ts-expect-error
|
|
37
|
+
this.latencies = {};
|
|
38
|
+
}
|
|
39
|
+
TelemetryCacheInMemory.prototype.getTimeUntilReady = function () {
|
|
40
|
+
return this.timeUntilReady;
|
|
41
|
+
};
|
|
42
|
+
TelemetryCacheInMemory.prototype.recordTimeUntilReady = function (ms) {
|
|
43
|
+
this.timeUntilReady = ms;
|
|
44
|
+
};
|
|
45
|
+
TelemetryCacheInMemory.prototype.getTimeUntilReadyFromCache = function () {
|
|
46
|
+
return this.timeUntilReadyFromCache;
|
|
47
|
+
};
|
|
48
|
+
TelemetryCacheInMemory.prototype.recordTimeUntilReadyFromCache = function (ms) {
|
|
49
|
+
this.timeUntilReadyFromCache = ms;
|
|
50
|
+
};
|
|
51
|
+
TelemetryCacheInMemory.prototype.getNonReadyUsage = function () {
|
|
52
|
+
return this.notReadyUsage;
|
|
53
|
+
};
|
|
54
|
+
TelemetryCacheInMemory.prototype.recordNonReadyUsage = function () {
|
|
55
|
+
this.notReadyUsage++;
|
|
56
|
+
};
|
|
57
|
+
TelemetryCacheInMemory.prototype.getImpressionStats = function (type) {
|
|
58
|
+
return this.impressionStats[type];
|
|
59
|
+
};
|
|
60
|
+
TelemetryCacheInMemory.prototype.recordImpressionStats = function (type, count) {
|
|
61
|
+
this.impressionStats[type] += count;
|
|
62
|
+
};
|
|
63
|
+
TelemetryCacheInMemory.prototype.getEventStats = function (type) {
|
|
64
|
+
return this.eventStats[type];
|
|
65
|
+
};
|
|
66
|
+
TelemetryCacheInMemory.prototype.recordEventStats = function (type, count) {
|
|
67
|
+
this.eventStats[type] += count;
|
|
68
|
+
};
|
|
69
|
+
TelemetryCacheInMemory.prototype.getLastSynchronization = function () {
|
|
70
|
+
return this.lastSync;
|
|
71
|
+
};
|
|
72
|
+
TelemetryCacheInMemory.prototype.recordSuccessfulSync = function (resource, timeMs) {
|
|
73
|
+
this.lastSync[resource] = timeMs;
|
|
74
|
+
};
|
|
75
|
+
TelemetryCacheInMemory.prototype.popHttpErrors = function () {
|
|
76
|
+
var result = this.httpErrors; // @ts-expect-error
|
|
77
|
+
this.httpErrors = {};
|
|
78
|
+
return result;
|
|
79
|
+
};
|
|
80
|
+
TelemetryCacheInMemory.prototype.recordHttpError = function (resource, status) {
|
|
81
|
+
if (!this.httpErrors[resource])
|
|
82
|
+
this.httpErrors[resource] = {};
|
|
83
|
+
if (!this.httpErrors[resource][status]) {
|
|
84
|
+
this.httpErrors[resource][status] = 1;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.httpErrors[resource][status]++;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
TelemetryCacheInMemory.prototype.popHttpLatencies = function () {
|
|
91
|
+
var result = this.httpLatencies; // @ts-expect-error
|
|
92
|
+
this.httpLatencies = {};
|
|
93
|
+
return result;
|
|
94
|
+
};
|
|
95
|
+
TelemetryCacheInMemory.prototype.recordHttpLatency = function (resource, latencyMs) {
|
|
96
|
+
if (!this.httpLatencies[resource]) {
|
|
97
|
+
this.httpLatencies[resource] = newBuckets();
|
|
98
|
+
}
|
|
99
|
+
this.httpLatencies[resource][(0, findLatencyIndex_1.findLatencyIndex)(latencyMs)]++;
|
|
100
|
+
};
|
|
101
|
+
TelemetryCacheInMemory.prototype.popAuthRejections = function () {
|
|
102
|
+
var result = this.authRejections;
|
|
103
|
+
this.authRejections = 0;
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
TelemetryCacheInMemory.prototype.recordAuthRejections = function () {
|
|
107
|
+
this.authRejections++;
|
|
108
|
+
};
|
|
109
|
+
TelemetryCacheInMemory.prototype.popTokenRefreshes = function () {
|
|
110
|
+
var result = this.tokenRefreshes;
|
|
111
|
+
this.tokenRefreshes = 0;
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
TelemetryCacheInMemory.prototype.recordTokenRefreshes = function () {
|
|
115
|
+
this.tokenRefreshes++;
|
|
116
|
+
};
|
|
117
|
+
TelemetryCacheInMemory.prototype.popStreamingEvents = function () {
|
|
118
|
+
return this.streamingEvents.splice(0);
|
|
119
|
+
};
|
|
120
|
+
TelemetryCacheInMemory.prototype.recordStreamingEvents = function (streamingEvent) {
|
|
121
|
+
if (this.streamingEvents.length < MAX_STREAMING_EVENTS) {
|
|
122
|
+
this.streamingEvents.push(streamingEvent);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
TelemetryCacheInMemory.prototype.popTags = function () {
|
|
126
|
+
return this.tags.splice(0);
|
|
127
|
+
};
|
|
128
|
+
TelemetryCacheInMemory.prototype.addTag = function (tag) {
|
|
129
|
+
if (this.tags.length < MAX_TAGS) {
|
|
130
|
+
this.tags.push(tag);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
TelemetryCacheInMemory.prototype.getSessionLength = function () {
|
|
134
|
+
return this.sessionLength;
|
|
135
|
+
};
|
|
136
|
+
TelemetryCacheInMemory.prototype.recordSessionLength = function (ms) {
|
|
137
|
+
this.sessionLength = ms;
|
|
138
|
+
};
|
|
139
|
+
TelemetryCacheInMemory.prototype.popExceptions = function () {
|
|
140
|
+
var result = this.exceptions; // @ts-expect-error
|
|
141
|
+
this.exceptions = {};
|
|
142
|
+
return result;
|
|
143
|
+
};
|
|
144
|
+
TelemetryCacheInMemory.prototype.recordException = function (method) {
|
|
145
|
+
if (!this.exceptions[method]) {
|
|
146
|
+
this.exceptions[method] = 1;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
this.exceptions[method]++;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
TelemetryCacheInMemory.prototype.popLatencies = function () {
|
|
153
|
+
var result = this.latencies; // @ts-expect-error
|
|
154
|
+
this.latencies = {};
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
TelemetryCacheInMemory.prototype.recordLatency = function (method, latencyMs) {
|
|
158
|
+
if (!this.latencies[method]) {
|
|
159
|
+
this.latencies[method] = newBuckets();
|
|
160
|
+
}
|
|
161
|
+
this.latencies[method][(0, findLatencyIndex_1.findLatencyIndex)(latencyMs)]++;
|
|
162
|
+
};
|
|
163
|
+
return TelemetryCacheInMemory;
|
|
164
|
+
}());
|
|
165
|
+
exports.TelemetryCacheInMemory = TelemetryCacheInMemory;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TelemetryCacheInRedis = void 0;
|
|
4
|
+
var findLatencyIndex_1 = require("../findLatencyIndex");
|
|
5
|
+
var TelemetryCacheInRedis = /** @class */ (function () {
|
|
6
|
+
/**
|
|
7
|
+
* Create a Telemetry cache that uses Redis as storage.
|
|
8
|
+
* @param log Logger instance.
|
|
9
|
+
* @param keys Key builder.
|
|
10
|
+
* @param redis Redis client.
|
|
11
|
+
*/
|
|
12
|
+
function TelemetryCacheInRedis(log, keys, redis) {
|
|
13
|
+
this.log = log;
|
|
14
|
+
this.keys = keys;
|
|
15
|
+
this.redis = redis;
|
|
16
|
+
}
|
|
17
|
+
TelemetryCacheInRedis.prototype.recordLatency = function (method, latencyMs) {
|
|
18
|
+
var _a = this.keys.buildLatencyKey(method, (0, findLatencyIndex_1.findLatencyIndex)(latencyMs)).split('::'), key = _a[0], field = _a[1];
|
|
19
|
+
return this.redis.hincrby(key, field, 1)
|
|
20
|
+
.catch(function () { });
|
|
21
|
+
};
|
|
22
|
+
TelemetryCacheInRedis.prototype.recordException = function (method) {
|
|
23
|
+
var _a = this.keys.buildExceptionKey(method).split('::'), key = _a[0], field = _a[1];
|
|
24
|
+
return this.redis.hincrby(key, field, 1)
|
|
25
|
+
.catch(function () { });
|
|
26
|
+
};
|
|
27
|
+
return TelemetryCacheInRedis;
|
|
28
|
+
}());
|
|
29
|
+
exports.TelemetryCacheInRedis = TelemetryCacheInRedis;
|
|
@@ -8,9 +8,8 @@ var SplitsCacheInRedis_1 = require("./SplitsCacheInRedis");
|
|
|
8
8
|
var SegmentsCacheInRedis_1 = require("./SegmentsCacheInRedis");
|
|
9
9
|
var ImpressionsCacheInRedis_1 = require("./ImpressionsCacheInRedis");
|
|
10
10
|
var EventsCacheInRedis_1 = require("./EventsCacheInRedis");
|
|
11
|
-
var LatenciesCacheInRedis_1 = require("./LatenciesCacheInRedis");
|
|
12
|
-
var CountsCacheInRedis_1 = require("./CountsCacheInRedis");
|
|
13
11
|
var constants_1 = require("../../utils/constants");
|
|
12
|
+
var TelemetryCacheInRedis_1 = require("./TelemetryCacheInRedis");
|
|
14
13
|
/**
|
|
15
14
|
* InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.
|
|
16
15
|
* @see {@link https://www.npmjs.com/package/ioredis}
|
|
@@ -31,8 +30,7 @@ function InRedisStorage(options) {
|
|
|
31
30
|
segments: new SegmentsCacheInRedis_1.SegmentsCacheInRedis(log, keys, redisClient),
|
|
32
31
|
impressions: new ImpressionsCacheInRedis_1.ImpressionsCacheInRedis(log, keys.buildImpressionsKey(), redisClient, metadata),
|
|
33
32
|
events: new EventsCacheInRedis_1.EventsCacheInRedis(log, keys.buildEventsKey(), redisClient, metadata),
|
|
34
|
-
|
|
35
|
-
counts: new CountsCacheInRedis_1.CountsCacheInRedis(keys, redisClient),
|
|
33
|
+
telemetry: new TelemetryCacheInRedis_1.TelemetryCacheInRedis(log, keys, redisClient),
|
|
36
34
|
// When using REDIS we should:
|
|
37
35
|
// 1- Disconnect from the storage
|
|
38
36
|
destroy: function () {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TelemetryCachePluggable = void 0;
|
|
4
|
+
var findLatencyIndex_1 = require("../findLatencyIndex");
|
|
5
|
+
var TelemetryCachePluggable = /** @class */ (function () {
|
|
6
|
+
/**
|
|
7
|
+
* Create a Telemetry cache that uses a storage wrapper.
|
|
8
|
+
* @param log Logger instance.
|
|
9
|
+
* @param keys Key builder.
|
|
10
|
+
* @param wrapper Adapted wrapper storage.
|
|
11
|
+
*/
|
|
12
|
+
function TelemetryCachePluggable(log, keys, wrapper) {
|
|
13
|
+
this.log = log;
|
|
14
|
+
this.keys = keys;
|
|
15
|
+
this.wrapper = wrapper;
|
|
16
|
+
}
|
|
17
|
+
TelemetryCachePluggable.prototype.recordLatency = function (method, latencyMs) {
|
|
18
|
+
return this.wrapper.incr(this.keys.buildLatencyKey(method, (0, findLatencyIndex_1.findLatencyIndex)(latencyMs)))
|
|
19
|
+
.catch(function () { });
|
|
20
|
+
};
|
|
21
|
+
TelemetryCachePluggable.prototype.recordException = function (method) {
|
|
22
|
+
return this.wrapper.incr(this.keys.buildExceptionKey(method))
|
|
23
|
+
.catch(function () { });
|
|
24
|
+
};
|
|
25
|
+
return TelemetryCachePluggable;
|
|
26
|
+
}());
|
|
27
|
+
exports.TelemetryCachePluggable = TelemetryCachePluggable;
|
|
@@ -66,7 +66,8 @@ function PluggableStorage(options) {
|
|
|
66
66
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable_1.ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
67
67
|
impressionCounts: optimize ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : undefined,
|
|
68
68
|
events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory_1.EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable_1.EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
|
|
69
|
-
// @TODO
|
|
69
|
+
// @TODO Not using TelemetryCachePluggable yet, because it is not supported by the Split Synchronizer
|
|
70
|
+
// telemetry: isPartialConsumer ? new TelemetryCacheInMemory() : new TelemetryCachePluggable(log, keys, wrapper),
|
|
70
71
|
// Disconnect the underlying storage
|
|
71
72
|
destroy: function () {
|
|
72
73
|
return wrapper.disconnect();
|
|
@@ -14,7 +14,7 @@ var constants_2 = require("../../logger/constants");
|
|
|
14
14
|
function pollingManagerCSFactory(params) {
|
|
15
15
|
var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
16
16
|
var log = settings.log;
|
|
17
|
-
var splitsSyncTask = (0, splitsSyncTask_1.splitsSyncTaskFactory)(splitApi.fetchSplitChanges, storage, readiness, settings);
|
|
17
|
+
var splitsSyncTask = (0, splitsSyncTask_1.splitsSyncTaskFactory)(splitApi.fetchSplitChanges, storage, readiness, settings, true);
|
|
18
18
|
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
19
19
|
var mySegmentsSyncTasks = {};
|
|
20
20
|
var matchingKey = (0, key_1.getMatching)(settings.core.key);
|
|
@@ -7,7 +7,7 @@ var splitChangesUpdater_1 = require("../updaters/splitChangesUpdater");
|
|
|
7
7
|
/**
|
|
8
8
|
* Creates a sync task that periodically executes a `splitChangesUpdater` task
|
|
9
9
|
*/
|
|
10
|
-
function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings) {
|
|
11
|
-
return (0, syncTask_1.syncTaskFactory)(settings.log, (0, splitChangesUpdater_1.splitChangesUpdaterFactory)(settings.log, (0, splitChangesFetcher_1.splitChangesFetcherFactory)(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
|
|
10
|
+
function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
|
|
11
|
+
return (0, syncTask_1.syncTaskFactory)(settings.log, (0, splitChangesUpdater_1.splitChangesUpdaterFactory)(settings.log, (0, splitChangesFetcher_1.splitChangesFetcherFactory)(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
|
|
12
12
|
}
|
|
13
13
|
exports.splitsSyncTaskFactory = splitsSyncTaskFactory;
|
|
@@ -18,9 +18,6 @@ function mySegmentsUpdaterFactory(log, mySegmentsFetcher, splitsCache, mySegment
|
|
|
18
18
|
if (startingUp)
|
|
19
19
|
promise = (0, timeout_1.timeout)(requestTimeoutBeforeReady, promise);
|
|
20
20
|
return promise;
|
|
21
|
-
// @TODO telemetry
|
|
22
|
-
// NOTE: We only collect metrics on startup.
|
|
23
|
-
// mySegmentsPromise = tracker.start(tracker.TaskNames.MY_SEGMENTS_FETCH, startingUp ? metricCollectors : false, mySegmentsPromise);
|
|
24
21
|
}
|
|
25
22
|
// @TODO if allowing pluggable storages, handle async execution
|
|
26
23
|
function updateSegments(segmentsData) {
|
|
@@ -18,13 +18,6 @@ var thenable_1 = require("../../../utils/promise/thenable");
|
|
|
18
18
|
*/
|
|
19
19
|
function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, readiness) {
|
|
20
20
|
var readyOnAlreadyExistentState = true;
|
|
21
|
-
/** telemetry decorator for `segmentChangesFetcher` promise */
|
|
22
|
-
function _promiseDecorator(promise) {
|
|
23
|
-
return promise;
|
|
24
|
-
// @TODO handle telemetry?
|
|
25
|
-
// const collectMetrics = startingUp || isNode; // If we are on the browser, only collect this metric for first fetch. On node do it always.
|
|
26
|
-
// splitsPromise = tracker.start(tracker.TaskNames.SPLITS_FETCH, collectMetrics ? metricCollectors : false, splitsPromise);
|
|
27
|
-
}
|
|
28
21
|
/**
|
|
29
22
|
* Segments updater returns a promise that resolves with a `false` boolean value if it fails at least to fetch a segment or synchronize it with the storage.
|
|
30
23
|
* Thus, a false result doesn't imply that SDK_SEGMENTS_ARRIVED was not emitted.
|
|
@@ -50,7 +43,7 @@ function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, read
|
|
|
50
43
|
// if fetchOnlyNew flag, avoid processing already fetched segments
|
|
51
44
|
if (fetchOnlyNew && since !== -1)
|
|
52
45
|
return -1;
|
|
53
|
-
return segmentChangesFetcher(since, segmentName, noCache
|
|
46
|
+
return segmentChangesFetcher(since, segmentName, noCache).then(function (changes) {
|
|
54
47
|
var changeNumber = -1;
|
|
55
48
|
var results = [];
|
|
56
49
|
changes.forEach(function (x) {
|
|
@@ -69,18 +69,15 @@ exports.computeSplitsMutation = computeSplitsMutation;
|
|
|
69
69
|
* @param requestTimeoutBeforeReady How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
|
|
70
70
|
* @param retriesOnFailureBeforeReady How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
|
|
71
71
|
*/
|
|
72
|
-
function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady) {
|
|
72
|
+
function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
|
|
73
73
|
if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
|
|
74
74
|
if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
|
|
75
75
|
var startingUp = true;
|
|
76
|
-
/** timeout
|
|
76
|
+
/** timeout decorator for `splitChangesFetcher` promise */
|
|
77
77
|
function _promiseDecorator(promise) {
|
|
78
78
|
if (startingUp && requestTimeoutBeforeReady)
|
|
79
79
|
promise = (0, timeout_1.timeout)(requestTimeoutBeforeReady, promise);
|
|
80
80
|
return promise;
|
|
81
|
-
// @TODO telemetry
|
|
82
|
-
// const collectMetrics = startingUp || isNode; // If we are on the browser, only collect this metric for first fetch. On node do it always.
|
|
83
|
-
// splitsPromise = tracker.start(tracker.TaskNames.SPLITS_FETCH, collectMetrics ? metricCollectors : false, splitsPromise);
|
|
84
81
|
}
|
|
85
82
|
/**
|
|
86
83
|
* SplitChanges updater returns a promise that resolves with a `false` boolean value if it fails to fetch splits or synchronize them with the storage.
|
|
@@ -114,7 +111,7 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
|
|
|
114
111
|
]).then(function () {
|
|
115
112
|
if (splitsEventEmitter) {
|
|
116
113
|
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
117
|
-
return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && checkAllSegmentsExist(segments)))
|
|
114
|
+
return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && (isClientSide || checkAllSegmentsExist(segments))))
|
|
118
115
|
.catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
|
|
119
116
|
.then(function (emitSplitsArrivedEvent) {
|
|
120
117
|
// emit SDK events
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.notificationKeeperFactory = void 0;
|
|
4
|
-
var constants_1 = require("
|
|
4
|
+
var constants_1 = require("../../../utils/constants");
|
|
5
|
+
var constants_2 = require("../constants");
|
|
5
6
|
var CONTROL_CHANNEL_REGEXS = [/control_pri$/, /control_sec$/];
|
|
7
|
+
var STREAMING_EVENT_TYPES = [constants_1.OCCUPANCY_PRI, constants_1.OCCUPANCY_SEC];
|
|
6
8
|
/**
|
|
7
9
|
* Factory of notification keeper, which process OCCUPANCY and CONTROL notifications and emits the corresponding push events.
|
|
8
10
|
*
|
|
9
11
|
* @param pushEmitter emitter for events related to streaming support
|
|
10
12
|
*/
|
|
11
13
|
// @TODO update logic to handle OCCUPANCY for any region and rename according to new spec (e.g.: PUSH_SUBSYSTEM_UP --> PUSH_SUBSYSTEM_UP)
|
|
12
|
-
function notificationKeeperFactory(pushEmitter) {
|
|
14
|
+
function notificationKeeperFactory(pushEmitter, telemetryTracker) {
|
|
13
15
|
var channels = CONTROL_CHANNEL_REGEXS.map(function (regex) { return ({
|
|
14
16
|
regex: regex,
|
|
15
17
|
hasPublishers: true,
|
|
@@ -25,7 +27,8 @@ function notificationKeeperFactory(pushEmitter) {
|
|
|
25
27
|
}
|
|
26
28
|
return {
|
|
27
29
|
handleOpen: function () {
|
|
28
|
-
|
|
30
|
+
telemetryTracker.streamingEvent(constants_1.CONNECTION_ESTABLISHED);
|
|
31
|
+
pushEmitter.emit(constants_2.PUSH_SUBSYSTEM_UP);
|
|
29
32
|
},
|
|
30
33
|
isStreamingUp: function () {
|
|
31
34
|
return hasResumed && hasPublishers;
|
|
@@ -34,16 +37,17 @@ function notificationKeeperFactory(pushEmitter) {
|
|
|
34
37
|
for (var i = 0; i < channels.length; i++) {
|
|
35
38
|
var c = channels[i];
|
|
36
39
|
if (c.regex.test(channel)) {
|
|
40
|
+
telemetryTracker.streamingEvent(STREAMING_EVENT_TYPES[i], publishers);
|
|
37
41
|
if (timestamp > c.oTime) {
|
|
38
42
|
c.oTime = timestamp;
|
|
39
43
|
c.hasPublishers = publishers !== 0;
|
|
40
44
|
var hasPublishersNow = getHasPublishers();
|
|
41
45
|
if (hasResumed) {
|
|
42
46
|
if (!hasPublishersNow && hasPublishers) {
|
|
43
|
-
pushEmitter.emit(
|
|
47
|
+
pushEmitter.emit(constants_2.PUSH_SUBSYSTEM_DOWN);
|
|
44
48
|
}
|
|
45
49
|
else if (hasPublishersNow && !hasPublishers) {
|
|
46
|
-
pushEmitter.emit(
|
|
50
|
+
pushEmitter.emit(constants_2.PUSH_SUBSYSTEM_UP);
|
|
47
51
|
}
|
|
48
52
|
// nothing to do when hasResumed === false:
|
|
49
53
|
// streaming is already down for `!hasPublishersNow`, and cannot be up for `hasPublishersNow`
|
|
@@ -58,7 +62,7 @@ function notificationKeeperFactory(pushEmitter) {
|
|
|
58
62
|
/* STREAMING_RESET control event is handled by PushManager directly since it doesn't require
|
|
59
63
|
* tracking timestamp and state like OCCUPANCY or CONTROL. It also ignores previous
|
|
60
64
|
* OCCUPANCY and CONTROL notifications, and whether PUSH_SUBSYSTEM_DOWN has been emitted or not */
|
|
61
|
-
if (controlType ===
|
|
65
|
+
if (controlType === constants_2.ControlType.STREAMING_RESET) {
|
|
62
66
|
pushEmitter.emit(controlType);
|
|
63
67
|
return;
|
|
64
68
|
}
|
|
@@ -67,20 +71,23 @@ function notificationKeeperFactory(pushEmitter) {
|
|
|
67
71
|
if (c.regex.test(channel)) {
|
|
68
72
|
if (timestamp > c.cTime) {
|
|
69
73
|
c.cTime = timestamp;
|
|
70
|
-
if (controlType ===
|
|
71
|
-
|
|
74
|
+
if (controlType === constants_2.ControlType.STREAMING_DISABLED) {
|
|
75
|
+
telemetryTracker.streamingEvent(constants_1.STREAMING_STATUS, constants_1.DISABLED);
|
|
76
|
+
pushEmitter.emit(constants_2.PUSH_NONRETRYABLE_ERROR);
|
|
72
77
|
}
|
|
73
78
|
else if (hasPublishers) {
|
|
74
|
-
if (controlType ===
|
|
75
|
-
|
|
79
|
+
if (controlType === constants_2.ControlType.STREAMING_PAUSED && hasResumed) {
|
|
80
|
+
telemetryTracker.streamingEvent(constants_1.STREAMING_STATUS, constants_1.PAUSED);
|
|
81
|
+
pushEmitter.emit(constants_2.PUSH_SUBSYSTEM_DOWN);
|
|
76
82
|
}
|
|
77
|
-
else if (controlType ===
|
|
78
|
-
|
|
83
|
+
else if (controlType === constants_2.ControlType.STREAMING_RESUMED && !hasResumed) {
|
|
84
|
+
telemetryTracker.streamingEvent(constants_1.STREAMING_STATUS, constants_1.ENABLED);
|
|
85
|
+
pushEmitter.emit(constants_2.PUSH_SUBSYSTEM_UP);
|
|
79
86
|
}
|
|
80
87
|
// nothing to do when hasPublishers === false:
|
|
81
88
|
// streaming is already down for `STREAMING_PAUSED`, and cannot be up for `STREAMING_RESUMED`
|
|
82
89
|
}
|
|
83
|
-
hasResumed = controlType ===
|
|
90
|
+
hasResumed = controlType === constants_2.ControlType.STREAMING_RESUMED;
|
|
84
91
|
}
|
|
85
92
|
return;
|
|
86
93
|
}
|
|
@@ -5,27 +5,33 @@ var NotificationParser_1 = require("./NotificationParser");
|
|
|
5
5
|
var NotificationKeeper_1 = require("./NotificationKeeper");
|
|
6
6
|
var constants_1 = require("../constants");
|
|
7
7
|
var constants_2 = require("../../../logger/constants");
|
|
8
|
-
|
|
9
|
-
if (error.parsedData && error.parsedData.code) {
|
|
10
|
-
var code = error.parsedData.code;
|
|
11
|
-
// 401 errors due to invalid or expired token (e.g., if refresh token coudn't be executed)
|
|
12
|
-
if (40140 <= code && code <= 40149)
|
|
13
|
-
return true;
|
|
14
|
-
// Others 4XX errors (e.g., bad request from the SDK)
|
|
15
|
-
if (40000 <= code && code <= 49999)
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
// network errors or 5XX HTTP errors
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
8
|
+
var constants_3 = require("../../../utils/constants");
|
|
21
9
|
/**
|
|
22
10
|
* Factory for SSEHandler, which processes SSEClient messages and emits the corresponding push events.
|
|
23
11
|
*
|
|
24
12
|
* @param log factory logger
|
|
25
13
|
* @param pushEmitter emitter for events related to streaming support
|
|
26
14
|
*/
|
|
27
|
-
function SSEHandlerFactory(log, pushEmitter) {
|
|
28
|
-
var notificationKeeper = (0, NotificationKeeper_1.notificationKeeperFactory)(pushEmitter);
|
|
15
|
+
function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
|
|
16
|
+
var notificationKeeper = (0, NotificationKeeper_1.notificationKeeperFactory)(pushEmitter, telemetryTracker);
|
|
17
|
+
function isRetryableError(error) {
|
|
18
|
+
if (error.parsedData && error.parsedData.code) {
|
|
19
|
+
// Ably error
|
|
20
|
+
var code = error.parsedData.code;
|
|
21
|
+
telemetryTracker.streamingEvent(constants_3.ABLY_ERROR, code);
|
|
22
|
+
// 401 errors due to invalid or expired token (e.g., if refresh token coudn't be executed)
|
|
23
|
+
if (40140 <= code && code <= 40149)
|
|
24
|
+
return true;
|
|
25
|
+
// Others 4XX errors (e.g., bad request from the SDK)
|
|
26
|
+
if (40000 <= code && code <= 49999)
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// network errors or 5XX HTTP errors
|
|
31
|
+
telemetryTracker.streamingEvent(constants_3.SSE_CONNECTION_ERROR, constants_3.NON_REQUESTED);
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
29
35
|
return {
|
|
30
36
|
handleOpen: function () {
|
|
31
37
|
notificationKeeper.handleOpen();
|
|
@@ -17,13 +17,14 @@ var types_1 = require("./SSEHandler/types");
|
|
|
17
17
|
var mySegmentsV2utils_1 = require("./mySegmentsV2utils");
|
|
18
18
|
var sets_1 = require("../../utils/lang/sets");
|
|
19
19
|
var murmur3_64_1 = require("../../utils/murmur3/murmur3_64");
|
|
20
|
+
var constants_3 = require("../../utils/constants");
|
|
20
21
|
/**
|
|
21
22
|
* PushManager factory:
|
|
22
23
|
* - for server-side if key is not provided in settings.
|
|
23
24
|
* - for client-side, with support for multiple clients, if key is provided in settings
|
|
24
25
|
*/
|
|
25
26
|
function pushManagerFactory(params, pollingManager) {
|
|
26
|
-
var settings = params.settings, storage = params.storage, splitApi = params.splitApi, readiness = params.readiness, platform = params.platform;
|
|
27
|
+
var settings = params.settings, storage = params.storage, splitApi = params.splitApi, readiness = params.readiness, platform = params.platform, telemetryTracker = params.telemetryTracker;
|
|
27
28
|
// `userKey` is the matching key of main client in client-side SDK.
|
|
28
29
|
// It can be used to check if running on client-side or server-side SDK.
|
|
29
30
|
var userKey = settings.core.key ? (0, key_1.getMatching)(settings.core.key) : undefined;
|
|
@@ -40,7 +41,7 @@ function pushManagerFactory(params, pollingManager) {
|
|
|
40
41
|
var authenticate = (0, AuthClient_1.authenticateFactory)(splitApi.fetchAuth);
|
|
41
42
|
// init feedback loop
|
|
42
43
|
var pushEmitter = new platform.EventEmitter();
|
|
43
|
-
var sseHandler = (0, SSEHandler_1.SSEHandlerFactory)(log, pushEmitter);
|
|
44
|
+
var sseHandler = (0, SSEHandler_1.SSEHandlerFactory)(log, pushEmitter, telemetryTracker);
|
|
44
45
|
sseClient.setEventHandler(sseHandler);
|
|
45
46
|
// init workers
|
|
46
47
|
// MySegmentsUpdateWorker (client-side) are initiated in `add` method
|
|
@@ -83,6 +84,7 @@ function pushManagerFactory(params, pollingManager) {
|
|
|
83
84
|
return;
|
|
84
85
|
sseClient.open(authData);
|
|
85
86
|
}, connDelay * 1000);
|
|
87
|
+
telemetryTracker.streamingEvent(constants_3.TOKEN_REFRESH, decodedToken.exp);
|
|
86
88
|
}
|
|
87
89
|
function connectPush() {
|
|
88
90
|
// Guard condition in case `stop/disconnectPush` has been called (e.g., calling SDK destroy, or app signal close/background)
|
|
@@ -113,6 +115,7 @@ function pushManagerFactory(params, pollingManager) {
|
|
|
113
115
|
log.error(constants_2.ERROR_STREAMING_AUTH, [error.message]);
|
|
114
116
|
// Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side)
|
|
115
117
|
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
118
|
+
telemetryTracker.streamingEvent(constants_3.AUTH_REJECTION);
|
|
116
119
|
pushEmitter.emit(constants_1.PUSH_NONRETRYABLE_ERROR);
|
|
117
120
|
return;
|
|
118
121
|
}
|
|
@@ -153,14 +156,14 @@ function pushManagerFactory(params, pollingManager) {
|
|
|
153
156
|
connectPushRetryBackoff.reset();
|
|
154
157
|
stopWorkers();
|
|
155
158
|
});
|
|
156
|
-
/**
|
|
159
|
+
/** Fallback to polling without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
157
160
|
pushEmitter.on(constants_1.PUSH_NONRETRYABLE_ERROR, function handleNonRetryableError() {
|
|
158
161
|
disabled = true;
|
|
159
162
|
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
160
163
|
disconnectPush();
|
|
161
164
|
pushEmitter.emit(constants_1.PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
162
165
|
});
|
|
163
|
-
/**
|
|
166
|
+
/** Fallback to polling with retry due to recoverable SSE and Authentication errors */
|
|
164
167
|
pushEmitter.on(constants_1.PUSH_RETRYABLE_ERROR, function handleRetryableError() {
|
|
165
168
|
// SSE connection is closed to avoid repeated errors due to retries
|
|
166
169
|
sseClient.close();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventsSubmitterFactory = void 0;
|
|
4
|
+
var submitter_1 = require("./submitter");
|
|
5
|
+
var constants_1 = require("../../logger/constants");
|
|
6
|
+
var DATA_NAME = 'events';
|
|
7
|
+
/**
|
|
8
|
+
* Submitter that periodically posts tracked events
|
|
9
|
+
*/
|
|
10
|
+
function eventsSubmitterFactory(params) {
|
|
11
|
+
var _a = params.settings, log = _a.log, eventsPushRate = _a.scheduler.eventsPushRate, eventsFirstPushWindow = _a.startup.eventsFirstPushWindow, postEventsBulk = params.splitApi.postEventsBulk, events = params.storage.events;
|
|
12
|
+
// don't retry events.
|
|
13
|
+
var submitter = (0, submitter_1.submitterFactory)(log, postEventsBulk, events, eventsPushRate, DATA_NAME);
|
|
14
|
+
// Set a timer for the first push window of events.
|
|
15
|
+
if (eventsFirstPushWindow > 0)
|
|
16
|
+
submitter = (0, submitter_1.firstPushWindowDecorator)(submitter, eventsFirstPushWindow);
|
|
17
|
+
// register events submitter to be executed when events cache is full
|
|
18
|
+
events.setOnFullQueueCb(function () {
|
|
19
|
+
if (submitter.isRunning()) {
|
|
20
|
+
log.info(constants_1.SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
21
|
+
submitter.execute();
|
|
22
|
+
}
|
|
23
|
+
// If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
|
|
24
|
+
// Data will be sent when submitter is resumed.
|
|
25
|
+
});
|
|
26
|
+
return submitter;
|
|
27
|
+
}
|
|
28
|
+
exports.eventsSubmitterFactory = eventsSubmitterFactory;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
var
|
|
3
|
+
exports.impressionCountsSubmitterFactory = exports.fromImpressionCountsCollector = void 0;
|
|
4
|
+
var submitter_1 = require("./submitter");
|
|
5
5
|
/**
|
|
6
6
|
* Converts `impressionCounts` data from cache into request payload.
|
|
7
7
|
*/
|
|
@@ -26,10 +26,13 @@ function fromImpressionCountsCollector(impressionsCount) {
|
|
|
26
26
|
exports.fromImpressionCountsCollector = fromImpressionCountsCollector;
|
|
27
27
|
var IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Submitter that periodically posts impression counts
|
|
30
30
|
*/
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
function impressionCountsSubmitterFactory(params) {
|
|
32
|
+
var log = params.settings.log, postTestImpressionsCount = params.splitApi.postTestImpressionsCount, impressionCounts = params.storage.impressionCounts;
|
|
33
|
+
if (impressionCounts) {
|
|
34
|
+
// retry impressions counts only once.
|
|
35
|
+
return (0, submitter_1.submitterFactory)(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
|
|
36
|
+
}
|
|
34
37
|
}
|
|
35
|
-
exports.
|
|
38
|
+
exports.impressionCountsSubmitterFactory = impressionCountsSubmitterFactory;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.impressionsSubmitterFactory = exports.fromImpressionsCollector = void 0;
|
|
4
4
|
var lang_1 = require("../../utils/lang");
|
|
5
|
-
var
|
|
5
|
+
var submitter_1 = require("./submitter");
|
|
6
6
|
var constants_1 = require("../../logger/constants");
|
|
7
7
|
var DATA_NAME = 'impressions';
|
|
8
8
|
/**
|
|
@@ -33,14 +33,14 @@ function fromImpressionsCollector(sendLabels, data) {
|
|
|
33
33
|
}
|
|
34
34
|
exports.fromImpressionsCollector = fromImpressionsCollector;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Submitter that periodically posts impressions data
|
|
37
37
|
*/
|
|
38
|
-
function
|
|
39
|
-
|
|
38
|
+
function impressionsSubmitterFactory(params) {
|
|
39
|
+
var _a = params.settings, log = _a.log, impressionsRefreshRate = _a.scheduler.impressionsRefreshRate, labelsEnabled = _a.core.labelsEnabled, postTestImpressionsBulk = params.splitApi.postTestImpressionsBulk, impressions = params.storage.impressions;
|
|
40
40
|
// retry impressions only once.
|
|
41
|
-
var syncTask = (0,
|
|
41
|
+
var syncTask = (0, submitter_1.submitterFactory)(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, DATA_NAME, fromImpressionsCollector.bind(undefined, labelsEnabled), 1);
|
|
42
42
|
// register impressions submitter to be executed when impressions cache is full
|
|
43
|
-
|
|
43
|
+
impressions.setOnFullQueueCb(function () {
|
|
44
44
|
if (syncTask.isRunning()) {
|
|
45
45
|
log.info(constants_1.SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
46
46
|
syncTask.execute();
|
|
@@ -50,4 +50,4 @@ function impressionsSyncTaskFactory(log, postTestImpressionsBulk, impressionsCac
|
|
|
50
50
|
});
|
|
51
51
|
return syncTask;
|
|
52
52
|
}
|
|
53
|
-
exports.
|
|
53
|
+
exports.impressionsSubmitterFactory = impressionsSubmitterFactory;
|