Skip to content

Commit 2551fc9

Browse files
authored
Merge pull request #125 from Flagsmith/features/cache_options
Cache Options
2 parents b4dc2f8 + c87b888 commit 2551fc9

File tree

22 files changed

+4035
-22
lines changed

22 files changed

+4035
-22
lines changed

flagsmith-core.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const Flagsmith = class {
5353
getFlags = (resolve?:(v?:any)=>any, reject?:(v?:any)=>any) => {
5454
const { onChange, onError, identity, api } = this;
5555
let resolved = false;
56+
this.log("Get Flags")
5657
const handleResponse = ({ flags: features, traits }) => {
5758
if (identity) {
5859
this.withTraits = false;
@@ -183,6 +184,7 @@ const Flagsmith = class {
183184
analyticsInterval= null
184185
api= null
185186
cacheFlags= null
187+
ts= null
186188
enableAnalytics= null
187189
enableLogs= null
188190
environmentID= null
@@ -201,7 +203,7 @@ const Flagsmith = class {
201203
traits= null
202204
dtrum= null
203205
withTraits= null
204-
206+
cacheOptions = {ttl:0, skipAPI: false}
205207
init({
206208
environmentID,
207209
api = defaultAPI,
@@ -219,6 +221,7 @@ const Flagsmith = class {
219221
traits,
220222
_trigger,
221223
state,
224+
cacheOptions,
222225
angularHttpClient,
223226
}: IInitConfig) {
224227

@@ -234,6 +237,10 @@ const Flagsmith = class {
234237
this.identity = identity;
235238
this.withTraits = traits;
236239
this.enableLogs = enableLogs;
240+
this.cacheOptions = cacheOptions? {skipAPI: !!cacheOptions.skipAPI, ttl: cacheOptions.ttl || 0} : this.cacheOptions;
241+
if (!this.cacheOptions.ttl && this.cacheOptions.skipAPI) {
242+
console.warn("Flagsmith: you have set a cache ttl of 0 and are skipping API calls, this means the API will not be hit unless you clear local storage.")
243+
}
237244
this.enableAnalytics = enableAnalytics ? enableAnalytics : false;
238245
this.flags = Object.assign({}, defaultFlags) || {};
239246
this.initialised = true;
@@ -369,12 +376,26 @@ const Flagsmith = class {
369376
if (res) {
370377
try {
371378
var json = JSON.parse(res);
379+
let cachePopulated = false;
372380
if (json && json.api === this.api && json.environmentID === this.environmentID) {
373-
this.setState(json);
374-
this.log("Retrieved flags from cache", json);
381+
let setState = true;
382+
if(this.cacheOptions.ttl){
383+
if (!json.ts || (new Date().valueOf() - json.ts > this.cacheOptions.ttl)) {
384+
if (json.ts) {
385+
this.log("Ignoring cache, timestamp is too old ts:" + json.ts + " ttl: " + this.cacheOptions.ttl + " time elapsed since cache: " + (new Date().valueOf()-json.ts)+"ms")
386+
setState = false;
387+
}
388+
}
389+
}
390+
if (setState) {
391+
cachePopulated = true;
392+
this.setState(json);
393+
this.log("Retrieved flags from cache", json);
394+
}
375395
}
376396

377397
if (this.flags) { // retrieved flags from local storage
398+
378399
if(this.trigger) {
379400
this.trigger()
380401
}
@@ -383,7 +404,10 @@ const Flagsmith = class {
383404
}
384405
this.oldFlags = this.flags;
385406
resolve(true);
386-
if (!preventFetch) {
407+
if (this.cacheOptions.skipAPI && cachePopulated) {
408+
this.log("Skipping API, using cache")
409+
}
410+
if (!preventFetch && (!this.cacheOptions.skipAPI||!cachePopulated)) {
387411
this.getFlags();
388412
}
389413
} else {
@@ -437,6 +461,8 @@ const Flagsmith = class {
437461

438462
identify(userId, traits) {
439463
this.identity = userId;
464+
this.log("Identify: " + this.identity)
465+
440466
if(traits) {
441467
this.withTraits = {
442468
...(this.withTraits||{}),
@@ -455,6 +481,7 @@ const Flagsmith = class {
455481
environmentID: this.environmentID,
456482
flags: this.flags,
457483
identity: this.identity,
484+
ts: this.ts,
458485
traits: this.traits,
459486
evaluationEvent: this.evaluationEvent,
460487
}
@@ -480,6 +507,7 @@ const Flagsmith = class {
480507

481508
updateStorage() {
482509
if (this.cacheFlags) {
510+
this.ts = new Date().valueOf()
483511
const state = JSON.stringify(this.getState());
484512
this.log("Setting storage", state);
485513
AsyncStorage.setItem(FLAGSMITH_KEY, state);

flagsmith-es/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flagsmith-es/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flagsmith-es/isomorphic.js

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

flagsmith-es/isomorphic.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flagsmith-es/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "flagsmith-es",
3-
"version": "3.2.0",
3+
"version": "3.3.0",
44
"description": "Feature flagging to support continuous development. This is an esm equivalent of the standard flagsmith npm module.",
55
"main": "./index.js",
66
"type": "module",

flagsmith-es/react/index.js

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

flagsmith-es/react/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flagsmith-es/types.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,15 @@ export interface IState {
2727
identity?: string;
2828
traits: ITraits;
2929
}
30+
declare type ICacheOptions = {
31+
ttl?: number;
32+
skipAPI?: boolean;
33+
};
3034
export interface IInitConfig {
3135
AsyncStorage?: any;
3236
api?: string;
3337
cacheFlags?: boolean;
38+
cacheOptions?: ICacheOptions;
3439
defaultFlags?: IFlags;
3540
enableAnalytics?: boolean;
3641
enableDynatrace?: boolean;
@@ -113,4 +118,9 @@ export interface IFlagsmith {
113118
* Used internally, this function will callback separately to onChange whenever flags are updated
114119
*/
115120
trigger?: () => {};
121+
cacheOptions: {
122+
ttl: number;
123+
skipAPI: boolean;
124+
};
116125
}
126+
export {};

flagsmith/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)