@statsig/client-core 3.25.0-beta.1 → 3.25.1
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/package.json +1 -1
- package/src/DataAdapterCore.d.ts +1 -0
- package/src/DataAdapterCore.js +43 -21
- package/src/EventLogger.js +9 -0
- package/src/StatsigMetadata.d.ts +1 -1
- package/src/StatsigMetadata.js +1 -1
package/package.json
CHANGED
package/src/DataAdapterCore.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare abstract class DataAdapterCore {
|
|
|
9
9
|
private _sdkKey;
|
|
10
10
|
private _inMemoryCache;
|
|
11
11
|
private _lastModifiedStoreKey;
|
|
12
|
+
private _cacheLimit;
|
|
12
13
|
protected constructor(_adapterName: string, _cacheSuffix: string);
|
|
13
14
|
attach(sdkKey: string, options: AnyStatsigOptions | null, _network: NetworkCore | null): void;
|
|
14
15
|
getDataSync(user?: StatsigUser | undefined): DataAdapterResult | null;
|
package/src/DataAdapterCore.js
CHANGED
|
@@ -16,12 +16,14 @@ const StatsigUser_1 = require("./StatsigUser");
|
|
|
16
16
|
const StorageProvider_1 = require("./StorageProvider");
|
|
17
17
|
const TypedJsonParse_1 = require("./TypedJsonParse");
|
|
18
18
|
const CACHE_LIMIT = 10;
|
|
19
|
+
const MAX_CACHE_WRITE_ATTEMPTS = 8;
|
|
19
20
|
class DataAdapterCore {
|
|
20
21
|
constructor(_adapterName, _cacheSuffix) {
|
|
21
22
|
this._adapterName = _adapterName;
|
|
22
23
|
this._cacheSuffix = _cacheSuffix;
|
|
23
24
|
this._options = null;
|
|
24
25
|
this._sdkKey = null;
|
|
26
|
+
this._cacheLimit = CACHE_LIMIT;
|
|
25
27
|
this._lastModifiedStoreKey = `statsig.last_modified_time.${_cacheSuffix}`;
|
|
26
28
|
this._inMemoryCache = new InMemoryCache();
|
|
27
29
|
}
|
|
@@ -38,7 +40,7 @@ class DataAdapterCore {
|
|
|
38
40
|
}
|
|
39
41
|
const cache = this._loadFromCache(cacheKey);
|
|
40
42
|
if (cache && this._getIsCacheValueValid(cache)) {
|
|
41
|
-
this._inMemoryCache.add(cacheKey, cache);
|
|
43
|
+
this._inMemoryCache.add(cacheKey, cache, this._cacheLimit);
|
|
42
44
|
return this._inMemoryCache.get(cacheKey, normalized);
|
|
43
45
|
}
|
|
44
46
|
return null;
|
|
@@ -46,7 +48,7 @@ class DataAdapterCore {
|
|
|
46
48
|
setData(data, user) {
|
|
47
49
|
const normalized = user && (0, StatsigUser_1._normalizeUser)(user, this._options);
|
|
48
50
|
const cacheKey = this._getCacheKey(normalized);
|
|
49
|
-
this._inMemoryCache.add(cacheKey, _makeDataAdapterResult('Bootstrap', data, null, normalized));
|
|
51
|
+
this._inMemoryCache.add(cacheKey, _makeDataAdapterResult('Bootstrap', data, null, normalized), this._cacheLimit);
|
|
50
52
|
}
|
|
51
53
|
_getIsCacheValueValid(current) {
|
|
52
54
|
return (current.stableID == null ||
|
|
@@ -74,7 +76,7 @@ class DataAdapterCore {
|
|
|
74
76
|
const cacheKey = this._getCacheKey(normalized);
|
|
75
77
|
const result = yield this._getDataAsyncImpl(null, normalized, options);
|
|
76
78
|
if (result) {
|
|
77
|
-
this._inMemoryCache.add(cacheKey, Object.assign(Object.assign({}, result), { source: 'Prefetch' }));
|
|
79
|
+
this._inMemoryCache.add(cacheKey, Object.assign(Object.assign({}, result), { source: 'Prefetch' }), this._cacheLimit);
|
|
78
80
|
}
|
|
79
81
|
});
|
|
80
82
|
}
|
|
@@ -103,7 +105,7 @@ class DataAdapterCore {
|
|
|
103
105
|
return null;
|
|
104
106
|
}
|
|
105
107
|
const cacheKey = this._getCacheKey(user);
|
|
106
|
-
this._inMemoryCache.add(cacheKey, result);
|
|
108
|
+
this._inMemoryCache.add(cacheKey, result, this._cacheLimit);
|
|
107
109
|
this._writeToCache(cacheKey, result);
|
|
108
110
|
return result;
|
|
109
111
|
});
|
|
@@ -125,15 +127,30 @@ class DataAdapterCore {
|
|
|
125
127
|
return result ? Object.assign(Object.assign({}, result), { source: 'Cache' }) : null;
|
|
126
128
|
}
|
|
127
129
|
_writeToCache(cacheKey, result) {
|
|
128
|
-
|
|
130
|
+
const resultString = JSON.stringify(result);
|
|
131
|
+
for (let i = 0; i < MAX_CACHE_WRITE_ATTEMPTS; i++) {
|
|
132
|
+
try {
|
|
133
|
+
StorageProvider_1.Storage.setItem(cacheKey, resultString);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (!(error instanceof Error) ||
|
|
138
|
+
error.name !== 'QuotaExceededError' ||
|
|
139
|
+
this._cacheLimit <= 1) {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
this._cacheLimit = Math.ceil(this._cacheLimit / 2);
|
|
143
|
+
this._runLocalStorageCacheEviction(cacheKey, this._cacheLimit - 1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
129
146
|
this._runLocalStorageCacheEviction(cacheKey);
|
|
130
147
|
}
|
|
131
|
-
_runLocalStorageCacheEviction(cacheKey) {
|
|
148
|
+
_runLocalStorageCacheEviction(cacheKey, cacheLimit = this._cacheLimit) {
|
|
132
149
|
var _a;
|
|
133
150
|
const lastModifiedTimeMap = (_a = (0, StorageProvider_1._getObjectFromStorage)(this._lastModifiedStoreKey)) !== null && _a !== void 0 ? _a : {};
|
|
134
151
|
lastModifiedTimeMap[cacheKey] = Date.now();
|
|
135
|
-
const
|
|
136
|
-
|
|
152
|
+
const evictableKeys = _getEvictableKeys(lastModifiedTimeMap, cacheLimit);
|
|
153
|
+
for (const evictable of evictableKeys) {
|
|
137
154
|
delete lastModifiedTimeMap[evictable];
|
|
138
155
|
StorageProvider_1.Storage.removeItem(evictable);
|
|
139
156
|
}
|
|
@@ -166,10 +183,10 @@ class InMemoryCache {
|
|
|
166
183
|
}
|
|
167
184
|
return result;
|
|
168
185
|
}
|
|
169
|
-
add(cacheKey, value) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
delete this._data[
|
|
186
|
+
add(cacheKey, value, cacheLimit) {
|
|
187
|
+
const evictableKeys = _getEvictableKeys(this._data, cacheLimit - 1);
|
|
188
|
+
for (const evictable of evictableKeys) {
|
|
189
|
+
delete this._data[evictable];
|
|
173
190
|
}
|
|
174
191
|
this._data[cacheKey] = value;
|
|
175
192
|
}
|
|
@@ -177,17 +194,22 @@ class InMemoryCache {
|
|
|
177
194
|
this._data = Object.assign(Object.assign({}, this._data), values);
|
|
178
195
|
}
|
|
179
196
|
}
|
|
180
|
-
function
|
|
197
|
+
function _getEvictableKeys(data, limit) {
|
|
181
198
|
const keys = Object.keys(data);
|
|
182
199
|
if (keys.length <= limit) {
|
|
183
|
-
return
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
if (limit === 0) {
|
|
203
|
+
return keys;
|
|
184
204
|
}
|
|
185
|
-
return keys
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
205
|
+
return keys
|
|
206
|
+
.sort((keyA, keyB) => {
|
|
207
|
+
const valueA = data[keyA];
|
|
208
|
+
const valueB = data[keyB];
|
|
209
|
+
if (typeof valueA === 'object' && typeof valueB === 'object') {
|
|
210
|
+
return valueA.receivedAt - valueB.receivedAt;
|
|
190
211
|
}
|
|
191
|
-
return
|
|
192
|
-
})
|
|
212
|
+
return valueA - valueB;
|
|
213
|
+
})
|
|
214
|
+
.slice(0, keys.length - limit);
|
|
193
215
|
}
|
package/src/EventLogger.js
CHANGED
|
@@ -68,6 +68,15 @@ class EventLogger {
|
|
|
68
68
|
this._network.setLogEventCompressionMode(mode);
|
|
69
69
|
}
|
|
70
70
|
setLoggingEnabled(loggingEnabled) {
|
|
71
|
+
if (this._loggingEnabled === 'disabled' && loggingEnabled !== 'disabled') {
|
|
72
|
+
// load any pre consented events into memory
|
|
73
|
+
const storageKey = this._getStorageKey();
|
|
74
|
+
const events = (0, StorageProvider_1._getObjectFromStorage)(storageKey);
|
|
75
|
+
if (events) {
|
|
76
|
+
this._queue.push(...events);
|
|
77
|
+
}
|
|
78
|
+
StorageProvider_1.Storage.removeItem(storageKey);
|
|
79
|
+
}
|
|
71
80
|
this._loggingEnabled = loggingEnabled;
|
|
72
81
|
}
|
|
73
82
|
enqueue(event) {
|
package/src/StatsigMetadata.d.ts
CHANGED
package/src/StatsigMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StatsigMetadataProvider = exports.SDK_VERSION = void 0;
|
|
4
|
-
exports.SDK_VERSION = '3.25.
|
|
4
|
+
exports.SDK_VERSION = '3.25.1';
|
|
5
5
|
let metadata = {
|
|
6
6
|
sdkVersion: exports.SDK_VERSION,
|
|
7
7
|
sdkType: 'js-mono', // js-mono is overwritten by Precomp and OnDevice clients
|