Skip to content

Commit

Permalink
refactor!: rename LRUCache into BaseLru
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Vanvelthem committed Jan 29, 2025
1 parent 449ceb8 commit 76556f0
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changeset/flat-worms-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@httpx/lru": minor
---

Rename LRUCache in BaseLru
8 changes: 4 additions & 4 deletions packages/lru/.size-limit.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
*/
module.exports = [
{
name: 'import { LruCache } (ESM)',
name: 'import { BaseLru } (ESM)',
path: ['dist/index.mjs'],
import: '{ LRUCache }',
import: '{ BaseLru }',
limit: '600B',
},
{
name: 'require { LRUCache } (CJS)',
import: '{ LRUCache }',
name: 'require { BaseLru } (CJS)',
import: '{ BaseLru }',
path: ['dist/index.cjs'],
limit: '700B',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { bench, describe } from 'vitest';

import { getLruCaches } from './get-lru-caches';
import { getLruCaches } from '../get-lru-caches';

describe(`LRU.get comparison`, async () => {
describe(`BaseLru.get comparison`, async () => {
const SEEDS_COUNT = 1000;
const MAX_SIZE = 500;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { bench, describe } from 'vitest';

import { getLruCaches } from './get-lru-caches';
import { getLruCaches } from '../get-lru-caches';

describe(`LRU.set comparison`, async () => {
describe(`BaseLru.set comparison`, async () => {
const seeds = Array.from({ length: 1000 }).map((_, i) => ({
key: `key-${i}`,
value: `value-${i}`,
Expand Down
8 changes: 4 additions & 4 deletions packages/lru/bench/get-lru-caches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
devDependencies,
version,
} from '../package.json' with { type: 'json' };
import { LRUCache } from '../src';
import { BaseLru } from '../src';

const versions = devDependencies;

const asyncLoadCompiled = async (): Promise<typeof LRUCache | null> => {
const asyncLoadCompiled = async (): Promise<typeof BaseLru | null> => {
return await import(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore to apply benchmarks assert must be built
Expand All @@ -18,7 +18,7 @@ const asyncLoadCompiled = async (): Promise<typeof LRUCache | null> => {
)
.then((mod) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
return mod.LRUCache as unknown as typeof LRUCache;
return mod.BaseLru as unknown as typeof BaseLru;
})
.catch((_e) => {
console.warn('Requires httpx/lru to be built (yarn build)');
Expand All @@ -35,7 +35,7 @@ export const getLruCaches = async (params: {
const { maxSize, prepopulate } = params;
const caches = {
'@httpx/lru': {
cache: new LRUCache({ maxSize }),
cache: new BaseLru({ maxSize }),
version: version,
},
...(LRUCacheCompiled
Expand Down
10 changes: 5 additions & 5 deletions packages/lru/src/__tests__/lru-cache.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { LRUCache } from '../lru-cache';
import { BaseLru } from '../base-lru';

describe('LRU cache', () => {
describe('LRUCache.get/set', () => {
describe('BaseLru', () => {
describe('Base.get/set', () => {
it('should set a value in the cache', () => {
const lru = new LRUCache({
const lru = new BaseLru({
maxSize: 1,
});
lru.set('key', 'value');
Expand All @@ -12,7 +12,7 @@ describe('LRU cache', () => {
});
describe('Eviction', () => {
it('should evict items based on maxSize', () => {
const lru = new LRUCache({
const lru = new BaseLru({
maxSize: 2,
});
lru.set('key1', 'value1');
Expand Down
48 changes: 27 additions & 21 deletions packages/lru/src/lru-cache.ts → packages/lru/src/base-lru.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
class Node<T> {
prev: Node<T> | null = null;
next: Node<T> | null = null;
constructor(public readonly key: T) {}
type SupportedKeys = string;

class Node<TValue, TKey extends SupportedKeys = string> {
prev: Node<TValue, TKey> | null = null;
next: Node<TValue, TKey> | null = null;
constructor(public readonly key: TKey) {}
}

type DataType<T> = {
value: T;
node: Node<T>;
type DataType<TValue, TKey extends SupportedKeys = string> = {
value: TValue;
node: Node<TValue, TKey>;
};

type Params<TValue, TKey extends SupportedKeys = string> = {
maxSize: number;
onEviction?: (key: TKey, value: TValue) => void;
};

/**
* Double linked list based lru cache that supports get in O(1)
*/
export class LRUCache<TValue = unknown> {
export class BaseLru<TValue = unknown, TKey extends SupportedKeys = string> {
private maxSize: number;

private cache: Map<TValue, DataType<TValue>>;
private head: Node<TValue> | null = null;
private tail: Node<TValue> | null = null;
private cache: Map<TKey, DataType<TValue, TKey>>;
private head: Node<TValue, TKey> | null = null;
private tail: Node<TValue, TKey> | null = null;

constructor(params: { maxSize: number }) {
constructor(params: Params<TValue, TKey>) {
const { maxSize } = params;
if (!Number.isSafeInteger(maxSize) && maxSize < 1) {
throw new TypeError(
Expand All @@ -30,7 +37,7 @@ export class LRUCache<TValue = unknown> {
this.cache = new Map();
}

private moveToHead(node: Node<TValue>): void {
private moveToHead(node: Node<TValue, TKey>): void {
if (node === this.head) {
return;
}
Expand Down Expand Up @@ -83,18 +90,18 @@ export class LRUCache<TValue = unknown> {
this.cache.clear();
}

has(key: TValue): boolean {
has(key: TKey): boolean {
return this.cache.has(key);
}

set(key: TValue, value: TValue): boolean {
set(key: TKey, value: TValue): boolean {
if (this.cache.has(key)) {
const data = this.cache.get(key)!;
data.value = value;
this.moveToHead(data.node);
} else {
const newNode = new Node(key);
const data: DataType<TValue> = { value, node: newNode };
const data: DataType<TValue, TKey> = { value, node: newNode };

this.cache.set(key, data);
this.moveToHead(newNode);
Expand All @@ -106,7 +113,7 @@ export class LRUCache<TValue = unknown> {
return this.cache.has(key);
}

get(key: TValue): TValue | undefined {
get(key: TKey): TValue | undefined {
if (!this.cache.has(key)) {
return;
}
Expand All @@ -117,7 +124,7 @@ export class LRUCache<TValue = unknown> {
return data.value;
}

delete(key: TValue): boolean {
delete(key: TKey): boolean {
const node = this.cache.get(key)?.node;

if (!node) {
Expand All @@ -143,16 +150,15 @@ export class LRUCache<TValue = unknown> {
return this.cache.delete(key);
}

toArray(): TValue[][] {
const result: TValue[][] = [];
toArray(): [key: TKey, value: TValue][] {
const result: [key: TKey, value: TValue][] = [];
let current = this.tail;

while (current) {
const data = this.cache.get(current.key)!;
result.push([current.key, data.value]);
current = current.prev;
}

return result;
}
}
2 changes: 1 addition & 1 deletion packages/lru/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { LRUCache } from './lru-cache';
export { BaseLru } from './base-lru';

0 comments on commit 76556f0

Please sign in to comment.