Skip to content

Commit

Permalink
expirationDays configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
EmilianoSanchez committed Dec 18, 2024
1 parent 9b8d36a commit 87fbc4f
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 14 deletions.
4 changes: 3 additions & 1 deletion src/storages/dataLoader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { PreloadedData } from '../types';
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../utils/constants/browser';
import { DataLoader, ISegmentsCacheSync, ISplitsCacheSync } from './types';

// This value might be eventually set via a config parameter
const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days

/**
* Factory of client-side storage loader
*
Expand Down
2 changes: 1 addition & 1 deletion src/storages/inLocalStorage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,

validateCache() {
return validateCache(settings, keys, splits, segments, largeSegments);
return validateCache(options, settings, keys, splits, segments, largeSegments);
},

destroy() { },
Expand Down
23 changes: 15 additions & 8 deletions src/storages/inLocalStorage/validateCache.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import { ISettings } from '../../types';
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
import { isNaNNumber } from '../../utils/lang';
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
import { getStorageHash } from '../KeyBuilder';
import { LOG_PREFIX } from './constants';
import type { SplitsCacheInLocal } from './SplitsCacheInLocal';
import type { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
import { KeyBuilderCS } from '../KeyBuilderCS';
import SplitIO from '../../../types/splitio';

function validateExpiration(settings: ISettings, keys: KeyBuilderCS) {
// milliseconds in a day
const DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
const MILLIS_IN_A_DAY = 86400000;

function validateExpiration(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS) {
const { log } = settings;

// Check expiration
const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
const expirationTimestamp = Date.now() - MILLIS_IN_A_DAY * (isFiniteNumber(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS);
let value: string | number | null = localStorage.getItem(keys.buildLastUpdatedKey());
if (value !== null) {
value = parseInt(value, 10);
if (!isNaNNumber(value) && value < expirationTimestamp) return true;
if (!isNaNNumber(value) && value < expirationTimestamp) {
log.info(LOG_PREFIX + 'Cache expired. Cleaning up cache');
return true;
}
}

// Check hash
Expand All @@ -24,7 +31,7 @@ function validateExpiration(settings: ISettings, keys: KeyBuilderCS) {
const currentStorageHash = getStorageHash(settings);

if (storageHash !== currentStorageHash) {
log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Cleaning up cache');
try {
localStorage.setItem(storageHashKey, currentStorageHash);
} catch (e) {
Expand All @@ -39,9 +46,9 @@ function validateExpiration(settings: ISettings, keys: KeyBuilderCS) {
* - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
* - hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
*/
export function validateCache(settings: ISettings, keys: KeyBuilderCS, splits: SplitsCacheInLocal, segments: MySegmentsCacheInLocal, largeSegments: MySegmentsCacheInLocal): boolean {
export function validateCache(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, splits: SplitsCacheInLocal, segments: MySegmentsCacheInLocal, largeSegments: MySegmentsCacheInLocal): boolean {

if (validateExpiration(settings, keys)) {
if (validateExpiration(options, settings, keys)) {
splits.clear();
segments.clear();
largeSegments.clear();
Expand Down
2 changes: 0 additions & 2 deletions src/utils/constants/browser.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/utils/lang/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export function isBoolean(val: any): boolean {
* Unlike `Number.isFinite`, it also tests Number object instances.
* Unlike global `isFinite`, it returns false if the value is not a number or Number object instance.
*/
export function isFiniteNumber(val: any): boolean {
export function isFiniteNumber(val: any): val is number {
if (val instanceof Number) val = val.valueOf();
return typeof val === 'number' ?
Number.isFinite ? Number.isFinite(val) : isFinite(val) :
Expand Down
26 changes: 25 additions & 1 deletion types/splitio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,18 @@ declare namespace SplitIO {
* @defaultValue `'SPLITIO'`
*/
prefix?: string;
/**
* Number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
*
* @defaultValue `10`
*/
expirationDays?: number;
/**
* Optional settings to clear the cache. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
*
* @defaultValue `false`
*/
clearOnInit?: boolean;
}
/**
* Storage for asynchronous (consumer) SDK.
Expand Down Expand Up @@ -1229,11 +1241,23 @@ declare namespace SplitIO {
*/
type?: BrowserStorage;
/**
* Optional prefix to prevent any kind of data collision between SDK versions.
* Optional prefix to prevent any kind of data collision between SDK versions when using 'LOCALSTORAGE'.
*
* @defaultValue `'SPLITIO'`
*/
prefix?: string;
/**
* Optional settings for the 'LOCALSTORAGE' storage type. It specifies the number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
*
* @defaultValue `10`
*/
expirationDays?: number;
/**
* Optional settings for the 'LOCALSTORAGE' storage type. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
*
* @defaultValue `false`
*/
clearOnInit?: boolean;
};
}
/**
Expand Down

0 comments on commit 87fbc4f

Please sign in to comment.