Skip to content

Commit e002ede

Browse files
Merge pull request #21 from splitio/pluggable_storage_segments_cache
[Pluggable storage] segments cache, consumer methods
2 parents ee05fe5 + 05ccd7d commit e002ede

21 files changed

Lines changed: 589 additions & 169 deletions

src/storages/inLocalStorage/MySegmentsCacheInLocal.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ILogger } from '../../logger/types';
22
import AbstractSegmentsCacheSync from '../AbstractSegmentsCacheSync';
33
import KeyBuilderCS from '../KeyBuilderCS';
4-
import { logPrefix, DEFINED } from './constants';
4+
import { LOG_PREFIX, DEFINED } from './constants';
55

66
export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
77

@@ -20,7 +20,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
2020
* @NOTE this method is not being used at the moment.
2121
*/
2222
clear() {
23-
this.log.info(logPrefix + 'Flushing MySegments data from localStorage');
23+
this.log.info(LOG_PREFIX + 'Flushing MySegments data from localStorage');
2424

2525
// We cannot simply call `localStorage.clear()` since that implies removing user items from the storage
2626
// We could optimize next sentence, since it implies iterating over all localStorage items
@@ -34,7 +34,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
3434
localStorage.setItem(segmentKey, DEFINED);
3535
return true;
3636
} catch (e) {
37-
this.log.error(logPrefix + e);
37+
this.log.error(LOG_PREFIX + e);
3838
return false;
3939
}
4040
}
@@ -46,7 +46,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
4646
localStorage.removeItem(segmentKey);
4747
return true;
4848
} catch (e) {
49-
this.log.error(logPrefix + e);
49+
this.log.error(LOG_PREFIX + e);
5050
return false;
5151
}
5252
}

src/storages/inLocalStorage/SplitsCacheInLocal.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import AbstractSplitsCacheSync, { usesSegments } from '../AbstractSplitsCacheSyn
33
import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
44
import KeyBuilderCS from '../KeyBuilderCS';
55
import { ILogger } from '../../logger/types';
6-
import { logPrefix } from './constants';
6+
import { LOG_PREFIX } from './constants';
77

88
/**
99
* ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
@@ -52,7 +52,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
5252
}
5353
}
5454
} catch (e) {
55-
this.log.error(logPrefix + e);
55+
this.log.error(LOG_PREFIX + e);
5656
}
5757
}
5858

@@ -72,7 +72,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
7272
}
7373
}
7474
} catch (e) {
75-
this.log.error(logPrefix + e);
75+
this.log.error(LOG_PREFIX + e);
7676
}
7777
}
7878

@@ -82,7 +82,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
8282
* We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
8383
*/
8484
clear() {
85-
this.log.info(logPrefix + 'Flushing Splits data from localStorage');
85+
this.log.info(LOG_PREFIX + 'Flushing Splits data from localStorage');
8686

8787
// collect item keys
8888
const len = localStorage.length;
@@ -114,7 +114,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
114114

115115
return true;
116116
} catch (e) {
117-
this.log.error(logPrefix + e);
117+
this.log.error(LOG_PREFIX + e);
118118
return false;
119119
}
120120
}
@@ -129,7 +129,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
129129

130130
return true;
131131
} catch (e) {
132-
this.log.error(logPrefix + e);
132+
this.log.error(LOG_PREFIX + e);
133133
return false;
134134
}
135135
}
@@ -147,14 +147,14 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
147147

148148
// when using a new split query, we must update it at the store
149149
if (this.updateNewFilter) {
150-
this.log.info(logPrefix + 'Split filter query was modified. Updating cache.');
150+
this.log.info(LOG_PREFIX + 'Split filter query was modified. Updating cache.');
151151
const queryKey = this.keys.buildSplitsFilterQueryKey();
152152
const queryString = this.splitFiltersValidation.queryString;
153153
try {
154154
if (queryString) localStorage.setItem(queryKey, queryString);
155155
else localStorage.removeItem(queryKey);
156156
} catch (e) {
157-
this.log.error(logPrefix + e);
157+
this.log.error(LOG_PREFIX + e);
158158
}
159159
this.updateNewFilter = false;
160160
}
@@ -166,7 +166,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
166166
this.hasSync = true;
167167
return true;
168168
} catch (e) {
169-
this.log.error(logPrefix + e);
169+
this.log.error(LOG_PREFIX + e);
170170
return false;
171171
}
172172
}
@@ -273,7 +273,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync {
273273
});
274274
}
275275
} catch (e) {
276-
this.log.error(logPrefix + e);
276+
this.log.error(LOG_PREFIX + e);
277277
}
278278
}
279279
// if the filter didn't change, nothing is done
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export const logPrefix = 'storage:localstorage: ';
1+
export const LOG_PREFIX = 'storage:localstorage: ';
22
export const DEFINED = '1';

