Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add factory destroy method #825

Merged
merged 8 commits into from
Oct 18, 2024
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
4 changes: 3 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
10.29.0 (September XX, 2024)
10.29.0 (October XX, 2024)
- Added `factory.destroy()` method, which invokes the `destroy` method on all SDK clients created by the factory.
- Updated @splitsoftware/splitio-commons package to version 1.18.0 that includes minor updates:
- Added support for targeting rules based on large segments for browsers.
- Updated some transitive dependencies for vulnerability fixes.
- Bugfixing - Removed an overloaded `client` method in the `SplitIO.ISDK` interface that accepted a key and trafficType parameters. This interface corresponds to the SDK factory instance in NodeJS, which, unlike `SplitIO.IBrowserSDK` for the Browser, does not handle multiple client instances based on keys or traffic types.

10.28.0 (September 6, 2024)
- Updated @splitsoftware/splitio-commons package to version 1.17.0 that includes minor updates:
Expand Down
295 changes: 213 additions & 82 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio",
"version": "10.28.1-rc.1",
"version": "10.28.1-rc.4",
"description": "Split SDK",
"files": [
"README.md",
Expand Down Expand Up @@ -40,7 +40,7 @@
"node": ">=6"
},
"dependencies": {
"@splitsoftware/splitio-commons": "1.17.1-rc.0",
"@splitsoftware/splitio-commons": "1.17.1-rc.4",
"@types/google.analytics": "0.0.40",
"@types/ioredis": "^4.28.0",
"bloom-filters": "^3.0.0",
Expand Down
1 change: 0 additions & 1 deletion src/__tests__/browserSuites/push-synchronization.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const config = {
},
urls: baseUrls,
streamingEnabled: true,
debug: true
};
const settings = settingsFactory(config);

Expand Down
82 changes: 21 additions & 61 deletions src/__tests__/browserSuites/readiness.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,7 @@ export default function (fetchMock, assert) {
t.equal(getMembershipsHits(), 4 * CLIENTS_COUNT - 1, 'It should have not tried to synchronize segments again after the last update that left us in a no segment state.');
t.equal(readyCount, CLIENTS_COUNT, 'all clients must be ready');

Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });

splitio.destroy().then(() => { t.end(); });
}, 10000);
}, 0);
});
Expand Down Expand Up @@ -293,12 +288,7 @@ export default function (fetchMock, assert) {
t.equal(getMembershipsHits(), 4 * CLIENTS_COUNT - 1, 'It should have not tried to synchronize segments again after the last update that left us in a no segment state.');
t.equal(readyCount, CLIENTS_COUNT, 'all clients must be ready');

Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });

splitio.destroy().then(() => { t.end(); });
}, 10000);
}, 0);
});
Expand Down Expand Up @@ -373,12 +363,7 @@ export default function (fetchMock, assert) {
t.equal(getMembershipsHits(), 6 * CLIENTS_COUNT - 1, 'It should keep the producer synchronizing periodically..');
t.equal(readyCount, CLIENTS_COUNT, 'all clients must be ready');

Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });

splitio.destroy().then(() => { t.end(); });
}, 3000);
}, 0);
});
Expand Down Expand Up @@ -417,8 +402,8 @@ export default function (fetchMock, assert) {
});
const CLIENTS_COUNT = 3; // Just so it's easier to read the assertions.
const client = splitio.client();
const client2 = splitio.client('[email protected]');
const client3 = splitio.client('[email protected]');
splitio.client('[email protected]');
splitio.client('[email protected]');

client.once(client.Event.SDK_READY, () => {
t.ok(Date.now() - start >= membershipsEndpointDelay, 'It should not be ready without waiting for memberships, as there are segments in the first splits payload.');
Expand All @@ -442,12 +427,7 @@ export default function (fetchMock, assert) {
setTimeout(() => {
t.equal(getMembershipsHits(), 6 * CLIENTS_COUNT, 'It should keep the producer synchronizing periodically..');

Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });

splitio.destroy().then(() => { t.end(); });
}, 3000);
}, 0);
});
Expand Down Expand Up @@ -486,19 +466,15 @@ export default function (fetchMock, assert) {
});
const CLIENTS_COUNT = 3; // Just so it's easier to read the assertions.
const client = splitio.client();
const client2 = splitio.client('[email protected]');
const client3 = splitio.client('[email protected]');
splitio.client('[email protected]');
splitio.client('[email protected]');

