Skip to content

Commit 8179bc4

Browse files
oakbanizashraf1985
andauthored
fix: Revert "refactor: Update datafile-manager to use Async Storage implementation from utils (#508)" (#525)
Summary: This reverts commit 9af51d8. ReactNative Async Storage implementation was previosuly moved to Utils package in order to use it both in Datafile Manager and Event Processor. While testing the new offline storage in event processor, it was observed that event processor asked for installing react-native-community/async storage package even when run for node or browser. This was because we didn't have separate entrypoints in the utils package. It was decided to move react native async storage implementation to both datafile manager and event processor. Test plan: All existing tests should pass Co-authored-by: Zeeshan Ashraf <[email protected]>
1 parent 67bba0a commit 8179bc4

9 files changed

+195
-8
lines changed

packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import HttpPollingDatafileManager from '../src/httpPollingDatafileManager';
1818
import { Headers, AbortableRequest, Response } from '../src/http';
1919
import { DatafileManagerConfig } from '../src/datafileManager';
2020
import { advanceTimersByTime, getTimerCount } from './testUtils';
21-
import { PersistentKeyValueCache } from '@optimizely/js-sdk-utils';
21+
import PersistentKeyValueCache from '../src/persistentKeyValueCache';
2222

2323
jest.mock('../src/backoffController', () => {
2424
return jest.fn().mockImplementation(() => {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Copyright 2020, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import ReactNativeAsyncStorageCache from '../src/reactNativeAsyncStorageCache';
18+
19+
describe('reactNativeAsyncStorageCache', () => {
20+
let cacheInstance: ReactNativeAsyncStorageCache;
21+
22+
beforeEach(() => {
23+
cacheInstance = new ReactNativeAsyncStorageCache();
24+
});
25+
26+
describe('get', function() {
27+
it('should return correct object when item is found in cache', function() {
28+
return cacheInstance.get('keyThatExists').then(v => expect(v).toEqual({ name: 'Awesome Object' }));
29+
});
30+
31+
it('should return null if item is not found in cache', function() {
32+
return cacheInstance.get('keyThatDoesNotExist').then(v => expect(v).toBeNull());
33+
});
34+
35+
it('should reject promise error if string has an incorrect JSON format', function() {
36+
return cacheInstance
37+
.get('keyWithInvalidJsonObject')
38+
.catch(() => 'exception caught')
39+
.then(v => {
40+
expect(v).toEqual('exception caught');
41+
});
42+
});
43+
});
44+
45+
describe('set', function() {
46+
it('should resolve promise if item was successfully set in the cache', function() {
47+
const testObj = { name: 'Awesome Object' };
48+
return cacheInstance.set('testKey', testObj);
49+
});
50+
51+
it('should reject promise if item was not set in the cache because of json stringifying error', function() {
52+
const testObj: any = { name: 'Awesome Object' };
53+
testObj.myOwnReference = testObj;
54+
return cacheInstance
55+
.set('testKey', testObj)
56+
.catch(() => 'exception caught')
57+
.then(v => expect(v).toEqual('exception caught'));
58+
});
59+
});
60+
61+
describe('contains', function() {
62+
it('should return true if object with key exists', function() {
63+
return cacheInstance.contains('keyThatExists').then(v => expect(v).toBeTruthy());
64+
});
65+
66+
it('should return false if object with key does not exist', function() {
67+
return cacheInstance.contains('keyThatDoesNotExist').then(v => expect(v).toBeFalsy());
68+
});
69+
});
70+
});

packages/datafile-manager/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/datafile-manager/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
},
1414
"main": "lib/index.node.js",
1515
"browser": "lib/index.browser.js",
16+
"react-native": "lib/index.react_native.js",
1617
"types": "lib/index.d.ts",
1718
"directories": {
1819
"lib": "lib",
@@ -48,7 +49,7 @@
4849
},
4950
"dependencies": {
5051
"@optimizely/js-sdk-logging": "^0.1.0",
51-
"@optimizely/js-sdk-utils": "^0.3.2",
52+
"@optimizely/js-sdk-utils": "^0.4.0",
5253
"decompress-response": "^4.2.1"
5354
},
5455
"peerDependencies": {

packages/datafile-manager/src/datafileManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import { PersistentKeyValueCache } from '@optimizely/js-sdk-utils';
16+
import PersistentKeyValueCache from './persistentKeyValueCache';
1717

1818
export interface DatafileUpdate {
1919
datafile: object;

packages/datafile-manager/src/httpPollingDatafileManager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
*/
1616

1717
import { getLogger } from '@optimizely/js-sdk-logging';
18-
import { sprintf, PersistentKeyValueCache } from '@optimizely/js-sdk-utils';
18+
import { sprintf } from '@optimizely/js-sdk-utils';
1919
import { DatafileManager, DatafileManagerConfig, DatafileUpdate } from './datafileManager';
2020
import EventEmitter, { Disposer } from './eventEmitter';
2121
import { AbortableRequest, Response, Headers } from './http';
2222
import { DEFAULT_UPDATE_INTERVAL, MIN_UPDATE_INTERVAL, DEFAULT_URL_TEMPLATE } from './config';
2323
import BackoffController from './backoffController';
24+
import PersistentKeyValueCache from './persistentKeyValueCache';
2425

2526
const logger = getLogger('DatafileManager');
2627

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright 2020, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* An Interface to implement a persistent key value cache which supports strings as keys
19+
* and JSON Object as value.
20+
*/
21+
export default interface PersistentKeyValueCache {
22+
/**
23+
* Returns value stored against a key or null if not found.
24+
* @param key
25+
* @returns
26+
* Resolves promise with
27+
* 1. Object if value found was stored as a JSON Object.
28+
* 2. null if the key does not exist in the cache.
29+
* Rejects the promise in case of an error
30+
*/
31+
get(key: string): Promise<any | null>;
32+
33+
/**
34+
* Stores Object in the persistent cache against a key
35+
* @param key
36+
* @param val
37+
* @returns
38+
* Resolves promise without a value if successful
39+
* Rejects the promise in case of an error
40+
*/
41+
set(key: string, val: any): Promise<void>;
42+
43+
/**
44+
* Checks if a key exists in the cache
45+
* @param key
46+
* Resolves promise with
47+
* 1. true if the key exists
48+
* 2. false if the key does not exist
49+
* Rejects the promise in case of an error
50+
*/
51+
contains(key: string): Promise<boolean>;
52+
53+
/**
54+
* Removes the key value pair from cache.
55+
* @param key
56+
* Resolves promise without a value if successful
57+
* Rejects the promise in case of an error
58+
*/
59+
remove(key: string): Promise<void>;
60+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Copyright 2020, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { getLogger } from '@optimizely/js-sdk-logging';
18+
import AsyncStorage from '@react-native-community/async-storage';
19+
20+
import PersistentKeyValueCache from './persistentKeyValueCache';
21+
22+
const logger = getLogger('DatafileManager');
23+
24+
export default class ReactNativeAsyncStorageCache implements PersistentKeyValueCache {
25+
get(key: string): Promise<any | null> {
26+
return AsyncStorage.getItem(key).then((val: string | null) => {
27+
if (!val) {
28+
return null;
29+
}
30+
try {
31+
return JSON.parse(val);
32+
} catch (ex) {
33+
logger.error('Error Parsing Object from cache - %s', ex);
34+
throw ex;
35+
}
36+
});
37+
}
38+
39+
set(key: string, val: any): Promise<void> {
40+
try {
41+
return AsyncStorage.setItem(key, JSON.stringify(val));
42+
} catch (ex) {
43+
logger.error('Error stringifying Object to Json - %s', ex);
44+
return Promise.reject(ex);
45+
}
46+
}
47+
48+
contains(key: string): Promise<boolean> {
49+
return AsyncStorage.getItem(key).then((val: string | null) => val !== null);
50+
}
51+
52+
remove(key: string): Promise<void> {
53+
return AsyncStorage.removeItem(key);
54+
}
55+
}

packages/datafile-manager/src/reactNativeDatafileManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { makeGetRequest } from './browserRequest';
1818
import HttpPollingDatafileManager from './httpPollingDatafileManager';
1919
import { Headers, AbortableRequest } from './http';
2020
import { DatafileManagerConfig } from './datafileManager';
21-
import { ReactNativeAsyncStorageCache } from '@optimizely/js-sdk-utils';
21+
import ReactNativeAsyncStorageCache from './reactNativeAsyncStorageCache';
2222

2323
export default class ReactNativeDatafileManager extends HttpPollingDatafileManager {
2424
protected makeGetRequest(reqUrl: string, headers: Headers): AbortableRequest {

0 commit comments

Comments
 (0)