Skip to content

Commit 64a6258

Browse files
Merge pull request #89 from splitio/consumer_mode_timeout
Consumer mode timeout and vulnerability fixes
2 parents 66ed2bf + 0cd5f98 commit 64a6258

8 files changed

Lines changed: 3430 additions & 4489 deletions

File tree

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
0.9.6 (June 29, 2023)
2+
- Updated some transitive dependencies for vulnerability fixes.
3+
- Updated @splitsoftware/splitio-commons package to version 1.8.3 that includes:
4+
- Updated SDK_READY_TIMED_OUT event to be emitted immediately when a connection error occurs using pluggable storage (i.e., when the wrapper `connect` promise is rejected) in consumer and partial consumer modes.
5+
- Bugfix - The `destroy` method has been updated to immediately flag the SDK client as destroyed, to prevent unexpected behaviours when `getTreatment` and `track` methods are called synchronously after `destroy` method is called.
6+
17
0.9.5 (May 15, 2023)
28
- Updated @splitsoftware/splitio-commons package to version 1.8.2 that includes minor improvements.
39
- Updated terminology on the SDKs codebase to be more aligned with current standard without causing a breaking change. The core change is the term split for feature flag on things like logs and IntelliSense comments.

package-lock.json

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

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@splitsoftware/splitio-browserjs",
3-
"version": "0.9.5",
3+
"version": "0.9.6",
44
"description": "Split SDK for JavaScript on Browser",
55
"main": "cjs/index.js",
66
"module": "esm/index.js",
@@ -64,7 +64,7 @@
6464
"bugs": "https://github.com/splitio/javascript-browser-client/issues",
6565
"homepage": "https://github.com/splitio/javascript-browser-client#readme",
6666
"dependencies": {
67-
"@splitsoftware/splitio-commons": "1.8.2",
67+
"@splitsoftware/splitio-commons": "1.8.3",
6868
"@types/google.analytics": "0.0.40",
6969
"unfetch": "^4.2.0"
7070
},

src/__tests__/consumer/browser_consumer.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,5 +558,4 @@ tape('Browser Consumer mode with pluggable storage', function (t) {
558558

559559
});
560560

561-
562561
});

src/__tests__/consumer/browser_consumer_partial.spec.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import fetchMock from '../testUtils/fetchMock';
44
import { inMemoryWrapperFactory } from '@splitsoftware/splitio-commons/src/storages/pluggable/inMemoryWrapper';
55
import { OPTIMIZED } from '@splitsoftware/splitio-commons/src/utils/constants';
66
import { SDK_NOT_READY } from '@splitsoftware/splitio-commons/src/utils/labels';
7-
import { url } from '../testUtils';
7+
import { url, nearlyEqual } from '../testUtils';
88
import { applyOperations } from './wrapper-commands';
99

1010
import { SplitFactory, PluggableStorage } from '../../';
@@ -341,4 +341,43 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) {
341341
});
342342
});
343343

344+
t.test('Wrapper connection error timeouts the SDK immediately', (assert) => {
345+
// Mock a wrapper connection error
346+
sinon.stub(wrapperInstance, 'connect').callsFake(() => { Promise.reject(); });
347+
const getSpy = sinon.spy(wrapperInstance, 'get');
348+
349+
const sdk = SplitFactory(config);
350+
351+
const client = sdk.client();
352+
353+
client.ready().then(() => {
354+
assert.fail('Ready promise should not be resolved if wrapper connection fails');
355+
}, () => {
356+
assert.pass('Ready promise should be rejected if wrapper connection fails');
357+
});
358+
359+
const start = Date.now();
360+
client.on(client.Event.SDK_READY_TIMED_OUT, async () => {
361+
assert.true(nearlyEqual(Date.now() - start, 0), 'SDK_READY_TIMED_OUT event is emitted immediately');
362+
363+
// Client methods behave as if the SDK is not ready
364+
assert.equal(await client.getTreatment('UT_IN_SEGMENT'), 'control', 'treatment is control with label not ready.');
365+
assert.true(await client.track('user', 'test.event', 18), 'event is tracked in memory (partial consumer mode).');
366+
367+
// Shared clients will also timeout immediately and behave as if the SDK is not ready
368+
const otherClient = sdk.client('other_user');
369+
otherClient.on(otherClient.Event.SDK_READY_TIMED_OUT, async () => {
370+
assert.true(nearlyEqual(Date.now() - start, 0), 'SDK_READY_TIMED_OUT event is emitted immediately in shared client');
371+
372+
assert.equal(await otherClient.getTreatment('UT_IN_SEGMENT'), 'control', 'treatment is control with label not ready.');
373+
assert.true(await otherClient.track('user', 'test.event', 18), 'event is tracked in memory (partial consumer mode).');
374+
375+
await client.destroy();
376+
assert.equal(getSpy.callCount, 0, '`getTreatment` shouldn\'t have called wrapper methods if SDK is not ready');
377+
378+
wrapperInstance.connect.restore();
379+
assert.end();
380+
});
381+
});
382+
});
344383
});

