Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
10.17.3 (XXX XX, 2022)
- Updated format for MySegments keys in LocalStorage, keeping backwards compatibility.

10.17.2 (January 31, 2022)
- Updated some dependencies for vulnerability fixes.
- Bugfixing - Fixed internal handling of Fetch API promise rejection, to avoid unhandled exceptions on some Web browsers (issue https://github.com/splitio/javascript-client/issues/621)
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio",
"version": "10.17.2",
"version": "10.17.3-rc.4",
"description": "Split SDK",
"files": [
"README.md",
Expand Down
16 changes: 14 additions & 2 deletions src/storage/KeysLocalStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ class KeyBuilderForLocalStorage extends KeyBuilder {
}

buildSegmentNameKey(segmentName) {
return `${matching(this.settings.core.key)}.${this.settings.storage.prefix}.segment.${segmentName}`;
return `${this.settings.storage.prefix}.${matching(this.settings.core.key)}.segment.${segmentName}`;
}

extractSegmentName(builtSegmentKeyName) {
const prefix = `${matching(this.settings.core.key)}.${this.settings.storage.prefix}.segment.`;
const prefix = `${this.settings.storage.prefix}.${matching(this.settings.core.key)}.segment.`;

if (startsWith(builtSegmentKeyName, prefix))
return builtSegmentKeyName.substr(prefix.length);
Expand All @@ -35,6 +35,18 @@ class KeyBuilderForLocalStorage extends KeyBuilder {
buildSplitsFilterQueryKey() {
return `${this.settings.storage.prefix}.splits.filterQuery`;
}

// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
buildOldSegmentNameKey(segmentName) {
return `${matching(this.settings.core.key)}.${this.settings.storage.prefix}.segment.${segmentName}`;
}
// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
extractOldSegmentKey(maybeOldKey) {
const prefix = `${matching(this.settings.core.key)}.${this.settings.storage.prefix}.segment.`;

if (startsWith(maybeOldKey, prefix))
return maybeOldKey.substr(prefix.length);
}
}

export default KeyBuilderForLocalStorage;
28 changes: 24 additions & 4 deletions src/storage/SegmentCache/InLocalStorage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,29 @@ class SegmentCacheInLocalStorage {

// Scan current values from localStorage
const storedSegmentNames = Object.keys(localStorage).reduce((accum, key) => {
const segmentName = this.keys.extractSegmentName(key);

if (segmentName) accum.push(segmentName);
let segmentName = this.keys.extractSegmentName(key);

if (segmentName) {
accum.push(segmentName);
} else {
// @BREAKING: This is only to clean up "old" keys. Remove this whole else code block.
segmentName = this.keys.extractOldSegmentKey(key);

if (segmentName) { // this was an old segment key, let's clean up.
const newSegmentKey = this.keys.buildSegmentNameKey(segmentName);
try {
// If the new format key is not there, create it.
if (!localStorage.getItem(newSegmentKey) && segmentNames.indexOf(segmentName) > -1) {
localStorage.setItem(newSegmentKey, DEFINED);
// we are migrating a segment, let's track it.
accum.push(segmentName);
}
localStorage.removeItem(key); // we migrated the current key, let's delete it.
} catch (e) {
log.error(e);
}
}
}

return accum;
}, []);
Expand All @@ -65,7 +85,7 @@ class SegmentCacheInLocalStorage {
segmentNames.forEach(segmentName => this.addToSegment(segmentName));
} else {
// Slowest path => we need to find at least 1 difference because
for(index = 0; index < segmentNames.length && storedSegmentNames.indexOf(segmentNames[index]) !== -1; index++) {
for (index = 0; index < segmentNames.length && storedSegmentNames.indexOf(segmentNames[index]) !== -1; index++) {
// TODO: why empty statement?
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,41 @@ tape('SEGMENT CACHE / in LocalStorage', assert => {

assert.ok( cache.isInSegment('mocked-segment') === false );

cache.flush();
assert.end();
});

// @BREAKING: REMOVE when removing this backwards compatibility.
tape('SEGMENT CACHE / in LocalStorage migration for mysegments keys', assert => {

const keys = new KeyBuilder(SettingsFactory({
core: { key: 'test_nico' },
storage:{ prefix: 'LS_BC_test'}
}));
const cache = new SegmentCacheInLocalStorage(keys);
const oldKey1 = 'test_nico.LS_BC_test.SPLITIO.segment.segment1';
const oldKey2 = 'test_nico.LS_BC_test.SPLITIO.segment.segment2';
const newKey1 = keys.buildSegmentNameKey('segment1');
const newKey2 = keys.buildSegmentNameKey('segment2');

cache.flush(); // cleanup before starting.

// Not adding a full suite for LS keys now, testing here
assert.equal(oldKey1, keys.buildOldSegmentNameKey('segment1'));
assert.equal('segment1', keys.extractOldSegmentKey(oldKey1));

// add two segments, one we don't want to send on reset, should only be cleared, other one will be migrated.
localStorage.setItem(oldKey1, 1);
localStorage.setItem(oldKey2, 1);
assert.equal(localStorage.getItem(newKey1), null, 'control assertion');

cache.resetSegments(['segment1']);

assert.equal(localStorage.getItem(newKey1), '1', 'The segment key for segment1, as is part of the new list, should be migrated.');
assert.equal(localStorage.getItem(newKey2), null, 'The segment key for segment2 should not be migrated.');
assert.equal(localStorage.getItem(oldKey1), null, 'Old keys are removed.');
assert.equal(localStorage.getItem(oldKey2), null, 'Old keys are removed.');

cache.flush();
assert.end();
});
2 changes: 1 addition & 1 deletion src/utils/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { API } from '../../utils/logger';
import { STANDALONE_MODE, STORAGE_MEMORY, CONSUMER_MODE, OPTIMIZED } from '../../utils/constants';
import validImpressionsMode from './impressionsMode';

const version = '10.17.2';
const version = '10.17.3-rc.4';
const eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/;
const authEndpointMatcher = /^\/v2\/auth/;
const streamingEndpointMatcher = /^\/(sse|event-stream)/;
Expand Down