Skip to content
Open
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
14 changes: 10 additions & 4 deletions src/factory/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { syncManagerOnlineFactory } from '@splitsoftware/splitio-commons/src/syn
import { pushManagerFactory } from '@splitsoftware/splitio-commons/src/sync/streaming/pushManager';
import { pollingManagerSSFactory } from '@splitsoftware/splitio-commons/src/sync/polling/pollingManagerSS';
import { InRedisStorage } from '@splitsoftware/splitio-commons/src/storages/inRedis';
import { PluggableStorage } from '@splitsoftware/splitio-commons/src/storages/pluggable';
import { InMemoryStorageFactory } from '@splitsoftware/splitio-commons/src/storages/inMemory/InMemoryStorage';
import { getRolloutPlan } from '@splitsoftware/splitio-commons/src/storages/getRolloutPlan';
import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager';
import { sdkClientMethodFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethod';
import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverSS';
import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory';
import { CONSUMER_MODE, LOCALHOST_MODE } from '@splitsoftware/splitio-commons/src/utils/constants';
import { CONSUMER_MODE, LOCALHOST_MODE, STORAGE_REDIS, STORAGE_PLUGGABLE } from '@splitsoftware/splitio-commons/src/utils/constants';
import { isConsumerMode } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/mode';

import { localhostFromFileFactory } from '../sync/offline/LocalhostFromFile';
Expand All @@ -20,9 +21,14 @@ import { bloomFilterFactory } from '../platform/filter/bloomFilter';
const syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory, pushManagerFactory);

function getStorage(settings) {
return settings.storage.type === 'REDIS' ?
InRedisStorage(settings.storage) :
InMemoryStorageFactory;
switch (settings.storage.type) {
case STORAGE_REDIS:
return InRedisStorage(settings.storage);
case STORAGE_PLUGGABLE:
return PluggableStorage({ prefix: settings.storage.prefix, wrapper: settings.storage.options.wrapper });
default:
return InMemoryStorageFactory;
}
}

/**
Expand Down
44 changes: 40 additions & 4 deletions src/settings/__tests__/node.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import sinon from 'sinon';
import osFunction from 'os';
import * as ipFunction from '../../utils/ip';
import { settingsFactory } from '../node';
import { CONSUMER_MODE, NA } from '@splitsoftware/splitio-commons/src/utils/constants';
import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE, NA } from '@splitsoftware/splitio-commons/src/utils/constants';

const IP_VALUE = ipFunction.address();
const HOSTNAME_VALUE = osFunction.hostname();
Expand Down Expand Up @@ -96,7 +96,7 @@ tape('SETTINGS / IPAddressesEnabled should be overwritable and true by default',
assert.end();
});

tape('SETTINGS / Throws exception if no "REDIS" storage is provided in consumer mode', (assert) => {
tape('SETTINGS / Throws exception if no async storage is provided in consumer mode', (assert) => {
const config = {
core: {
authorizationKey: 'dummy token'
Expand All @@ -106,13 +106,13 @@ tape('SETTINGS / Throws exception if no "REDIS" storage is provided in consumer

assert.throws(() => {
settingsFactory(config);
}, /A REDIS storage is required on consumer mode/);
}, /A REDIS or PLUGGABLE storage is required on consumer mode/);
assert.throws(() => {
settingsFactory({
...config,
storage: { type: 'invalid type' }
});
}, /A REDIS storage is required on consumer mode/);
}, /A REDIS or PLUGGABLE storage is required on consumer mode/);

assert.end();
});
Expand Down Expand Up @@ -144,6 +144,42 @@ tape('SETTINGS / Log error and fallback to InMemory storage if no valid storage
assert.end();
});

tape('SETTINGS / PLUGGABLE storage is accepted in consumer modes', (assert) => {
const wrapper = { get: () => {}, set: () => {} };

[CONSUMER_MODE, CONSUMER_PARTIAL_MODE].forEach(mode => {
const settings = settingsFactory({
core: { authorizationKey: 'dummy token' },
mode,
storage: { type: 'PLUGGABLE', prefix: 'test_prefix', options: { wrapper } }
});

assert.deepEqual(settings.storage, {
type: 'PLUGGABLE', prefix: 'test_prefix', options: { wrapper }
}, `Pluggable storage settings and options should be passed through in ${mode} mode.`);
});

assert.end();
});

tape('SETTINGS / Log error and fallback to InMemory storage if PLUGGABLE storage is used outside consumer modes', (assert) => {
const logSpy = sinon.spy(console, 'log');

const settings = settingsFactory({
core: { authorizationKey: 'dummy token' }, // standalone mode
storage: { type: 'PLUGGABLE', options: { wrapper: {} } },
debug: 'ERROR'
});

assert.deepEqual(logSpy.args, [
['[ERROR] splitio => The provided PLUGGABLE storage is invalid for this mode. It requires consumer mode. Fallback into default MEMORY storage.']
], 'logs error message');
assert.equal(settings.storage.type, 'MEMORY', 'fallbacks to memory storage');

logSpy.restore();
assert.end();
});

tape('SETTINGS / Consent is not overwritable in server-side', assert => {
const settings = settingsFactory({ userConsent: 'UNKNOWN' });

Expand Down
25 changes: 21 additions & 4 deletions src/settings/storage/node.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LOCALHOST_MODE, STORAGE_MEMORY, STORAGE_REDIS, CONSUMER_MODE, STANDALONE_MODE } from '@splitsoftware/splitio-commons/src/utils/constants';
import { LOCALHOST_MODE, STORAGE_MEMORY, STORAGE_REDIS, STORAGE_PLUGGABLE, CONSUMER_MODE, STANDALONE_MODE } from '@splitsoftware/splitio-commons/src/utils/constants';

export function validateStorage(settings) {
const {
Expand All @@ -11,7 +11,7 @@ export function validateStorage(settings) {
} = { type: STORAGE_MEMORY }
} = settings;

// We can have MEMORY, REDIS or an invalid storage type
// We can have MEMORY, REDIS, PLUGGABLE or an invalid storage type
switch (type) {
case STORAGE_REDIS: {
// If passing REDIS storage in localhost or standalone mode, we log an error and fallback to MEMORY storage
Expand Down Expand Up @@ -68,11 +68,28 @@ export function validateStorage(settings) {
};
}

case STORAGE_PLUGGABLE: {
// If passing PLUGGABLE storage in localhost or standalone mode, we log an error and fallback to MEMORY storage
if (mode === STANDALONE_MODE || mode === LOCALHOST_MODE) {
log.error('The provided PLUGGABLE storage is invalid for this mode. It requires consumer mode. Fallback into default MEMORY storage.');
return {
type: STORAGE_MEMORY,
prefix
};
}

return {
type,
prefix,
options
};
}

// For now, we don't have modifiers or settings for MEMORY in Node.js
case STORAGE_MEMORY:
default: {
// If passing MEMORY storage in consumer mode, throw an error (no way to fallback to REDIS storage)
if (mode === CONSUMER_MODE) throw new Error('A REDIS storage is required on consumer mode');
// If passing MEMORY storage in consumer mode, throw an error (no way to fallback to an async storage)
if (mode === CONSUMER_MODE) throw new Error('A REDIS or PLUGGABLE storage is required on consumer mode');
// If passing an invalid storage type, log an error
if (type !== STORAGE_MEMORY) log.error(`The provided '${type}' storage type is invalid. Fallback into default MEMORY storage.`);
return {
Expand Down