-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathvalidateCache.ts
More file actions
95 lines (82 loc) · 3.72 KB
/
validateCache.ts
File metadata and controls
95 lines (82 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { ISettings } from '../../types';
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
import { getStorageHash } from '../KeyBuilder';
import { LOG_PREFIX } from './constants';
import type { SplitsCacheInLocal } from './SplitsCacheInLocal';
import type { RBSegmentsCacheInLocal } from './RBSegmentsCacheInLocal';
import type { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
import { KeyBuilderCS } from '../KeyBuilderCS';
import SplitIO from '../../../types/splitio';
const DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
const MILLIS_IN_A_DAY = 86400000;
/**
* Validates if cache should be cleared and sets the cache `hash` if needed.
*
* @returns `true` if cache should be cleared, `false` otherwise
*/
function validateExpiration(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, currentTimestamp: number, isThereCache: boolean) {
const { log } = settings;
// Check expiration
const lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()) as string, 10);
if (!isNaNNumber(lastUpdatedTimestamp)) {
const cacheExpirationInDays = isFiniteNumber(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
const expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
if (lastUpdatedTimestamp < expirationTimestamp) {
log.info(LOG_PREFIX + 'Cache expired more than ' + cacheExpirationInDays + ' days ago. Cleaning up cache');
return true;
}
}
// Check hash
const storageHashKey = keys.buildHashKey();
const storageHash = localStorage.getItem(storageHashKey);
const currentStorageHash = getStorageHash(settings);
if (storageHash !== currentStorageHash) {
try {
localStorage.setItem(storageHashKey, currentStorageHash);
} catch (e) {
log.error(LOG_PREFIX + e);
}
if (isThereCache) {
log.info(LOG_PREFIX + 'SDK key, flags filter criteria, or flags spec version has changed. Cleaning up cache');
return true;
}
return false; // No cache to clear
}
// Clear on init
if (options.clearOnInit) {
const lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()) as string, 10);
if (isNaNNumber(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
log.info(LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
return true;
}
}
}
/**
* Clean cache if:
* - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
* - its hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
* - `clearOnInit` was set and cache was not cleared in the last 24 hours
*
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
*/
export function validateCache(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, splits: SplitsCacheInLocal, rbSegments: RBSegmentsCacheInLocal, segments: MySegmentsCacheInLocal, largeSegments: MySegmentsCacheInLocal): Promise<boolean> {
return Promise.resolve().then(() => {
const currentTimestamp = Date.now();
const isThereCache = splits.getChangeNumber() > -1;
if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
splits.clear();
rbSegments.clear();
segments.clear();
largeSegments.clear();
// Update last clear timestamp
try {
localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
} catch (e) {
settings.log.error(LOG_PREFIX + e);
}
return false;
}
// Check if ready from cache
return isThereCache;
});
}