@splitsoftware/splitio-commons 1.17.1 → 1.17.2-rc.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.
@@ -88,54 +88,28 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
88
88
  this.hasSync = false;
89
89
  };
90
90
  SplitsCacheInLocal.prototype.addSplit = function (name, split) {
91
- try {
92
- var splitKey = this.keys.buildSplitKey(name);
93
- var splitFromLocalStorage = localStorage.getItem(splitKey);
94
- var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
95
- localStorage.setItem(splitKey, JSON.stringify(split));
96
- this._incrementCounts(split);
97
- this._decrementCounts(previousSplit);
98
- if (previousSplit)
99
- this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
100
- this.addToFlagSets(split);
101
- return true;
102
- }
103
- catch (e) {
104
- this.log.error(constants_1.LOG_PREFIX + e);
105
- return false;
106
- }
91
+ var splitKey = this.keys.buildSplitKey(name);
92
+ var splitFromLocalStorage = localStorage.getItem(splitKey);
93
+ var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
94
+ localStorage.setItem(splitKey, JSON.stringify(split));
95
+ this._incrementCounts(split);
96
+ this._decrementCounts(previousSplit);
97
+ // if (previousSplit) this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
98
+ // this.addToFlagSets(split);
99
+ return true;
107
100
  };
108
101
  SplitsCacheInLocal.prototype.removeSplit = function (name) {
109
- try {
110
- var split = this.getSplit(name);
111
- localStorage.removeItem(this.keys.buildSplitKey(name));
112
- this._decrementCounts(split);
113
- if (split)
114
- this.removeFromFlagSets(split.name, split.sets);
115
- return true;
116
- }
117
- catch (e) {
118
- this.log.error(constants_1.LOG_PREFIX + e);
119
- return false;
120
- }
102
+ var split = this.getSplit(name);
103
+ localStorage.removeItem(this.keys.buildSplitKey(name));
104
+ this._decrementCounts(split);
105
+ // if (split) this.removeFromFlagSets(split.name, split.sets);
106
+ return true;
121
107
  };
122
108
  SplitsCacheInLocal.prototype.getSplit = function (name) {
123
109
  var item = localStorage.getItem(this.keys.buildSplitKey(name));
124
110
  return item && JSON.parse(item);
125
111
  };
126
112
  SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
127
- // when using a new split query, we must update it at the store
128
- if (this.updateNewFilter) {
129
- this.log.info(constants_1.LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
130
- var storageHashKey = this.keys.buildHashKey();
131
- try {
132
- localStorage.setItem(storageHashKey, this.storageHash);
133
- }
134
- catch (e) {
135
- this.log.error(constants_1.LOG_PREFIX + e);
136
- }
137
- this.updateNewFilter = false;
138
- }
139
113
  try {
140
114
  localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
141
115
  // update "last updated" timestamp with current time
@@ -213,11 +187,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
213
187
  var storageHash = localStorage.getItem(storageHashKey);
214
188
  if (storageHash !== this.storageHash) {
215
189
  try {
216
- // mark cache to update the new query filter on first successful splits fetch
217
- this.updateNewFilter = true;
218
190
  // if there is cache, clear it
219
191
  if (this.checkCache())
220
192
  this.clear();
193
+ this.log.info(constants_1.LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
194
+ localStorage.setItem(storageHashKey, this.storageHash);
221
195
  }
222
196
  catch (e) {
223
197
  this.log.error(constants_1.LOG_PREFIX + e);
@@ -233,41 +207,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
233
207
  return new sets_1._Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
234
208
  });
235
209
  };
236
- SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
237
- var _this = this;
238
- if (!featureFlag.sets)
239
- return;
240
- featureFlag.sets.forEach(function (featureFlagSet) {
241
- if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
242
- return;
243
- var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
244
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
245
- var flagSetCache = new sets_1._Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
246
- flagSetCache.add(featureFlag.name);
247
- localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
248
- });
249
- };
250
- SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
251
- var _this = this;
252
- if (!flagSets)
253
- return;
254
- flagSets.forEach(function (flagSet) {
255
- _this.removeNames(flagSet, featureFlagName);
256
- });
257
- };
258
- SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
259
- var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
260
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
261
- if (!flagSetFromLocalStorage)
262
- return;
263
- var flagSetCache = new sets_1._Set(JSON.parse(flagSetFromLocalStorage));
264
- flagSetCache.delete(featureFlagName);
265
- if (flagSetCache.size === 0) {
266
- localStorage.removeItem(flagSetKey);
267
- return;
268
- }
269
- localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
270
- };
271
210
  return SplitsCacheInLocal;
