Skip to content

Commit f2c95bd

Browse files
refactor: set change number only if add/removeSplits operations don't fail, for storage consistency
1 parent 7b43dc5 commit f2c95bd

File tree

4 files changed

+45
-67
lines changed

4 files changed

+45
-67
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@splitsoftware/splitio-commons",
3-
"version": "1.17.2-rc.0",
3+
"version": "1.17.2-rc.1",
44
"description": "Split JavaScript SDK common components",
55
"main": "cjs/index.js",
66
"module": "esm/index.js",

src/storages/inLocalStorage/SplitsCacheInLocal.ts

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
1818
private readonly storageHash: string;
1919
private readonly flagSetsFilter: string[];
2020
private hasSync?: boolean;
21-
private updateNewFilter?: boolean;
2221

2322
/**
2423
* @param {KeyBuilderCS} keys
@@ -102,39 +101,29 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
102101
}
103102

104103
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;
109107

110-
localStorage.setItem(splitKey, JSON.stringify(split));
108+
localStorage.setItem(splitKey, JSON.stringify(split));
111109

112-
this._incrementCounts(split);
113-
this._decrementCounts(previousSplit);
110+
this._incrementCounts(split);
111+
this._decrementCounts(previousSplit);
114112

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);
117115

118-
return true;
119-
} catch (e) {
120-
this.log.error(LOG_PREFIX + e);
121-
return false;
122-
}
116+
return true;
123117
}
124118

125119
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));
129122

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);
132125

133-
return true;
134-
} catch (e) {
135-
this.log.error(LOG_PREFIX + e);
136-
return false;
137-
}
126+
return true;
138127
}
139128

140129
getSplit(name: string) {
@@ -143,19 +132,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
143132
}
144133

145134
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-
159135
try {
160136
localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
161137
// update "last updated" timestamp with current time
@@ -246,12 +222,12 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
246222

247223
if (storageHash !== this.storageHash) {
248224
try {
249-
// mark cache to update the new query filter on first successful splits fetch
250-
this.updateNewFilter = true;
251-
252225
// if there is cache, clear it
253226
if (this.checkCache()) this.clear();
254227

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+
255231
} catch (e) {
256232
this.log.error(LOG_PREFIX + e);
257233
}

src/sync/polling/updaters/splitChangesUpdater.ts

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ export function splitChangesUpdaterFactory(
129129
}
130130

131131
/** 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;
134134
// There is at least one added or modified feature flag
135135
if (added && added.some((update: boolean) => update)) return true;
136136
// There is at least one removed feature flag
@@ -158,38 +158,40 @@ export function splitChangesUpdaterFactory(
158158
splitChangesFetcher(since, noCache, till, _promiseDecorator)
159159
)
160160
.then((splitChanges: ISplitChangesResponse) => {
161-
startingUp = false;
162-
163161
const mutation = computeSplitsMutation(splitChanges.splits, splitFiltersValidation);
164162

165163
log.debug(SYNC_SPLITS_NEW, [mutation.added.length]);
166164
log.debug(SYNC_SPLITS_REMOVED, [mutation.removed.length]);
167165
log.debug(SYNC_SPLITS_SEGMENTS, [mutation.segments.length]);
168166

169167
// 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+
});
189190
});
190191
})
191192
.catch(error => {
192193
log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
194+
console.log('startingUp', startingUp, 'retriesOnFailureBeforeReady', retriesOnFailureBeforeReady, 'retry', retry);
193195

194196
if (startingUp && retriesOnFailureBeforeReady > retry) {
195197
retry += 1;

0 commit comments

Comments
 (0)