Skip to content
Prev Previous commit
Next Next commit
refactor: modify cache implementations to store values as a string in…
…stead of 'any' type and update corresponding tests
  • Loading branch information
pthompson127 committed Jul 31, 2020
commit 0b7b8674112c6b3c056fb0c5c95cfbdd24a25bfe
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ class TestDatafileManager extends HttpPollingDatafileManager {
}

const testCache: PersistentKeyValueCache = {
get(key: string): Promise<any | null> {
let val = null;
get(key: string): Promise<string> {
let val = '';
switch (key) {
case 'opt-datafile-keyThatExists':
val = { name: 'keyThatExists' };
val = JSON.stringify({ name: 'keyThatExists' });
break;
}
return Promise.resolve(val);
Expand Down Expand Up @@ -640,9 +640,9 @@ describe('httpPollingDatafileManager', () => {
manager.on('update', updateFn);
manager.start();
await manager.onReady();
expect(manager.get()).toEqual({ name: 'keyThatExists' });
expect(JSON.parse(manager.get())).toEqual({ name: 'keyThatExists' });
await advanceTimersByTime(50);
expect(manager.get()).toEqual({ name: 'keyThatExists' });
expect(JSON.parse(manager.get())).toEqual({ name: 'keyThatExists' });
expect(updateFn).toBeCalledTimes(0);
});

Expand All @@ -657,7 +657,7 @@ describe('httpPollingDatafileManager', () => {
manager.on('update', updateFn);
manager.start();
await manager.onReady();
expect(manager.get()).toEqual({ name: 'keyThatExists' });
expect(JSON.parse(manager.get())).toEqual({ name: 'keyThatExists' });
expect(updateFn).toBeCalledTimes(0);
await advanceTimersByTime(50);
expect(JSON.parse(manager.get())).toEqual({ foo: 'bar' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,46 +24,28 @@ describe('reactNativeAsyncStorageCache', () => {
});

describe('get', function() {
it('should return correct object when item is found in cache', function() {
return cacheInstance.get('keyThatExists').then(v => expect(v).toEqual({ name: 'Awesome Object' }));
it('should return correct string when item is found in cache', function() {
return cacheInstance.get('keyThatExists').then(v => expect(JSON.parse(v)).toEqual({ name: 'Awesome Object' }));
});

it('should return null if item is not found in cache', function() {
return cacheInstance.get('keyThatDoesNotExist').then(v => expect(v).toBeNull());
});

it('should reject promise error if string has an incorrect JSON format', function() {
return cacheInstance
.get('keyWithInvalidJsonObject')
.catch(() => 'exception caught')
.then(v => {
expect(v).toEqual('exception caught');
});
it('should return empty string if item is not found in cache', function() {
return cacheInstance.get('keyThatDoesNotExist').then(v => expect(v).toEqual(''));
});
});

describe('set', function() {
it('should resolve promise if item was successfully set in the cache', function() {
const testObj = { name: 'Awesome Object' };
return cacheInstance.set('testKey', testObj);
});

it('should reject promise if item was not set in the cache because of json stringifying error', function() {
const testObj: any = { name: 'Awesome Object' };
testObj.myOwnReference = testObj;
return cacheInstance
.set('testKey', testObj)
.catch(() => 'exception caught')
.then(v => expect(v).toEqual('exception caught'));
return cacheInstance.set('testKey', JSON.stringify(testObj));
});
});

describe('contains', function() {
it('should return true if object with key exists', function() {
it('should return true if value with key exists', function() {
return cacheInstance.contains('keyThatExists').then(v => expect(v).toBeTruthy());
});

it('should return false if object with key does not exist', function() {
it('should return false if value with key does not exist', function() {
return cacheInstance.contains('keyThatDoesNotExist').then(v => expect(v).toBeFalsy());
});
});
Expand Down
6 changes: 3 additions & 3 deletions packages/datafile-manager/src/httpPollingDatafileManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ function isSuccessStatusCode(statusCode: number): boolean {
}

const noOpKeyValueCache: PersistentKeyValueCache = {
get(): Promise<any | null> {
return Promise.resolve(null);
get(): Promise<string> {
return Promise.resolve('');
},

set(): Promise<void> {
Expand Down Expand Up @@ -329,7 +329,7 @@ export default abstract class HttpPollingDatafileManager implements DatafileMana

setDatafileFromCacheIfAvailable(): void {
this.cache.get(this.cacheKey).then(datafile => {
if (this.isStarted && !this.isReadyPromiseSettled && datafile) {
if (this.isStarted && !this.isReadyPromiseSettled && datafile !== '') {
logger.debug('Using datafile from cache');
this.currentDatafile = datafile;
this.resolveReadyPromise();
Expand Down
11 changes: 5 additions & 6 deletions packages/datafile-manager/src/persistentKeyValueCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,29 @@
*/

/**
* An Interface to implement a persistent key value cache which supports strings as keys
* and JSON Object as value.
* An Interface to implement a persistent key value cache which supports strings as keys and values.
*/
export default interface PersistentKeyValueCache {
/**
* Returns value stored against a key or null if not found.
* @param key
* @returns
* Resolves promise with
* 1. Object if value found was stored as a JSON Object.
* 1. string if value found was stored as a string.
* 2. null if the key does not exist in the cache.
* Rejects the promise in case of an error
*/
get(key: string): Promise<any | null>;
get(key: string): Promise<string>;

/**
* Stores Object in the persistent cache against a key
* Stores string in the persistent cache against a key
* @param key
* @param val
* @returns
* Resolves promise without a value if successful
* Rejects the promise in case of an error
*/
set(key: string, val: any): Promise<void>;
set(key: string, val: string): Promise<void>;

/**
* Checks if a key exists in the cache
Expand Down
23 changes: 5 additions & 18 deletions packages/datafile-manager/src/reactNativeAsyncStorageCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,22 @@
* limitations under the License.
*/

import { getLogger } from '@optimizely/js-sdk-logging';
import AsyncStorage from '@react-native-community/async-storage';

import PersistentKeyValueCache from './persistentKeyValueCache';

const logger = getLogger('DatafileManager');

export default class ReactNativeAsyncStorageCache implements PersistentKeyValueCache {
get(key: string): Promise<any | null> {
get(key: string): Promise<string> {
return AsyncStorage.getItem(key).then((val: string | null) => {
if (!val) {
return null;
}
try {
return JSON.parse(val);
} catch (ex) {
logger.error('Error Parsing Object from cache - %s', ex);
throw ex;
return '';
}
return val;
});
}

set(key: string, val: any): Promise<void> {
try {
return AsyncStorage.setItem(key, JSON.stringify(val));
} catch (ex) {
logger.error('Error stringifying Object to Json - %s', ex);
return Promise.reject(ex);
}
set(key: string, val: string): Promise<void> {
return AsyncStorage.setItem(key, val);
}

contains(key: string): Promise<boolean> {
Expand Down