272
211
  }(AbstractSplitsCacheSync_1.AbstractSplitsCacheSync));
273
212
  exports.SplitsCacheInLocal = SplitsCacheInLocal;
@@ -102,7 +102,7 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
102
102
  }
103
103
  /** Returns true if at least one split was updated */
104
104
  function isThereUpdate(flagsChange) {
105
- var added = flagsChange[1], removed = flagsChange[2];
105
+ var added = flagsChange[0], removed = flagsChange[1];
106
106
  // There is at least one added or modified feature flag
107
107
  if (added && added.some(function (update) { return update; }))
108
108
  return true;
@@ -130,36 +130,38 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
130
130
  { splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
131
131
  splitChangesFetcher(since, noCache, till, _promiseDecorator))
132
132
  .then(function (splitChanges) {
133
- startingUp = false;
134
133
  var mutation = computeSplitsMutation(splitChanges.splits, splitFiltersValidation);
135
134
  log.debug(constants_2.SYNC_SPLITS_NEW, [mutation.added.length]);
136
135
  log.debug(constants_2.SYNC_SPLITS_REMOVED, [mutation.removed.length]);
137
136
  log.debug(constants_2.SYNC_SPLITS_SEGMENTS, [mutation.segments.length]);
138
137
  // Write into storage
139
- // @TODO call `setChangeNumber` only if the other storage operations have succeeded, in order to keep storage consistency
140
- return Promise.all([
141
- // calling first `setChangenumber` method, to perform cache flush if split filter queryString changed
142
- splits.setChangeNumber(splitChanges.till),
143
- splits.addSplits(mutation.added),
144
- splits.removeSplits(mutation.removed),
145
- segments.registerSegments(mutation.segments)
146
- ]).then(function (flagsChange) {
147
- if (splitsEventEmitter) {
148
- // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
149
- return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate(flagsChange) && (isClientSide || checkAllSegmentsExist(segments))))
150
- .catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
151
- .then(function (emitSplitsArrivedEvent) {
152
- // emit SDK events
153
- if (emitSplitsArrivedEvent)
154
- splitsEventEmitter.emit(constants_1.SDK_SPLITS_ARRIVED);
155
- return true;
156
- });
157
- }
158
- return true;
138
+ // Wrap into a promise to handle LOCALSTORAGE exceptions and REDIS rejected promises uniformly
139
+ return Promise.resolve().then(function () {
140
+ return Promise.all([
141
+ splits.addSplits(mutation.added),
142
+ splits.removeSplits(mutation.removed),
143
+ segments.registerSegments(mutation.segments)
144
+ ]).then(function (flagsChange) {
145
+ splits.setChangeNumber(splitChanges.till);
146
+ startingUp = false;
147
+ if (splitsEventEmitter) {
148
+ // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
149
+ return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate(flagsChange) && (isClientSide || checkAllSegmentsExist(segments))))
150
+ .catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
151
+ .then(function (emitSplitsArrivedEvent) {
152
+ // emit SDK events
153
+ if (emitSplitsArrivedEvent)
154
+ splitsEventEmitter.emit(constants_1.SDK_SPLITS_ARRIVED);
155
+ return true;
156
+ });
157
+ }
158
+ return true;
159
+ });
159
160
  });
160
161
  })
