Skip to content

Commit

Permalink
Merge pull request #62 from oslabs-beta/refactor_and_add_redis_types
Browse files Browse the repository at this point in the history
refactor: small code changes and added redis types
  • Loading branch information
hankthetank27 authored Jan 22, 2025
2 parents 70d27fb + 96ff85e commit 01e6fed
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 55 deletions.
1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"oak": "https://deno.land/x/oak@v17.1.4/mod.ts",
"oak/application": "https://deno.land/x/oak@v17.1.4/application.ts",
"redis": "https://deno.land/x/redis@v0.37.1/mod.ts",
"redis/command": "https://deno.land/x/redis@v0.37.1/command.ts",
"cors": "https://deno.land/x/cors@v1.2.2/mod.ts"
}
}
114 changes: 83 additions & 31 deletions src/doublyLinkedLists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ export class Node {
timeStamp: Date;
parent?: FreqNode;

constructor(key: string, value: cacheValue, byteSize: number, timeStamp: Date, parent?: FreqNode){
constructor(
key: string,
value: cacheValue,
byteSize: number,
timeStamp: Date,
parent?: FreqNode
) {
this.next = null;
this.prev = null;
this.value = value;
Expand All @@ -34,7 +40,13 @@ export class ValueDoublyLinkedList {
this.tail = null;
}

public addHead(key: string, value: cacheValue, byteSize: number, timeStamp: Date, parent?: FreqNode){
public addHead(
key: string,
value: cacheValue,
byteSize: number,
timeStamp: Date,
parent?: FreqNode
) {
const node = new Node(key, value, byteSize, timeStamp, parent);
if (!this.head) {
this.head = node;
Expand All @@ -47,25 +59,47 @@ export class ValueDoublyLinkedList {
return this.head;
}

public delete(node: Node | null){
if (!node) return;
node.prev ?
node.prev.next = node.next
: this.head = node.next;
node.next ?
node.next.prev = node.prev
: this.tail = node.prev;
public delete(node: Node | null) {
if (!node) {
return;
}

if (node.prev) {
node.prev.next = node.next;
} else {
this.head = node.next;
}

if (node.next) {
node.next.prev = node.prev;
} else {
this.tail = node.prev;
}

return node;
}

public deleteTail(){
public deleteTail(): Node | null {
if (!this.tail) {
return null;
}

const deleted = this.tail;
if (this.head === this.tail) {
this.head = this.tail = null;
} else if (this.tail) {
this.tail = this.tail.prev
if (this.tail) this.tail.next = null;
// handle single-node case
this.head = this.tail = null;
} else {
// handle multiple-node case
this.tail = this.tail.prev;
if (this.tail) {
this.tail.next = null;
}
}

// cleanup for deleted node's references
deleted.prev = null;
deleted.next = null;

return deleted;
}
}
Expand All @@ -79,7 +113,7 @@ export class FreqNode {
next: FreqNode | null;
prev: FreqNode | null;

constructor(freqValue: number){
constructor(freqValue: number) {
this.freqValue = freqValue;
this.valList = new ValueDoublyLinkedList();
this.next = null;
Expand All @@ -92,13 +126,13 @@ export class FreqDoublyLinkedList {
head: FreqNode | null;
tail: FreqNode | null;

constructor(){
constructor() {
//head being lowest freq item, tail being highest.
this.head = null;
this.tail = null;
}

public addNewFreq(key: string, value: cacheValue, byteSize: number, timeStamp: Date){
public addNewFreq(key: string, value: cacheValue, byteSize: number, timeStamp: Date) {
if (!this.head) {
this.head = new FreqNode(1);
this.tail = this.head;
Expand All @@ -112,8 +146,11 @@ export class FreqDoublyLinkedList {
return this.head.valList.addHead(key, value, byteSize, timeStamp, this.head);
}

public increaseFreq(node: Node){
if (!node.parent) return;
public increaseFreq(node: Node) {
if (!node.parent) {
return;
}

const { key, value, byteSize, timeStamp, parent } = node;

//is highest freq
Expand Down Expand Up @@ -142,22 +179,37 @@ export class FreqDoublyLinkedList {
this.deleteValNode(this.head.valList.tail)
: undefined;

public deleteValNode(node: Node | null){
if (!node || !node.parent) return;
public deleteValNode(node: Node | null) {
if (!node || !node.parent) {
return;
}

const { valList } = node.parent;
valList.delete(node);
if (!valList.head) this.delete(node.parent);
if (!valList.head) {
this.delete(node.parent);
}

return node;
}

public delete(freqNode: FreqNode | null){
if (!freqNode) return;
freqNode.prev ?
freqNode.prev.next = freqNode.next
: this.head = freqNode.next;
freqNode.next ?
freqNode.next.prev = freqNode.prev
: this.tail = freqNode.prev;
public delete(freqNode: FreqNode | null) {
if (!freqNode) {
return;
}

if (freqNode.prev) {
freqNode.prev.next = freqNode.next;
} else {
this.head = freqNode.next;
}

if (freqNode.next) {
freqNode.next.prev = freqNode.prev;
} else {
this.tail = freqNode.prev;
}

return freqNode;
}
}
24 changes: 13 additions & 11 deletions src/lfu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class LFU {
expire: number;
metrics: PerfMetrics;

constructor(expire: number, metrics: PerfMetrics, capacity: number){
constructor(expire: number, metrics: PerfMetrics, capacity: number) {
this.freqList = new FreqDoublyLinkedList();
this.cache = {};
this.length = 0;
Expand All @@ -31,7 +31,7 @@ class LFU {
* @param value
* @returns
*/
public put(key: string, value: cacheValue, byteSize: number){
public put(key: string, value: cacheValue, byteSize: number) {
if (this.cache[key]){
this.metrics.decreaseBytes(this.cache[key].byteSize);
this.metrics.increaseBytes(byteSize);
Expand All @@ -45,17 +45,19 @@ class LFU {

if (this.length < this.capacity) {
this.length++;
} else {
const deletedNode: Node | undefined = this.freqList.deleteLeastFreq();
if (!deletedNode) throw new Error('Node is null. Ensure cache capcity is greater than 0.');
delete this.cache[deletedNode.key];
this.metrics.decreaseBytes(deletedNode.byteSize);
return;
}

const deletedNode: Node | undefined = this.freqList.deleteLeastFreq();
if (!deletedNode) {
throw new Error('Node is null. Ensure cache capcity is greater than 0.');
}

return;
delete this.cache[deletedNode.key];
this.metrics.decreaseBytes(deletedNode.byteSize);
}

public get(key: string){
public get(key: string) {
if (!this.cache[key]) return;
//if entry is stale, deletes and exits
const currentTime = new Date();
Expand All @@ -74,7 +76,7 @@ class LFU {
}
}

public delete(key: string){
public delete(key: string) {
const node = this.cache[key];
if (!node) return;

Expand All @@ -86,7 +88,7 @@ class LFU {
return node;
}

public clear(){
public clear() {
this.freqList = new FreqDoublyLinkedList();
this.cache = {};
this.length = 0;
Expand Down
27 changes: 15 additions & 12 deletions src/lru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class LRU {
this.capacity = capacity;
this.expire = expire;
this.metrics = metrics;

this.get = this.get.bind(this);
this.put = this.put.bind(this);
this.delete = this.delete.bind(this);
Expand All @@ -34,7 +33,7 @@ class LRU {
* @param value
* @returns
*/
public put (key: string, value: cacheValue, byteSize: number) {
public put(key: string, value: cacheValue, byteSize: number) {
//if key alreadys exits in cache, replace key value with new value, and move to list head.
if (this.cache[key]){
this.metrics.decreaseBytes(this.cache[key].byteSize);
Expand All @@ -51,22 +50,24 @@ class LRU {
//evalutes if least recently used item should be evicted.
if (this.length < this.capacity) {
this.length++;
} else {
const deletedNode: Node | null = this.list.deleteTail();
if (deletedNode === null) throw new Error('Node is null. Ensure cache capcity is greater than 0.');
delete this.cache[deletedNode.key];
this.metrics.decreaseBytes(deletedNode.byteSize);
return;
}

return;
const deletedNode: Node | null = this.list.deleteTail();
if (deletedNode === null) {
throw new Error('Node is null. Ensure cache capcity is greater than 0.');
}

delete this.cache[deletedNode.key];
this.metrics.decreaseBytes(deletedNode.byteSize);
}

/**
* Gets item from cache and moves to head -- most recently used.
* @param key
* @returns
*/
public get (key: string) {
public get(key: string) {
//If no matching cache value (cache miss), return next();
if (!this.cache[key]) return undefined;

Expand All @@ -80,7 +81,9 @@ class LRU {
}

// if current key is already node at head of list, return immediately.
if (this.cache[key] === this.list.head) return this.list.head.value;
if (this.cache[key] === this.list.head) {
return this.list.head.value;
}

//create new node, then delete node at current key, to replace at list head.
const node = this.cache[key];
Expand All @@ -97,7 +100,7 @@ class LRU {
* @param key
* @returns
*/
public delete (key: string) {
public delete(key: string) {
const node = this.cache[key];
if (!node) return;

Expand All @@ -111,7 +114,7 @@ class LRU {
/**
* Clears entire cache contents.
*/
public clear () {
public clear() {
this.list = new ValueDoublyLinkedList();
this.cache = {};
this.length = 0;
Expand Down
1 change: 1 addition & 0 deletions src/performanceMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class PerfMetrics {
this.currentMissLatency = latency;
return;
}

throw new TypeError('Hit or miss not specified');
};
}
Expand Down
2 changes: 1 addition & 1 deletion zoic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import LFU from './src/lfu.ts'
*
* ```ts
*
* import { Zoic } from "https://deno.land/x/ozoic/zoic.ts"
* import { Zoic } from "https://deno.land/x/zoic"
*
* const cache = new Zoic({
* cache: 'LRU',
Expand Down

0 comments on commit 01e6fed

Please sign in to comment.