Skip to content

Commit 96071a4

Browse files
Merge pull request #438 from splitio/readiness-sdk-ready-from-cache
Update SDK_READY_FROM_CACHE event to be emitted alongside SDK_READY event
2 parents 9163c48 + 8b6a8d5 commit 96071a4

File tree

14 files changed

+42
-45
lines changed

14 files changed

+42
-45
lines changed

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2.8.0 (October XX, 2025)
2+
- Updated the SDK_READY_FROM_CACHE event to be emitted alongside the SDK_READY event if it hasn’t already been emitted.
3+
14
2.7.1 (October 8, 2025)
25
- Bugfix - Update `debug` option to support log levels when `logger` option is used.
36

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/readiness/readinessManager.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { ISettings } from '../types';
33
import SplitIO from '../../types/splitio';
44
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED, SDK_SEGMENTS_ARRIVED, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE, SDK_READY } from './constants';
55
import { IReadinessEventEmitter, IReadinessManager, ISegmentsEventEmitter, ISplitsEventEmitter } from './types';
6-
import { STORAGE_LOCALSTORAGE } from '../utils/constants';
76

87
function splitsEventEmitterFactory(EventEmitter: new () => SplitIO.IEventEmitter): ISplitsEventEmitter {
98
const splitsEventEmitter = objectAssign(new EventEmitter(), {
@@ -115,7 +114,7 @@ export function readinessManagerFactory(
115114
isReady = true;
116115
try {
117116
syncLastUpdate();
118-
if (!isReadyFromCache && settings.storage?.type === STORAGE_LOCALSTORAGE) {
117+
if (!isReadyFromCache) {
119118
isReadyFromCache = true;
120119
gate.emit(SDK_READY_FROM_CACHE);
121120
}

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();

0 commit comments

Comments
 (0)