client.once(client.Event.SDK_READY, () => {
t.ok(Date.now() - start >= membershipsEndpointDelay, 'It should not be ready without waiting for memberships, when we start from cache it might be stale.');

setTimeout(() => {
t.equal(getMembershipsHits(), 3 * CLIENTS_COUNT, 'memberships should had been hit once per client on the first attempt and keep syncing afterwards.');
Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });
splitio.destroy().then(() => { t.end(); });
}, 2500);
});
client.once(client.Event.SDK_READY_TIMED_OUT, () => {
Expand Down Expand Up @@ -533,19 +509,15 @@ export default function (fetchMock, assert) {
});
const CLIENTS_COUNT = 3; // Just so it's easier to read the assertions.
const client = splitio.client();
const client2 = splitio.client('[email protected]');
const client3 = splitio.client('[email protected]');
splitio.client('[email protected]');
splitio.client('[email protected]');

client.once(client.Event.SDK_READY, () => {
t.ok(Date.now() - start < 50, 'It should be ready quickly, since it had no segments and update has no segments either.');

setTimeout(() => {
t.equal(getMembershipsHits(), 1 * CLIENTS_COUNT, 'memberships should had been hit once per client on the first attempt but stopped syncing afterwards');
Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });
splitio.destroy().then(() => { t.end(); });
}, 4500);
});
client.once(client.Event.SDK_READY_TIMED_OUT, () => {
Expand Down Expand Up @@ -584,19 +556,15 @@ export default function (fetchMock, assert) {
});
const CLIENTS_COUNT = 3; // Just so it's easier to read the assertions.
const client = splitio.client();
const client2 = splitio.client('[email protected]');
const client3 = splitio.client('[email protected]');
splitio.client('[email protected]');
splitio.client('[email protected]');

client.once(client.Event.SDK_READY, () => {
const delay = Date.now() - start;
t.ok(delay >= membershipsEndpointDelay, 'It should not be ready without waiting for memberships, when we start from cache it might be stale.');
setTimeout(() => {
t.equal(getMembershipsHits(), 3 * CLIENTS_COUNT, 'memberships should had been hit once per client on the first attempt but stopped syncing afterwards');
Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });
splitio.destroy().then(() => { t.end(); });
}, 3000);
});
client.once(client.Event.SDK_READY_TIMED_OUT, () => {
Expand Down Expand Up @@ -631,19 +599,15 @@ export default function (fetchMock, assert) {
});
const CLIENTS_COUNT = 3; // Just so it's easier to read the assertions.
const client = splitio.client();
const client2 = splitio.client('[email protected]');
const client3 = splitio.client('[email protected]');
splitio.client('[email protected]');
splitio.client('[email protected]');

client.once(client.Event.SDK_READY, () => {
t.ok(Date.now() - start >= membershipsEndpointDelay, 'It should not be ready without waiting for memberships, when we start from cache it might be stale and we had segments even though the update has nothing.');

setTimeout(() => {
t.equal(getMembershipsHits(), 3 * CLIENTS_COUNT, 'memberships should had been hit once per client on the first attempt and kept syncing afterwards');
Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });
splitio.destroy().then(() => { t.end(); });
}, 3000);
});
client.once(client.Event.SDK_READY_TIMED_OUT, () => {
Expand Down Expand Up @@ -681,19 +645,15 @@ export default function (fetchMock, assert) {
});
const CLIENTS_COUNT = 3; // Just so it's easier to read the assertions.
const client = splitio.client();
const client2 = splitio.client('[email protected]');
const client3 = splitio.client('[email protected]');
splitio.client('[email protected]');
splitio.client('[email protected]');

client.once(client.Event.SDK_READY, () => {
t.ok(Date.now() - start < 50, 'It should be ready without waiting for memberships, since when it downloads changes it will have no more use for them.');

setTimeout(() => {
t.equal(getMembershipsHits(), 1 * CLIENTS_COUNT, 'memberships should had been hit once per client on the first attempt and stopped syncing afterwards');
Promise.all([
client2.destroy(),
client3.destroy(),
client.destroy()
]).then(() => { t.end(); });
splitio.destroy().then(() => { t.end(); });
}, 3000);
});
client.once(client.Event.SDK_READY_TIMED_OUT, () => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/browserSuites/ready-promise.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ export default function readyPromiseAssertions(fetchMock, assert) {
});
}, 0);
});
}, fromSecondsToMillis(0.2));
}, fromSecondsToMillis(0.25));

}, 'Validate that warning messages are properly sent');

Expand Down
89 changes: 89 additions & 0 deletions src/__tests__/nodeSuites/lazy-init.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { SplitFactory as SplitFactorySS } from '../../factory/node';
import { SplitFactory as SplitFactoryCS } from '../../factory/browser';

