-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change LRUDiskCache to allow subclasses to override functionality #554
base: feat/cacheOptions
Are you sure you want to change the base?
Changes from all commits
e2fcf91
4145372
5c5983e
c867b0f
9c1ca53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,14 +5,17 @@ import { outputJSON, readJSON, remove } from 'fs-extra' | |
import LRU from 'lru-cache' | ||
import { join } from 'path' | ||
import ReadWriteLock from 'rwlock' | ||
import { LocalCacheOptions } from '../HttpClient' | ||
|
||
export type LRUData = Record<string, unknown> & { timeOfDeath: number } | ||
|
||
export class LRUDiskCache<V> implements CacheLayer<string, V>{ | ||
|
||
protected disposed: number | ||
protected hits = 0 | ||
protected total = 0 | ||
private lock: ReadWriteLock | ||
private disposed: number | ||
private hits = 0 | ||
private total = 0 | ||
private lruStorage: LRU<string, number> | ||
private lruStorage: LRU<string, LRUData> | ||
private keyToBeDeleted: string | ||
|
||
constructor(private cachePath: string, options: LRUDiskCacheOptions, private readFile=readJSON, private writeFile=outputJSON) { | ||
|
@@ -33,11 +36,13 @@ export class LRUDiskCache<V> implements CacheLayer<string, V>{ | |
noDisposeOnSet: true, | ||
} | ||
|
||
this.lruStorage = new LRU<string, number>(lruOptions) | ||
this.lruStorage = new LRU<string, LRUData>(lruOptions) | ||
|
||
} | ||
|
||
public has = (key: string): boolean => this.lruStorage.has(key) | ||
public has (key: string): boolean { | ||
return this.lruStorage.has(key) | ||
} | ||
|
||
public getStats = (name='disk-lru-cache'): LRUStats => { | ||
const stats = { | ||
|
@@ -56,10 +61,10 @@ export class LRUDiskCache<V> implements CacheLayer<string, V>{ | |
return stats | ||
} | ||
|
||
public get = async (key: string): Promise<V | void> => { | ||
const timeOfDeath = this.lruStorage.get(key) | ||
public async get (key: string): Promise<V | void> { | ||
const lruData = this.lruStorage.get(key) | ||
this.total += 1 | ||
if (timeOfDeath === undefined) { | ||
if (lruData === undefined) { | ||
|
||
// if it is an outdated file when stale=false | ||
if (this.keyToBeDeleted) { | ||
|
@@ -85,23 +90,18 @@ export class LRUDiskCache<V> implements CacheLayer<string, V>{ | |
}) | ||
|
||
// if it is an outdated file when stale=true | ||
if (timeOfDeath < Date.now()) { | ||
if (lruData.timeOfDeath < Date.now()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
this.lruStorage.del(key) | ||
await this.deleteFile(key) | ||
} | ||
|
||
return data | ||
} | ||
|
||
public set = async (key: string, value: V, maxAge?: number): Promise<boolean> => { | ||
let timeOfDeath = NaN | ||
if (maxAge) { | ||
timeOfDeath = maxAge + Date.now() | ||
this.lruStorage.set(key, timeOfDeath, maxAge) | ||
} | ||
else { | ||
this.lruStorage.set(key, NaN) | ||
} | ||
public async set (key: string, value: V, maxAge?: number, localCacheOptions?: LocalCacheOptions): Promise<boolean> { | ||
const timeOfDeath = maxAge ? maxAge + Date.now() : NaN | ||
const lruData = this.buildLRUData(timeOfDeath, localCacheOptions) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This just changed the way we build the data to be stored in the memory cache to use the new buildLRUData function. |
||
this.lruStorage.set(key, lruData, maxAge ? maxAge : undefined) | ||
|
||
if (this.keyToBeDeleted && this.keyToBeDeleted !== key) { | ||
await this.deleteFile(this.keyToBeDeleted) | ||
|
@@ -124,6 +124,19 @@ export class LRUDiskCache<V> implements CacheLayer<string, V>{ | |
return !failure | ||
} | ||
|
||
/** | ||
* Builds the data object that will be stored at the LRU memory storage. | ||
* Subclasses that need to store more than just the time of death should | ||
* override this. | ||
*/ | ||
protected buildLRUData(timeOfDeath: number, localCacheOptions?: LocalCacheOptions): LRUData { | ||
return { timeOfDeath } | ||
} | ||
Comment on lines
+127
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The data stored in the memory part of the cache was only the timeOfDeath. This new method will allow storing more data there, for any logic that needs to run before deciding to fetch the file from disk. In our use case this extra data will be the list of fields that we have stored from the original object. |
||
|
||
protected getLRU() { | ||
return this.lruStorage | ||
} | ||
|
||
private getPathKey = (key: string): string => { | ||
return join(this.cachePath, key) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the has/get/set methods syntax because the previous syntax doesn't work properly when a subclass overrides, losing the access to
super
.No changes were made in this one besides the syntax though.