src/storages/inLocalStorage/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import MySegmentsCacheInMemory from '../inMemory/MySegmentsCacheInMemory';
1010
import SplitsCacheInMemory from '../inMemory/SplitsCacheInMemory';
1111
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
1212
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
13-
import { logPrefix } from './constants';
13+
import { LOG_PREFIX } from './constants';
1414

1515
export interface InLocalStorageOptions {
1616
prefix?: string
@@ -27,7 +27,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}) {
2727

2828
// Fallback to InMemoryStorage if LocalStorage API is not available
2929
if (!isLocalStorageAvailable()) {
30-
params.log.warn(logPrefix + 'LocalStorage API is unavailable. Fallbacking into default MEMORY storage');
30+
params.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Fallbacking into default MEMORY storage');
3131
return InMemoryStorageCSFactory(params);
3232
}
3333

src/storages/inRedis/EventsCacheInRedis.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import KeyBuilderSS from '../KeyBuilderSS';
44
import { Redis } from 'ioredis';
55
import { SplitIO } from '../../types';
66
import { ILogger } from '../../logger/types';
7-
8-
const logPrefix = 'storage:redis: ';
7+
import { LOG_PREFIX } from './constants';
98

109
export default class EventsCacheInRedis implements IEventsCacheAsync {
1110

@@ -33,7 +32,7 @@ export default class EventsCacheInRedis implements IEventsCacheAsync {
3332
// We use boolean values to signal successful queueing
3433
.then(() => true)
3534
.catch(err => {
36-
this.log.error(logPrefix + `Error adding event to queue: ${err}.`);
35+
this.log.error(LOG_PREFIX + `Error adding event to queue: ${err}.`);
3736
return false;
3837
});
3938
}

src/storages/inRedis/RedisAdapter.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { _Set, setToArray, ISet } from '../../utils/lang/sets';
55
import thenable from '../../utils/promise/thenable';
66
import timeout from '../../utils/promise/timeout';
77

8-
const logPrefix = 'storage:redis-adapter: ';
8+
const LOG_PREFIX = 'storage:redis-adapter: ';
99

1010
// If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis.
1111
const METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'pipeline', 'expire', 'mget'];
@@ -55,16 +55,16 @@ export default class RedisAdapter extends ioredis {
5555
_listenToEvents() {
5656
this.once('ready', () => {
5757
const commandsCount = this._notReadyCommandsQueue ? this._notReadyCommandsQueue.length : 0;
58-
this.log.info(logPrefix + `Redis connection established. Queued commands: ${commandsCount}.`);
58+
this.log.info(LOG_PREFIX + `Redis connection established. Queued commands: ${commandsCount}.`);
5959
this._notReadyCommandsQueue && this._notReadyCommandsQueue.forEach(queued => {
60-
this.log.info(logPrefix + `Executing queued ${queued.name} command.`);
60+
this.log.info(LOG_PREFIX + `Executing queued ${queued.name} command.`);
6161
queued.command().then(queued.resolve).catch(queued.reject);
6262
});
6363
// After the SDK is ready for the first time we'll stop queueing commands. This is just so we can keep handling BUR for them.
6464
this._notReadyCommandsQueue = undefined;
6565
});
6666
this.once('close', () => {
67-
this.log.info(logPrefix + 'Redis connection closed.');
67+
this.log.info(LOG_PREFIX + 'Redis connection closed.');
6868
});
6969
}
7070

@@ -78,7 +78,7 @@ export default class RedisAdapter extends ioredis {
7878
const params = arguments;
7979

8080
function commandWrapper() {
81-
instance.log.debug(logPrefix + `Executing ${method}.`);
81+
instance.log.debug(LOG_PREFIX + `Executing ${method}.`);
8282
// Return original method
8383
const result = originalMethod.apply(instance, params);
8484

@@ -93,7 +93,7 @@ export default class RedisAdapter extends ioredis {
9393
result.then(cleanUpRunningCommandsCb, cleanUpRunningCommandsCb);
9494

9595
return timeout(instance._options.operationTimeout, result).catch(err => {
96-
instance.log.error(logPrefix + `${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`);
96+
instance.log.error(LOG_PREFIX + `${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`);
9797
// Handling is not the adapter responsibility.
9898
throw err;
9999
});
@@ -126,19 +126,19 @@ export default class RedisAdapter extends ioredis {
126126

127127
setTimeout(function deferedDisconnect() {
128128
if (instance._runningCommands.size > 0) {
129-
instance.log.info(logPrefix + `Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`);
129+
instance.log.info(LOG_PREFIX + `Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`);
130130

131131
Promise.all(setToArray(instance._runningCommands))
132132
.then(() => {
133-
instance.log.debug(logPrefix + 'Pending commands finished successfully, disconnecting.');
133+
instance.log.debug(LOG_PREFIX + 'Pending commands finished successfully, disconnecting.');
134134
originalMethod.apply(instance, params);
135135
})
136136
.catch(e => {
137-
instance.log.warn(logPrefix + `Pending commands finished with error: ${e}. Proceeding with disconnection.`);
137+
instance.log.warn(LOG_PREFIX + `Pending commands finished with error: ${e}. Proceeding with disconnection.`);
138138
originalMethod.apply(instance, params);
139139
});
140140
} else {
141-
instance.log.debug(logPrefix + 'No commands pending execution, disconnect.');
141+
instance.log.debug(LOG_PREFIX + 'No commands pending execution, disconnect.');
142142
// Nothing pending, just proceed.
143143
originalMethod.apply(instance, params);
144144
}

src/storages/inRedis/SplitsCacheInRedis.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import KeyBuilderSS from '../KeyBuilderSS';
33
import { ISplitsCacheAsync } from '../types';
44
import { Redis } from 'ioredis';
55
import { ILogger } from '../../logger/types';
6-
import { SplitError } from '../../utils/lang/errors';
7-
8-
const logPrefix = 'storage:redis: ';
6+
import { LOG_PREFIX } from './constants';
97

108
/**
119
* Discard errors for an answer of multiple operations.
@@ -90,11 +88,11 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync {
9088

9189
/**
9290
* Get split definition or null if it's not defined.
93-
* Returned promise is Rejected with an SplitError if redis operation fails.
91+
* Returned promise is rejected if redis operation fails.
9492
*/
9593
getSplit(name: string): Promise<string | null> {
9694
if (this.redisError) {
97-
this.log.error(logPrefix + this.redisError);
95+
this.log.error(LOG_PREFIX + this.redisError);
9896

9997
return Promise.reject(this.redisError); // no need to wrap as an SplitError
10098
}
@@ -150,14 +148,14 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync {
150148

151149
ttCount = parseInt(ttCount as string, 10);
152150
if (!isFiniteNumber(ttCount) || ttCount < 0) {
153-
this.log.info(logPrefix + `Could not validate traffic type existence of ${trafficType} due to data corruption of some sorts.`);
151+
this.log.info(LOG_PREFIX + `Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`);
154152
return false;
155153
}
156154

157155
return ttCount > 0;
158156
})
159157
.catch(e => {
160-
this.log.error(logPrefix + `Could not validate traffic type existence of ${trafficType} due to an error: ${e}.`);
158+
this.log.error(LOG_PREFIX + `Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`);
161159
// If there is an error, bypass the validation so the event can get tracked.
162160
return true;
163161
});
@@ -179,11 +177,11 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync {
179177

180178
/**
181179
* Fetches multiple splits definitions.
182-
* Returned promise is Rejected with an SplitError if redis operation fails.
180+
* Returned promise is rejected if redis operation fails.
183181
*/
184182
getSplits(names: string[]): Promise<Record<string, string | null>> {
185183
if (this.redisError) {
186-
this.log.error(logPrefix + this.redisError);
184+
this.log.error(LOG_PREFIX + this.redisError);
187185

188186
return Promise.reject(this.redisError); // no need to wrap as an SplitError
189187
}
@@ -198,8 +196,8 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync {
198196
return Promise.resolve(splits);
199197
})
200198
.catch(e => {
201-
this.log.error(logPrefix + `Could not grab splits due to an error: ${e}.`);
202-
return Promise.reject(new SplitError(e));
199+
this.log.error(LOG_PREFIX + `Could not grab splits due to an error: ${e}.`);
200+
return Promise.reject(e);
203201
});
204202
}
205203

0 commit comments

Comments
 (0)