// Tests should finish without dangling timers or requests
export default function (settings, fetchMock, t) {

t.test('Server-side', async (assert) => {
let splitio;

for (let i = 0; i < 100; i++) {
splitio = SplitFactorySS({
core: {
authorizationKey: 'fake-token-' + i,
},
urls: {
sdk: 'https://not-called/api',
events: 'https://not-called/api',
auth: 'https://not-called/api',
}
}, (modules) => {
modules.lazyInit = true;
});

const manager = splitio.manager();
assert.deepEqual(manager.names(), [], 'We should not have done any request yet');

const client = splitio.client();
assert.equal(client.getTreatment('user-1', 'split_test'), 'control', 'We should get control');
assert.equal(client.track('user-1', 'user', 'my_event'), true, 'We should track the event');
}

fetchMock.getOnce('https://not-called/api/splitChanges?s=1.1&since=-1', { status: 200, body: { splits: [], since: -1, till: 1457552620999 } });
fetchMock.getOnce('https://not-called/api/splitChanges?s=1.1&since=1457552620999', { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } });
fetchMock.postOnce('https://not-called/api/testImpressions/bulk', 200);
fetchMock.postOnce('https://not-called/api/events/bulk', 200);

splitio.init();
await splitio.client().ready();
assert.true(splitio.client().__getStatus().isReady, 'Split SDK is ready');
await splitio.destroy();

assert.end();
});

t.test('Client-side', async (assert) => {
let splitio;

for (let i = 0; i < 100; i++) {
splitio = SplitFactoryCS({
core: {
authorizationKey: 'fake-token-' + i,
key: 'user-' + i,
},
urls: {
sdk: 'https://not-called/api',
events: 'https://not-called/api',
auth: 'https://not-called/api',
}
}, (modules) => {
modules.lazyInit = true;
});

const manager = splitio.manager();
assert.deepEqual(manager.names(), [], 'We should not have done any request yet');

const client = splitio.client();
assert.equal(client.getTreatment('split_test'), 'control', 'We should get control');
assert.equal(client.track('user', 'my_event'), true, 'We should track the event');

const otherClient = splitio.client('other-user');
assert.equal(otherClient.getTreatment('split_test'), 'control', 'We should get control');
assert.equal(otherClient.track('user', 'my_event'), true, 'We should track the event');
}

fetchMock.getOnce('https://not-called/api/splitChanges?s=1.2&since=-1', { status: 200, body: { splits: [], since: -1, till: 1457552620999 } });
fetchMock.getOnce('https://not-called/api/splitChanges?s=1.2&since=1457552620999', { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } });
fetchMock.getOnce('https://not-called/api/memberships/user-99', { status: 200, body: {} });
fetchMock.getOnce('https://not-called/api/memberships/other-user', { status: 200, body: {} });
fetchMock.postOnce('https://not-called/api/testImpressions/bulk', 200);
fetchMock.postOnce('https://not-called/api/events/bulk', 200);

splitio.init();
await splitio.client().ready();
assert.true(splitio.client().__getStatus().isReady, 'Split SDK is ready');
await splitio.destroy();

assert.end();
});
}
2 changes: 1 addition & 1 deletion src/__tests__/nodeSuites/readiness.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default function (fetchMock, assert) {
try {
await client.ready();
} catch (e) {
await client.destroy();
await splitio.destroy();
t.end();
}
});
Expand Down
9 changes: 6 additions & 3 deletions src/__tests__/online/node.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import fetchMock from '../testUtils/nodeFetchMock';
import { url } from '../testUtils';
import { settingsFactory } from '../../settings/node';

import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';

import evaluationsSuite from '../nodeSuites/evaluations.spec';
import evaluationsSemverSuite from '../nodeSuites/evaluations-semver.spec';
import eventsSuite from '../nodeSuites/events.spec';
Expand All @@ -18,10 +21,8 @@ import ipAddressesSettingDebug from '../nodeSuites/ip-addresses-setting.debug.sp
import readinessSuite from '../nodeSuites/readiness.spec';
import readyPromiseSuite from '../nodeSuites/ready-promise.spec';
import { fetchSpecificSplits, fetchSpecificSplitsForFlagSets } from '../nodeSuites/fetch-specific-splits.spec';

import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';
import flagSets from '../nodeSuites/flag-sets.spec';
import lazyInitSuite from '../nodeSuites/lazy-init.spec';

const config = {
core: {
Expand Down Expand Up @@ -94,5 +95,7 @@ tape('## Node JS - E2E CI Tests ##', async function (assert) {
/* Validate flag sets */
assert.test('E2E / Flag sets', flagSets.bind(null, fetchMock));

assert.test('E2E / SplitFactory with lazy init', lazyInitSuite.bind(null, settings, fetchMock));

assert.end();
});
2 changes: 1 addition & 1 deletion src/settings/defaults/version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const packageVersion = '10.28.1-rc.1';
export const packageVersion = '10.28.1-rc.4';
Loading
Loading