src/__tests__/destroy/browser.spec.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,7 @@ tape('SDK destroy for BrowserJS', async function (assert) {
114114
assert.ok(manager.names().length > 0, 'control assertion');
115115
assert.notOk(client2.track('tt', 'eventType', 2), 'After destroy, track calls return false.');
116116

117-
await client.destroy();
118-
fetchMock.restore();
117+
const destroyPromise = client.destroy();
119118

120119
assert.equal(client.getTreatment('Single_Test'), 'control', 'After destroy, getTreatment returns control for every destroyed client.');
121120
assert.deepEqual(client.getTreatments(['Single_Test']), { 'Single_Test': 'control' }, 'After destroy, getTreatments returns map of controls for every destroyed client.');
@@ -125,5 +124,8 @@ tape('SDK destroy for BrowserJS', async function (assert) {
125124
assert.equal(manager.names().length, 0, 'After the main client is destroyed, manager.names will return empty array');
126125
assert.equal(manager.split('Single_Test'), null, 'After the main client is destroyed, manager.split will return null');
127126

127+
await destroyPromise;
128+
fetchMock.restore();
129+
128130
assert.end();
129131
});

src/settings/defaults.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/
22
import { ConsentStatus, LogLevel } from '@splitsoftware/splitio-commons/src/types';
33
import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants';
44

5-
const packageVersion = '0.9.5';
5+
const packageVersion = '0.9.6';
66

77
/**
88
* In browser, the default debug level, can be set via the `localStorage.splitio_debug` item.

types/splitio.d.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,14 +1342,14 @@ declare namespace SplitIO {
13421342
*/
13431343
setAttribute(attributeName: string, attributeValue: AttributeType): boolean,
13441344
/**
1345-
* Returns the attribute with the given key.
1345+
* Returns the attribute with the given name.
13461346
*
13471347
* @param {string} attributeName Attribute name
1348-
* @returns {AttributeType} Attribute with the given key
1348+
* @returns {AttributeType} Attribute with the given name
13491349
*/
13501350
getAttribute(attributeName: string): AttributeType,
13511351
/**
1352-
* Removes from client's in memory attributes storage the attribute with the given key.
1352+
* Removes from client's in memory attributes storage the attribute with the given name.
13531353
*
13541354
* @param {string} attributeName
13551355
* @returns {boolean} true if attribute was removed and false otherwise
@@ -1432,14 +1432,14 @@ declare namespace SplitIO {
14321432
*/
14331433
setAttribute(attributeName: string, attributeValue: AttributeType): boolean,
14341434
/**
1435-
* Returns the attribute with the given key.
1435+
* Returns the attribute with the given name.
14361436
*
14371437
* @param {string} attributeName Attribute name
1438-
* @returns {AttributeType} Attribute with the given key
1438+
* @returns {AttributeType} Attribute with the given name
14391439
*/
14401440
getAttribute(attributeName: string): AttributeType,
14411441
/**
1442-
* Removes from client's in memory attributes storage the attribute with the given key.
1442+
* Removes from client's in memory attributes storage the attribute with the given name.
14431443
*
14441444
* @param {string} attributeName
14451445
* @returns {boolean} true if attribute was removed and false otherwise

0 commit comments

Comments
 (0)