-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(infra): rework project struct, configure TSC, emit *.d.ts
- Loading branch information
Showing
25 changed files
with
519 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
; | ||
const Node = (data, next) => ({ data, next }); | ||
class FifoCache { | ||
#capacity; | ||
#store; | ||
#map; | ||
constructor(options) { | ||
const { capacity } = options; | ||
if (!Number.isInteger(capacity) || capacity <= 0) | ||
throw new Error('invalid "capacity": positive integer expected'); | ||
this.#capacity = capacity; | ||
// Store is a Singly linked list to support fast add (to tail) and delete (from head) records. | ||
this.#store = { head: null, tail: null }; | ||
// Struct for fast access to cache records, use as <key:reference> lookup table. | ||
this.#map = new Map(); | ||
} | ||
get size() { | ||
return this.#map.size; | ||
} | ||
set capacity(value) { | ||
if (!Number.isInteger(value) || value <= 0) | ||
throw new Error('invalid "capacity": positive integer expected'); | ||
if (value < this.#capacity) { | ||
// @todo: implement | ||
} | ||
this.#capacity = value; | ||
} | ||
read(key) { | ||
if (this.#map.has(key)) { | ||
return this.#map.get(key)?.data.value; | ||
} | ||
return null; | ||
} | ||
store(key, value) { | ||
// check if cache capacity limit is reached | ||
if (this.#map.size === this.#capacity) { | ||
// evict head since we are out of capacity | ||
const node = this.#store.head; | ||
this.#store.head = node.next; | ||
this.#map.delete(node.data.key); | ||
node.next = null; | ||
} | ||
const node = Node({ key, value }); | ||
if (this.#map.size === 0) { | ||
this.#store.head = node; | ||
} | ||
else if (this.#map.size === 1) { | ||
this.#store.tail = node; | ||
this.#store.head.next = this.#store.tail; | ||
} | ||
else { | ||
this.#store.tail.next = node; | ||
this.#store.tail = node; | ||
} | ||
this.#map.set(key, node); | ||
} | ||
has(key) { | ||
return this.#map.has(key); | ||
} | ||
clear() { | ||
this.#store.head = null; | ||
this.#store.tail = null; | ||
this.#map.clear(); | ||
} | ||
} | ||
export default FifoCache; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {}; |
File renamed without changes.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
; | ||
const getTimestamp = () => Date.now(); | ||
class LruCache { | ||
#capacity; | ||
#store; | ||
#accessMap; | ||
constructor(options) { | ||
const { capacity, checkLowMemory } = options; | ||
let checkLowMemoryTimer; | ||
if (!Number.isInteger(capacity) || capacity <= 0) | ||
throw new Error('invalid "capacity": positive integer expected'); | ||
if (typeof checkLowMemory !== 'boolean') | ||
throw new Error('option "checkLowMemory" must be boolean if provided'); | ||
this.#capacity = capacity; | ||
if (checkLowMemory) { | ||
checkLowMemoryTimer = setInterval(() => { | ||
// @todo | ||
}, 5000); | ||
// checkLowMemoryTimer.unref?.(); | ||
} | ||
this.#store = new Map(); | ||
// struct for tracking of access to cache items | ||
this.#accessMap = new Map(); | ||
} | ||
get size() { | ||
return this.#store.size; | ||
} | ||
set capacity(value) { | ||
if (!Number.isInteger(value) || value <= 0) | ||
throw new Error('invalid "capacity": positive integer expected'); | ||
this.#capacity = value; | ||
} | ||
read(key) { | ||
if (this.#store.has(key)) { | ||
// update access time | ||
this.#accessMap.set(key, getTimestamp()); | ||
return this.#store.get(key); | ||
} | ||
return null; | ||
} | ||
store(key, value) { | ||
const timestamp = getTimestamp(); | ||
// check if cache size limit is reached | ||
if (this.#store.size === this.#capacity) { | ||
// first, get item with the lowest priority (oldest based on timestamp) | ||
const min = { | ||
key: null, | ||
value: +Infinity | ||
}; | ||
for (const [itemKey, itemValue] of this.#accessMap) { | ||
if (itemValue < min.value) { | ||
min.key = itemKey; | ||
min.value = itemValue; | ||
} | ||
} | ||
this.#accessMap.delete(min.key); | ||
this.#store.delete(min.key); | ||
} | ||
this.#accessMap.set(key, timestamp); | ||
this.#store.set(key, value); | ||
} | ||
has(key) { | ||
return this.#store.has(key); | ||
} | ||
remove(key) { | ||
this.#store.delete(key); | ||
} | ||
clear() { | ||
this.#store.clear(); | ||
this.#accessMap.clear(); | ||
} | ||
} | ||
export default LruCache; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
type TStats = { | ||
size: number; | ||
capacity: number; | ||
locked: boolean; | ||
}; | ||
interface IRRCache { | ||
get stats(): TStats; | ||
set locked(state: boolean); | ||
read: (key: any) => any; | ||
add: (key: any, value: any) => void; | ||
has: (key: any) => boolean; | ||
remove: (key: any) => void; | ||
clear: () => void; | ||
} | ||
type TConfigOptions = { | ||
/** | ||
* Capacity means how many items can be stored at the same time in cache. | ||
* For RR cache, by definition, capacity is a required restriction, | ||
* without it becomes almost meaningless, so this option is mandatory. | ||
*/ | ||
capacity: number; | ||
}; | ||
declare class RRCache implements IRRCache { | ||
#private; | ||
constructor(options: TConfigOptions); | ||
get stats(): { | ||
size: number; | ||
capacity: number; | ||
locked: boolean; | ||
}; | ||
set locked(state: boolean); | ||
/** | ||
* Read value stored in cache by assosiated key. | ||
* @param {*} key - cache record's key | ||
* @return {*|null} record's value retrieved by key or null if record is absent | ||
*/ | ||
read(key: any): any; | ||
add(key: any, value: any): void; | ||
/** | ||
* Check if record by given key exists in cache. | ||
* @param {*} key - cache record's key | ||
* @return {boolean} return true if record is in the cache | ||
*/ | ||
has(key: any): boolean; | ||
/** | ||
* Remove an item from the cache. | ||
* @param {*} key - cache record's key | ||
* @return {void} | ||
*/ | ||
remove(key: any): void; | ||
/** | ||
* Remove all items from the cache. | ||
* @return {void} | ||
*/ | ||
clear(): void; | ||
} | ||
export default RRCache; |
Oops, something went wrong.