Skip to content
Draft
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
61 changes: 0 additions & 61 deletions src/readiness/__tests__/sdkReadinessManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,64 +299,3 @@ describe('SDK Readiness Manager - Promises', () => {
expect(loggerMock.warn).not.toBeCalled(); // But if we have a listener or call the whenReady method, we get no warnings.
});
});

// @TODO: remove in next major
describe('SDK Readiness Manager - Ready promise', () => {

beforeEach(() => { loggerMock.mockClear(); });

test('ready promise count as a callback and resolves on SDK_READY', (done) => {
const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, fullSettings);
const readyPromise = sdkReadinessManager.sdkStatus.ready();

// Get the callback
const readyEventCB = sdkReadinessManager.readinessManager.gate.once.mock.calls[0][1];

readyEventCB();
expect(loggerMock.warn).toBeCalledWith(CLIENT_NO_LISTENER); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise.
loggerMock.warn.mockClear();

readyPromise.then(() => {
expect('The ready promise is resolved when the gate emits SDK_READY.');
done();
}, () => {
throw new Error('This should not be called as the promise is being resolved.');
});

readyEventCB();
expect(loggerMock.warn).not.toBeCalled(); // But if we have a listener there are no warnings.
});

test('.ready() rejected promises have a default onRejected handler that just logs the error', (done) => {
const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, fullSettings);
let readyForTimeout = sdkReadinessManager.sdkStatus.ready();

emitTimeoutEvent(sdkReadinessManager.readinessManager); // make the SDK "timed out"

readyForTimeout.then(
() => { throw new Error('It should be a promise that was rejected on SDK_READY_TIMED_OUT, not resolved.'); }
);

expect(loggerMock.error).not.toBeCalled(); // not called until promise is rejected

setTimeout(() => {
expect(loggerMock.error.mock.calls).toEqual([[timeoutErrorMessage]]); // If we don\'t handle the rejected promise, an error is logged.
readyForTimeout = sdkReadinessManager.sdkStatus.ready();

setTimeout(() => {
expect(loggerMock.error).lastCalledWith('Split SDK has emitted SDK_READY_TIMED_OUT event.'); // If we don\'t handle a new .ready() rejected promise, an error is logged.
readyForTimeout = sdkReadinessManager.sdkStatus.ready();

readyForTimeout
.then(() => { throw new Error(); })
.then(() => { throw new Error(); })
.catch((error) => {
expect(error instanceof Error).toBe(true);
expect(error.message).toBe('Split SDK has emitted SDK_READY_TIMED_OUT event.');
expect(loggerMock.error).toBeCalledTimes(2); // If we provide an onRejected handler, even chaining several onFulfilled handlers, the error is not logged.
done();
});
}, 0);
}, 0);
});
});
45 changes: 9 additions & 36 deletions src/readiness/sdkReadinessManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { objectAssign } from '../utils/lang/objectAssign';
import { promiseWrapper } from '../utils/promise/wrapper';
import { readinessManagerFactory } from './readinessManager';
import { ISdkReadinessManager } from './types';
import { ISettings } from '../types';
Expand Down Expand Up @@ -44,33 +43,19 @@ export function sdkReadinessManagerFactory(
}
});

/** Ready promise */
const readyPromise = generateReadyPromise();
readinessManager.gate.once(SDK_READY, () => {
log.info(CLIENT_READY);

readinessManager.gate.once(SDK_READY_FROM_CACHE, () => {
log.info(CLIENT_READY_FROM_CACHE);
if (readyCbCount === internalReadyCbCount) log.warn(CLIENT_NO_LISTENER);
});

// default onRejected handler, that just logs the error, if ready promise doesn't have one.
function defaultOnRejected(err: any) {
log.error(err && err.message);
}

function generateReadyPromise() {
const promise = promiseWrapper(new Promise<void>((resolve, reject) => {
readinessManager.gate.once(SDK_READY, () => {
log.info(CLIENT_READY);

if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn(CLIENT_NO_LISTENER);
resolve();
});
readinessManager.gate.once(SDK_READY_TIMED_OUT, (message: string) => {
reject(new Error(message));
});
}), defaultOnRejected);
readinessManager.gate.once(SDK_READY_TIMED_OUT, (message: string) => {
log.error(message);
});

return promise;
}
readinessManager.gate.once(SDK_READY_FROM_CACHE, () => {
log.info(CLIENT_READY_FROM_CACHE);
});

function getStatus() {
return {
Expand Down Expand Up @@ -107,18 +92,6 @@ export function sdkReadinessManagerFactory(
SDK_READY_TIMED_OUT,
},

// @TODO: remove in next major
ready() {
if (readinessManager.hasTimedout()) {
if (!readinessManager.isReady()) {
return promiseWrapper(Promise.reject(new Error('Split SDK has emitted SDK_READY_TIMED_OUT event.')), defaultOnRejected);
} else {
return Promise.resolve();
}
}
return readyPromise;
},

whenReady() {
return new Promise<SplitIO.SdkReadyMetadata>((resolve, reject) => {
if (readinessManager.isReady()) {
Expand Down
162 changes: 0 additions & 162 deletions src/utils/promise/__tests__/wrapper.spec.ts

This file was deleted.

60 changes: 0 additions & 60 deletions src/utils/promise/wrapper.ts

This file was deleted.

19 changes: 0 additions & 19 deletions types/splitio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -809,25 +809,6 @@ declare namespace SplitIO {
* @returns The current readiness status.
*/
getStatus(): ReadinessStatus;
/**
* Returns a promise that resolves when the SDK has finished initial synchronization with the backend (`SDK_READY` event emitted), or rejected if the SDK has timedout (`SDK_READY_TIMED_OUT` event emitted).
* As it's meant to provide similar flexibility to the event approach, given that the SDK might be eventually ready after a timeout event, the `ready` method will return a resolved promise once the SDK is ready.
*
* Caveats: the method was designed to avoid an unhandled Promise rejection if the rejection case is not handled, so that `onRejected` handler is optional when using promises.
* However, when using async/await syntax, the rejection should be explicitly propagated like in the following example:
* ```
* try {
* await client.ready().catch((e) => { throw e; });
* // SDK is ready
* } catch(e) {
* // SDK has timedout
* }
* ```
*
* @returns A promise that resolves once the SDK is ready or rejects if the SDK has timedout.
* @deprecated Use `whenReady` instead.
*/
ready(): Promise<void>;
/**
* Returns a promise that resolves when the SDK has finished initial synchronization with the backend (`SDK_READY` event emitted), or rejected if the SDK has timedout (`SDK_READY_TIMED_OUT` event emitted).
* As it's meant to provide similar flexibility than event listeners, given that the SDK might be ready after a timeout event, the `whenReady` method will return a resolved promise once the SDK is ready.
Expand Down