161
162
  .catch(function (error) {
162
163
  log.warn(constants_2.SYNC_SPLITS_FETCH_FAILS, [error]);
164
+ console.log('startingUp', startingUp, 'retriesOnFailureBeforeReady', retriesOnFailureBeforeReady, 'retry', retry);
163
165
  if (startingUp && retriesOnFailureBeforeReady > retry) {
164
166
  retry += 1;
165
167
  log.info(constants_2.SYNC_SPLITS_FETCH_RETRY, [retry, error]);
@@ -2,7 +2,7 @@ import { __extends } from "tslib";
2
2
  import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
3
3
  import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
4
  import { LOG_PREFIX } from './constants';
5
- import { _Set, setToArray } from '../../utils/lang/sets';
5
+ import { _Set } from '../../utils/lang/sets';
6
6
  import { getStorageHash } from '../KeyBuilder';
7
7
  /**
8
8
  * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
@@ -85,54 +85,28 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
85
85
  this.hasSync = false;
86
86
  };
87
87
  SplitsCacheInLocal.prototype.addSplit = function (name, split) {
88
- try {
89
- var splitKey = this.keys.buildSplitKey(name);
90
- var splitFromLocalStorage = localStorage.getItem(splitKey);
91
- var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
92
- localStorage.setItem(splitKey, JSON.stringify(split));
93
- this._incrementCounts(split);
94
- this._decrementCounts(previousSplit);
95
- if (previousSplit)
96
- this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
97
- this.addToFlagSets(split);
98
- return true;
99
- }
100
- catch (e) {
101
- this.log.error(LOG_PREFIX + e);
102
- return false;
103
- }
88
+ var splitKey = this.keys.buildSplitKey(name);
89
+ var splitFromLocalStorage = localStorage.getItem(splitKey);
90
+ var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
91
+ localStorage.setItem(splitKey, JSON.stringify(split));
92
+ this._incrementCounts(split);
93
+ this._decrementCounts(previousSplit);
94
+ // if (previousSplit) this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
95
+ // this.addToFlagSets(split);
96
+ return true;
104
97
  };
105
98
  SplitsCacheInLocal.prototype.removeSplit = function (name) {
106
- try {
107
- var split = this.getSplit(name);
108
- localStorage.removeItem(this.keys.buildSplitKey(name));
109
- this._decrementCounts(split);
110
- if (split)
111
- this.removeFromFlagSets(split.name, split.sets);
112
- return true;
113
- }
114
- catch (e) {
115
- this.log.error(LOG_PREFIX + e);
116
- return false;
117
- }
99
+ var split = this.getSplit(name);
100
+ localStorage.removeItem(this.keys.buildSplitKey(name));
101
+ this._decrementCounts(split);
102
+ // if (split) this.removeFromFlagSets(split.name, split.sets);
103
+ return true;
118
104
  };
119
105
  SplitsCacheInLocal.prototype.getSplit = function (name) {
120
106
  var item = localStorage.getItem(this.keys.buildSplitKey(name));
121
107
  return item && JSON.parse(item);
122
108
  };
123
109
  SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
124
- // when using a new split query, we must update it at the store
125
- if (this.updateNewFilter) {
126
- this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
127
- var storageHashKey = this.keys.buildHashKey();
128
- try {
129
- localStorage.setItem(storageHashKey, this.storageHash);
130
- }
131
- catch (e) {
132
- this.log.error(LOG_PREFIX + e);
133
- }
134
- this.updateNewFilter = false;
135
- }
136
110
  try {
137
111
  localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
138
112
  // update "last updated" timestamp with current time
@@ -210,11 +184,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
210
184
  var storageHash = localStorage.getItem(storageHashKey);
211
185
  if (storageHash !== this.storageHash) {
212
186
  try {
213
- // mark cache to update the new query filter on first successful splits fetch
214
- this.updateNewFilter = true;
215
187
  // if there is cache, clear it
216
188
  if (this.checkCache())
217
189
  this.clear();
190
+ this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
191
+ localStorage.setItem(storageHashKey, this.storageHash);
218
192
  }
219
193
  catch (e) {
220
194
  this.log.error(LOG_PREFIX + e);
@@ -230,41 +204,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
230
204
  return new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
231
205
  });
232
206
  };
233
- SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
234
- var _this = this;
235
- if (!featureFlag.sets)
236
- return;
237
- featureFlag.sets.forEach(function (featureFlagSet) {
238
- if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
239
- return;
240
- var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
241
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
242
- var flagSetCache = new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
243
- flagSetCache.add(featureFlag.name);
244
- localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
245
- });
246
- };
247
- SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
248
- var _this = this;
249
- if (!flagSets)
250
- return;
251
- flagSets.forEach(function (flagSet) {
252
- _this.removeNames(flagSet, featureFlagName);
253
- });
254
- };
255
- SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
256
- var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
257
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
258
- if (!flagSetFromLocalStorage)
259
- return;
260
- var flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
261
- flagSetCache.delete(featureFlagName);
262
- if (flagSetCache.size === 0) {
263
- localStorage.removeItem(flagSetKey);
264
- return;
265
- }
266
- localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
267
- };
268
207
  return SplitsCacheInLocal;
269
208
  }(AbstractSplitsCacheSync));
270
209
  export { SplitsCacheInLocal };
@@ -97,7 +97,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
97
97
  }
98
98
  /** Returns true if at least one split was updated */
99
99
  function isThereUpdate(flagsChange) {
100
- var added = flagsChange[1], removed = flagsChange[2];
100
+ var added = flagsChange[0], removed = flagsChange[1];
101
101
  // There is at least one added or modified feature flag
102
102
  if (added && added.some(function (update) { return update; }))
103
103
  return true;
@@ -125,36 +125,38 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
125
125
  { splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
126
126
  splitChangesFetcher(since, noCache, till, _promiseDecorator))
127
127
  .then(function (splitChanges) {
128
- startingUp = false;
129
128
  var mutation = computeSplitsMutation(splitChanges.splits, splitFiltersValidation);
130
129
  log.debug(SYNC_SPLITS_NEW, [mutation.added.length]);
131
130
  log.debug(SYNC_SPLITS_REMOVED, [mutation.removed.length]);
132
131
  log.debug(SYNC_SPLITS_SEGMENTS, [mutation.segments.length]);
133
132
  // Write into storage
134
- // @TODO call `setChangeNumber` only if the other storage operations have succeeded, in order to keep storage consistency
135
- return Promise.all([
136
- // calling first `setChangenumber` method, to perform cache flush if split filter queryString changed
137
- splits.setChangeNumber(splitChanges.till),
138
- splits.addSplits(mutation.added),
139
- splits.removeSplits(mutation.removed),
140
- segments.registerSegments(mutation.segments)
141
- ]).then(function (flagsChange) {
142
- if (splitsEventEmitter) {
143
- // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
144
- return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate(flagsChange) && (isClientSide || checkAllSegmentsExist(segments))))
145
- .catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
146
- .then(function (emitSplitsArrivedEvent) {
147
- // emit SDK events
148
- if (emitSplitsArrivedEvent)
149
- splitsEventEmitter.emit(SDK_SPLITS_ARRIVED);
150
- return true;
151
- });
152
- }
153
- return true;
133
+ // Wrap into a promise to handle LOCALSTORAGE exceptions and REDIS rejected promises uniformly
134
+ return Promise.resolve().then(function () {
135
+ return Promise.all([
136
+ splits.addSplits(mutation.added),
137
+ splits.removeSplits(mutation.removed),
138
+ segments.registerSegments(mutation.segments)
139
+ ]).then(function (flagsChange) {
140
+ splits.setChangeNumber(splitChanges.till);
141
+ startingUp = false;
142
+ if (splitsEventEmitter) {
143
+ // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
144
+ return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate(flagsChange) && (isClientSide || checkAllSegmentsExist(segments))))
145
+ .catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
146
+ .then(function (emitSplitsArrivedEvent) {
147
+ // emit SDK events
148
+ if (emitSplitsArrivedEvent)
149
+ splitsEventEmitter.emit(SDK_SPLITS_ARRIVED);
150
+ return true;
151
+ });
152
+ }
153
+ return true;
154
+ });
154
155
  });
155
156
  })
156
157
  .catch(function (error) {
157
158
  log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
159
+ console.log('startingUp', startingUp, 'retriesOnFailureBeforeReady', retriesOnFailureBeforeReady, 'retry', retry);
158
160
  if (startingUp && retriesOnFailureBeforeReady > retry) {
159
161
  retry += 1;
160
162
  log.info(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.17.1",
3
+ "version": "1.17.2-rc.1",
4
4
  "description": "Split JavaScript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -4,7 +4,7 @@ import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
4
  import { KeyBuilderCS } from '../KeyBuilderCS';
5
5
  import { ILogger } from '../../logger/types';
6
6
  import { LOG_PREFIX } from './constants';
7
- import { ISet, _Set, setToArray } from '../../utils/lang/sets';
7
+ import { ISet, _Set } from '../../utils/lang/sets';
8
8
  import { ISettings } from '../../types';
9
9
  import { getStorageHash } from '../KeyBuilder';
10
10
 
@@ -18,7 +18,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
18
18
  private readonly storageHash: string;
19
19
  private readonly flagSetsFilter: string[];
20
20
  private hasSync?: boolean;
21
- private updateNewFilter?: boolean;
22
21
 
23
22
  /**
24
23
  * @param {KeyBuilderCS} keys
@@ -102,39 +101,29 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
102
101
  }
103
102
 
104
103
  addSplit(name: string, split: ISplit) {
105
- try {
106
- const splitKey = this.keys.buildSplitKey(name);
107
- const splitFromLocalStorage = localStorage.getItem(splitKey);
108
- const previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
104
+ const splitKey = this.keys.buildSplitKey(name);
105
+ const splitFromLocalStorage = localStorage.getItem(splitKey);
106
+ const previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
109
107
 
110
- localStorage.setItem(splitKey, JSON.stringify(split));
108
+ localStorage.setItem(splitKey, JSON.stringify(split));
111
109
 
112
- this._incrementCounts(split);
113
- this._decrementCounts(previousSplit);
110
+ this._incrementCounts(split);
111
+ this._decrementCounts(previousSplit);
114
112
 
115
- if (previousSplit) this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
116
- this.addToFlagSets(split);
113
+ // if (previousSplit) this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
114
+ // this.addToFlagSets(split);
117
115
 
118
- return true;
119
- } catch (e) {
120
- this.log.error(LOG_PREFIX + e);
121
- return false;
122
- }
116
+ return true;
123
117
  }
124
118
 
125
119
  removeSplit(name: string): boolean {
126
- try {
127
- const split = this.getSplit(name);
128
- localStorage.removeItem(this.keys.buildSplitKey(name));
120
+ const split = this.getSplit(name);
121
+ localStorage.removeItem(this.keys.buildSplitKey(name));
129
122
 
130
- this._decrementCounts(split);
131
- if (split) this.removeFromFlagSets(split.name, split.sets);
123
+ this._decrementCounts(split);
124
+ // if (split) this.removeFromFlagSets(split.name, split.sets);
132
125
 
133
- return true;
134
- } catch (e) {
135
- this.log.error(LOG_PREFIX + e);
136
- return false;
137
- }
126
+ return true;
138
127
  }
139
128
 
140
129
  getSplit(name: string) {
@@ -143,19 +132,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
143
132
  }
144
133
 
145
134
  setChangeNumber(changeNumber: number): boolean {
146
-
147
- // when using a new split query, we must update it at the store
148
- if (this.updateNewFilter) {
149
- this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
150
- const storageHashKey = this.keys.buildHashKey();
151
- try {
152
- localStorage.setItem(storageHashKey, this.storageHash);
153
- } catch (e) {
154
- this.log.error(LOG_PREFIX + e);
155
- }
156
- this.updateNewFilter = false;
157
- }
158
-
159
135
  try {
160
136
  localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
161
137
  // update "last updated" timestamp with current time
@@ -246,12 +222,12 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
246
222
 
247
223
  if (storageHash !== this.storageHash) {
248
224
  try {
249
- // mark cache to update the new query filter on first successful splits fetch
250
- this.updateNewFilter = true;
251
-
252
225
  // if there is cache, clear it
253
226
  if (this.checkCache()) this.clear();
254
227
 
228
+ this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
229
+ localStorage.setItem(storageHashKey, this.storageHash);
230
+
255
231
  } catch (e) {
256
232
  this.log.error(LOG_PREFIX + e);
257
233
  }
@@ -268,48 +244,48 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
268
244
  });
269
245
  }
270
246
 
271
- private addToFlagSets(featureFlag: ISplit) {
272
- if (!featureFlag.sets) return;
247
+ // private addToFlagSets(featureFlag: ISplit) {
248
+ // if (!featureFlag.sets) return;
273
249
 
274
- featureFlag.sets.forEach(featureFlagSet => {
250
+ // featureFlag.sets.forEach(featureFlagSet => {
275
251
 
276
- if (this.flagSetsFilter.length > 0 && !this.flagSetsFilter.some(filterFlagSet => filterFlagSet === featureFlagSet)) return;
252
+ // if (this.flagSetsFilter.length > 0 && !this.flagSetsFilter.some(filterFlagSet => filterFlagSet === featureFlagSet)) return;
277
253
 
278
- const flagSetKey = this.keys.buildFlagSetKey(featureFlagSet);
254
+ // const flagSetKey = this.keys.buildFlagSetKey(featureFlagSet);
279
255
 
280
- const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
256
+ // const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
281
257
 
282
- const flagSetCache = new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
283
- flagSetCache.add(featureFlag.name);
258
+ // const flagSetCache = new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
259
+ // flagSetCache.add(featureFlag.name);
284
260
 
285
- localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
286
- });
287
- }
261
+ // localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
262
+ // });
263
+ // }
288
264
 
289
- private removeFromFlagSets(featureFlagName: string, flagSets?: string[]) {
290
- if (!flagSets) return;
265
+ // private removeFromFlagSets(featureFlagName: string, flagSets?: string[]) {
266
+ // if (!flagSets) return;
291
267
 
292
- flagSets.forEach(flagSet => {
293
- this.removeNames(flagSet, featureFlagName);
294
- });
295
- }
268
+ // flagSets.forEach(flagSet => {
269
+ // this.removeNames(flagSet, featureFlagName);
270
+ // });
271
+ // }
296
272
 
297
- private removeNames(flagSetName: string, featureFlagName: string) {
298
- const flagSetKey = this.keys.buildFlagSetKey(flagSetName);
273
+ // private removeNames(flagSetName: string, featureFlagName: string) {
274
+ // const flagSetKey = this.keys.buildFlagSetKey(flagSetName);
299
275
 
300
- const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
276
+ // const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
301
277
 
302
- if (!flagSetFromLocalStorage) return;
278
+ // if (!flagSetFromLocalStorage) return;
303
279
 
304
- const flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
305
- flagSetCache.delete(featureFlagName);
280
+ // const flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
281
+ // flagSetCache.delete(featureFlagName);
306
282
 
307
- if (flagSetCache.size === 0) {
308
- localStorage.removeItem(flagSetKey);
309
- return;
310
- }
283
+ // if (flagSetCache.size === 0) {
284
+ // localStorage.removeItem(flagSetKey);
285
+ // return;
286
+ // }
311
287
 
312
- localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
313
- }
288
+ // localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
289
+ // }
314
290
 
315
291
  }
@@ -129,8 +129,8 @@ export function splitChangesUpdaterFactory(
129
129
  }
130
130
 
131
131
  /** Returns true if at least one split was updated */
132
- function isThereUpdate(flagsChange: [boolean | void, void | boolean[], void | boolean[], boolean | void] | [any, any, any]) {
133
- const [, added, removed] = flagsChange;
132
+ function isThereUpdate(flagsChange: [void | boolean[], void | boolean[], boolean | void] | [any, any, any]) {
133
+ const [added, removed] = flagsChange;
134
134
  // There is at least one added or modified feature flag
135
135
  if (added && added.some((update: boolean) => update)) return true;
136
136
  // There is at least one removed feature flag
@@ -158,8 +158,6 @@ export function splitChangesUpdaterFactory(
158
158
  splitChangesFetcher(since, noCache, till, _promiseDecorator)
159
159
  )
160
160
  .then((splitChanges: ISplitChangesResponse) => {
161
- startingUp = false;
162
-
163
161
  const mutation = computeSplitsMutation(splitChanges.splits, splitFiltersValidation);
164
162
 
165
163
  log.debug(SYNC_SPLITS_NEW, [mutation.added.length]);
@@ -167,29 +165,33 @@ export function splitChangesUpdaterFactory(
167
165
  log.debug(SYNC_SPLITS_SEGMENTS, [mutation.segments.length]);
168
166
 
169
167
  // Write into storage
170
- // @TODO call `setChangeNumber` only if the other storage operations have succeeded, in order to keep storage consistency
171
- return Promise.all([
172
- // calling first `setChangenumber` method, to perform cache flush if split filter queryString changed
173
- splits.setChangeNumber(splitChanges.till),
174
- splits.addSplits(mutation.added),
175
- splits.removeSplits(mutation.removed),
176
- segments.registerSegments(mutation.segments)
177
- ]).then((flagsChange) => {
178
- if (splitsEventEmitter) {
179
- // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
180
- return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate(flagsChange) && (isClientSide || checkAllSegmentsExist(segments))))
181
- .catch(() => false /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
182
- .then(emitSplitsArrivedEvent => {
183
- // emit SDK events
184
- if (emitSplitsArrivedEvent) splitsEventEmitter.emit(SDK_SPLITS_ARRIVED);
185
- return true;
186
- });
187
- }
188
- return true;
168
+ // Wrap into a promise to handle LOCALSTORAGE exceptions and REDIS rejected promises uniformly
169
+ return Promise.resolve().then(() => {
170
+ return Promise.all([
171
+ splits.addSplits(mutation.added),
172
+ splits.removeSplits(mutation.removed),
173
+ segments.registerSegments(mutation.segments)
174
+ ]).then((flagsChange) => {
175
+ splits.setChangeNumber(splitChanges.till);
176
+ startingUp = false;
177
+
178
+ if (splitsEventEmitter) {
179
+ // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
180
+ return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate(flagsChange) && (isClientSide || checkAllSegmentsExist(segments))))
181
+ .catch(() => false /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
182
+ .then(emitSplitsArrivedEvent => {
183
+ // emit SDK events
184
+ if (emitSplitsArrivedEvent) splitsEventEmitter.emit(SDK_SPLITS_ARRIVED);
185
+ return true;
186
+ });
187
+ }
188
+ return true;
189
+ });
189
190
  });
190
191
  })
191
192
  .catch(error => {
192
193
  log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
194
+ console.log('startingUp', startingUp, 'retriesOnFailureBeforeReady', retriesOnFailureBeforeReady, 'retry', retry);
193
195
 
194
196
  if (startingUp && retriesOnFailureBeforeReady > retry) {
195
197
  retry += 1;
@@ -12,7 +12,6 @@ export declare class SplitsCacheInLocal extends AbstractSplitsCacheSync {
12
12
  private readonly storageHash;
13
13
  private readonly flagSetsFilter;
14
14
  private hasSync?;
15
- private updateNewFilter?;
16
15
  /**
17
16
  * @param {KeyBuilderCS} keys
18
17
  * @param {number | undefined} expirationTimestamp
@@ -49,7 +48,4 @@ export declare class SplitsCacheInLocal extends AbstractSplitsCacheSync {
49
48
  private _checkExpiration;
50
49
  private _checkFilterQuery;
51
50
  getNamesByFlagSets(flagSets: string[]): ISet<string>[];
52
- private addToFlagSets;
53
- private removeFromFlagSets;
54
- private removeNames;
55
51
  }