Skip to content

Commit 8b6a8d5

Browse files
refactor: simplify SDK readiness checks
1 parent 1724ce8 commit 8b6a8d5

File tree

12 files changed

+38
-43
lines changed

12 files changed

+38
-43
lines changed

src/logger/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const SUBMITTERS_PUSH_PAGE_HIDDEN = 125;
6060
export const ENGINE_VALUE_INVALID = 200;
6161
export const ENGINE_VALUE_NO_ATTRIBUTES = 201;
6262
export const CLIENT_NO_LISTENER = 202;
63-
export const CLIENT_NOT_READY = 203;
63+
export const CLIENT_NOT_READY_FROM_CACHE = 203;
6464
export const SYNC_MYSEGMENTS_FETCH_RETRY = 204;
6565
export const SYNC_SPLITS_FETCH_FAILS = 205;
6666
export const STREAMING_PARSING_ERROR_FAILS = 206;

src/logger/messages/warn.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const codesWarn: [number, string][] = codesError.concat([
1414
[c.SUBMITTERS_PUSH_FAILS, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Dropping %s after retry. Reason: %s.'],
1515
[c.SUBMITTERS_PUSH_RETRY, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Failed to push %s, keeping data to retry on next iteration. Reason: %s.'],
1616
// client status
17-
[c.CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect%s. Make sure to wait for SDK readiness before using this method.'],
17+
[c.CLIENT_NOT_READY_FROM_CACHE, '%s: the SDK is not ready to evaluate. Results may be incorrect%s. Make sure to wait for SDK readiness before using this method.'],
1818
[c.CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'],
1919
// input validation
2020
[c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'],

src/sdkClient/__tests__/clientInputValidation.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const EVALUATION_RESULT = 'on';
1414
const client: any = createClientMock(EVALUATION_RESULT);
1515

1616
const readinessManager: any = {
17-
isReady: () => true,
17+
isReadyFromCache: () => true,
1818
isDestroyed: () => false
1919
};
2020

src/sdkClient/client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
5151
return treatment;
5252
};
5353

54-
const evaluation = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
54+
const evaluation = readinessManager.isReadyFromCache() ?
5555
evaluateFeature(log, key, featureFlagName, attributes, storage) :
5656
isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
5757
Promise.resolve(treatmentNotReady) :
@@ -80,7 +80,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
8080
return treatments;
8181
};
8282

83-
const evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
83+
const evaluations = readinessManager.isReadyFromCache() ?
8484
evaluateFeatures(log, key, featureFlagNames, attributes, storage) :
8585
isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
8686
Promise.resolve(treatmentsNotReady(featureFlagNames)) :
@@ -109,7 +109,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
109109
return treatments;
110110
};
111111

112-
const evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
112+
const evaluations = readinessManager.isReadyFromCache() ?
113113
evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName) :
114114
isAsync ?
115115
Promise.resolve({}) :

src/sdkClient/clientInputValidation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
validateSplits,
1010
validateTrafficType,
1111
validateIfNotDestroyed,
12-
validateIfOperational,
12+
validateIfReadyFromCache,
1313
validateEvaluationOptions
1414
} from '../utils/inputValidation';
1515
import { startsWith } from '../utils/lang';
@@ -46,7 +46,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
4646
const isNotDestroyed = validateIfNotDestroyed(log, readinessManager, methodName);
4747
const options = validateEvaluationOptions(log, maybeOptions, methodName);
4848

49-
validateIfOperational(log, readinessManager, methodName, nameOrNames);
49+
validateIfReadyFromCache(log, readinessManager, methodName, nameOrNames);
5050

5151
const valid = isNotDestroyed && key && nameOrNames && attributes !== false;
5252

src/sdkManager/__tests__/index.asyncCache.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import SplitIO from '../../../types/splitio';
1515
const sdkReadinessManagerMock = {
1616
readinessManager: {
1717
isReady: jest.fn(() => true),
18+
isReadyFromCache: jest.fn(() => true),
1819
isDestroyed: jest.fn(() => false)
1920
},
2021
sdkStatus: jest.fn()
@@ -77,7 +78,7 @@ describe('Manager with async cache', () => {
7778
const cache = new SplitsCachePluggable(loggerMock, keys, wrapperAdapter(loggerMock, {}));
7879
const manager = sdkManagerFactory({ mode: 'consumer_partial', log: loggerMock }, cache, sdkReadinessManagerMock);
7980

80-
expect(await manager.split('some_spplit')).toEqual(null);
81+
expect(await manager.split('some_split')).toEqual(null);
8182
expect(await manager.splits()).toEqual([]);
8283
expect(await manager.names()).toEqual([]);
8384

@@ -98,7 +99,7 @@ describe('Manager with async cache', () => {
9899
const manager = sdkManagerFactory({ mode: 'consumer_partial', log: loggerMock }, {}, sdkReadinessManagerMock) as SplitIO.IAsyncManager;
99100

100101
function validateManager() {
101-
expect(manager.split('some_spplit')).resolves.toBe(null);
102+
expect(manager.split('some_split')).resolves.toBe(null);
102103
expect(manager.splits()).resolves.toEqual([]);
103104
expect(manager.names()).resolves.toEqual([]);
104105
}

src/sdkManager/__tests__/index.syncCache.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { loggerMock } from '../../logger/__tests__/sdkLogger.mock';
99
const sdkReadinessManagerMock = {
1010
readinessManager: {
1111
isReady: jest.fn(() => true),
12+
isReadyFromCache: jest.fn(() => true),
1213
isDestroyed: jest.fn(() => false)
1314
},
1415
sdkStatus: jest.fn()
@@ -62,7 +63,7 @@ describe('Manager with sync cache (In Memory)', () => {
6263
sdkReadinessManagerMock.readinessManager.isDestroyed = () => true;
6364

6465
function validateManager() {
65-
expect(manager.split('some_spplit')).toBe(null);
66+
expect(manager.split('some_split')).toBe(null);
6667
expect(manager.splits()).toEqual([]);
6768
expect(manager.names()).toEqual([]);
6869
}

src/sdkManager/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { objectAssign } from '../utils/lang/objectAssign';
22
import { thenable } from '../utils/promise/thenable';
33
import { find } from '../utils/lang';
4-
import { validateSplit, validateSplitExistence, validateIfNotDestroyed, validateIfOperational } from '../utils/inputValidation';
4+
import { validateSplit, validateSplitExistence, validateIfOperational } from '../utils/inputValidation';
55
import { ISplitsCacheAsync, ISplitsCacheSync } from '../storages/types';
66
import { ISdkReadinessManager } from '../readiness/types';
77
import { ISplit } from '../dtos/types';
@@ -66,7 +66,7 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
6666
*/
6767
split(featureFlagName: string) {
6868
const splitName = validateSplit(log, featureFlagName, SPLIT_FN_LABEL);
69-
if (!validateIfNotDestroyed(log, readinessManager, SPLIT_FN_LABEL) || !validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
69+
if (!validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
7070
return isAsync ? Promise.resolve(null) : null;
7171
}
7272

@@ -87,7 +87,7 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
8787
* Get the feature flag objects present on the factory storage
8888
*/
8989
splits() {
90-
if (!validateIfNotDestroyed(log, readinessManager, SPLITS_FN_LABEL) || !validateIfOperational(log, readinessManager, SPLITS_FN_LABEL)) {
90+
if (!validateIfOperational(log, readinessManager, SPLITS_FN_LABEL)) {
9191
return isAsync ? Promise.resolve([]) : [];
9292
}
9393
const currentSplits = splits.getAll();
@@ -100,7 +100,7 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
100100
* Get the feature flag names present on the factory storage
101101
*/
102102
names() {
103-
if (!validateIfNotDestroyed(log, readinessManager, NAMES_FN_LABEL) || !validateIfOperational(log, readinessManager, NAMES_FN_LABEL)) {
103+
if (!validateIfOperational(log, readinessManager, NAMES_FN_LABEL)) {
104104
return isAsync ? Promise.resolve([]) : [];
105105
}
106106
const splitNames = splits.getSplitNames();
Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { CLIENT_NOT_READY, ERROR_CLIENT_DESTROYED } from '../../../logger/constants';
1+
import { CLIENT_NOT_READY_FROM_CACHE, ERROR_CLIENT_DESTROYED } from '../../../logger/constants';
22
import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock';
33

4-
import { validateIfNotDestroyed, validateIfOperational } from '../isOperational';
4+
import { validateIfNotDestroyed, validateIfReadyFromCache } from '../isOperational';
55

66
describe('validateIfNotDestroyed', () => {
77

@@ -28,37 +28,25 @@ describe('validateIfNotDestroyed', () => {
2828
});
2929
});
3030

31-
describe('validateIfOperational', () => {
32-
33-
test('Should return true and log nothing if the SDK was ready.', () => {
34-
const readinessManagerMock = { isReady: jest.fn(() => true) };
35-
36-
// @ts-ignore
37-
expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready.
38-
expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for readiness status using the context.
39-
expect(loggerMock.warn).not.toBeCalled(); // But it should not log any warnings.
40-
expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors.
41-
});
31+
describe('validateIfReadyFromCache', () => {
4232

4333
test('Should return true and log nothing if the SDK was ready from cache.', () => {
44-
const readinessManagerMock = { isReady: jest.fn(() => false), isReadyFromCache: jest.fn(() => true) };
34+
const readinessManagerMock = { isReadyFromCache: jest.fn(() => true) };
4535

4636
// @ts-ignore
47-
expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready.
48-
expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for SDK_READY status.
37+
expect(validateIfReadyFromCache(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready.
4938
expect(readinessManagerMock.isReadyFromCache).toBeCalledTimes(1); // It checks for SDK_READY_FROM_CACHE status.
5039
expect(loggerMock.warn).not.toBeCalled(); // But it should not log any warnings.
5140
expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors.
5241
});
5342

54-
test('Should return false and log a warning if the SDK was not ready.', () => {
55-
const readinessManagerMock = { isReady: jest.fn(() => false), isReadyFromCache: jest.fn(() => false) };
43+
test('Should return false and log a warning if the SDK was not ready from cache.', () => {
44+
const readinessManagerMock = { isReadyFromCache: jest.fn(() => false) };
5645

5746
// @ts-ignore
58-
expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready.
59-
expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for SDK_READY status.
47+
expect(validateIfReadyFromCache(loggerMock, readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready.
6048
expect(readinessManagerMock.isReadyFromCache).toBeCalledTimes(1); // It checks for SDK_READY_FROM_CACHE status.
61-
expect(loggerMock.warn).toBeCalledWith(CLIENT_NOT_READY, ['test_method', '']); // It should log the expected warning.
49+
expect(loggerMock.warn).toBeCalledWith(CLIENT_NOT_READY_FROM_CACHE, ['test_method', '']); // It should log the expected warning.
6250
expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors.
6351
});
6452
});

src/utils/inputValidation/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export { validateKey } from './key';
77
export { validateSplit } from './split';
88
export { validateSplits } from './splits';
99
export { validateTrafficType } from './trafficType';
10-
export { validateIfNotDestroyed, validateIfOperational } from './isOperational';
10+
export { validateIfNotDestroyed, validateIfReadyFromCache, validateIfOperational } from './isOperational';
1111
export { validateSplitExistence } from './splitExistence';
1212
export { validateTrafficTypeExistence } from './trafficTypeExistence';
1313
export { validateEvaluationOptions } from './eventProperties';

0 commit comments

Comments
 (0)