diff --git a/src/matrix/e2ee/megolm/decryption/SessionCache.js b/src/matrix/e2ee/megolm/decryption/SessionCache.js index 712e2e50..cbb868ea 100644 --- a/src/matrix/e2ee/megolm/decryption/SessionCache.js +++ b/src/matrix/e2ee/megolm/decryption/SessionCache.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseLRUCache} from "../../../../utils/LRUCache.js"; +import {BaseLRUCache} from "../../../../utils/LRUCache"; const DEFAULT_CACHE_SIZE = 10; /** diff --git a/src/matrix/room/timeline/persistence/MemberWriter.js b/src/matrix/room/timeline/persistence/MemberWriter.js index b21a4461..1cdcb7d5 100644 --- a/src/matrix/room/timeline/persistence/MemberWriter.js +++ b/src/matrix/room/timeline/persistence/MemberWriter.js @@ -15,7 +15,7 @@ limitations under the License. */ import {MemberChange, RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "../../members/RoomMember.js"; -import {LRUCache} from "../../../../utils/LRUCache.js"; +import {LRUCache} from "../../../../utils/LRUCache"; export class MemberWriter { constructor(roomId) { diff --git a/src/utils/LRUCache.js b/src/utils/LRUCache.ts similarity index 73% rename from src/utils/LRUCache.js rename to src/utils/LRUCache.ts index 98ded41b..d275b9f1 100644 --- a/src/utils/LRUCache.js +++ b/src/utils/LRUCache.ts @@ -18,8 +18,12 @@ limitations under the License. * Very simple least-recently-used cache implementation * that should be fast enough for very small cache sizes */ -export class BaseLRUCache { - constructor(limit) { +export class BaseLRUCache { + + private _limit: number; + private _entries: T[]; + + constructor(limit: number) { this._limit = limit; this._entries = []; } @@ -27,7 +31,7 @@ export class BaseLRUCache { get size() { return this._entries.length; } get limit() { return this._limit; } - _get(findEntryFn) { + _get(findEntryFn: (T) => boolean) { const idx = this._entries.findIndex(findEntryFn); if (idx !== -1) { const entry = this._entries[idx]; @@ -40,7 +44,7 @@ export class BaseLRUCache { } } - _set(value, findEntryFn) { + _set(value: T, findEntryFn: (T) => boolean) { let indexToRemove = this._entries.findIndex(findEntryFn); this._entries.unshift(value); if (indexToRemove === -1) { @@ -57,7 +61,7 @@ export class BaseLRUCache { } } - find(callback) { + find(callback: (T) => boolean) { // iterate backwards so least recently used items are found first for (let i = this._entries.length - 1; i >= 0; i -= 1) { const entry = this._entries[i]; @@ -67,69 +71,76 @@ export class BaseLRUCache { } } - _onEvictEntry() {} + _onEvictEntry(entry: T) {} } -export class LRUCache extends BaseLRUCache { - constructor(limit, keyFn) { +export class LRUCache extends BaseLRUCache { + private _keyFn: (T) => K; + + constructor(limit, keyFn: (T) => K) { super(limit); this._keyFn = keyFn; } - get(key) { + get(key: K): T | undefined { return this._get(e => this._keyFn(e) === key); } - set(value) { + set(value: T) { const key = this._keyFn(value); this._set(value, e => this._keyFn(e) === key); } } export function tests() { + interface NameTuple { + id: number; + name: string; + } + return { "can retrieve added entries": assert => { - const cache = new LRUCache(2, e => e.id); + const cache = new LRUCache(2, e => e.id); cache.set({id: 1, name: "Alice"}); cache.set({id: 2, name: "Bob"}); - assert.equal(cache.get(1).name, "Alice"); - assert.equal(cache.get(2).name, "Bob"); + assert.equal(cache.get(1)!.name, "Alice"); + assert.equal(cache.get(2)!.name, "Bob"); }, "first entry is evicted first": assert => { - const cache = new LRUCache(2, e => e.id); + const cache = new LRUCache(2, e => e.id); cache.set({id: 1, name: "Alice"}); cache.set({id: 2, name: "Bob"}); cache.set({id: 3, name: "Charly"}); assert.equal(cache.get(1), undefined); - assert.equal(cache.get(2).name, "Bob"); - assert.equal(cache.get(3).name, "Charly"); - assert.equal(cache._entries.length, 2); + assert.equal(cache.get(2)!.name, "Bob"); + assert.equal(cache.get(3)!.name, "Charly"); + assert.equal(cache.size, 2); }, "second entry is evicted if first is requested": assert => { - const cache = new LRUCache(2, e => e.id); + const cache = new LRUCache(2, e => e.id); cache.set({id: 1, name: "Alice"}); cache.set({id: 2, name: "Bob"}); cache.get(1); cache.set({id: 3, name: "Charly"}); - assert.equal(cache.get(1).name, "Alice"); + assert.equal(cache.get(1)!.name, "Alice"); assert.equal(cache.get(2), undefined); - assert.equal(cache.get(3).name, "Charly"); - assert.equal(cache._entries.length, 2); + assert.equal(cache.get(3)!.name, "Charly"); + assert.equal(cache.size, 2); }, "setting an entry twice removes the first": assert => { - const cache = new LRUCache(2, e => e.id); + const cache = new LRUCache(2, e => e.id); cache.set({id: 1, name: "Alice"}); cache.set({id: 2, name: "Bob"}); cache.set({id: 1, name: "Al Ice"}); cache.set({id: 3, name: "Charly"}); - assert.equal(cache.get(1).name, "Al Ice"); + assert.equal(cache.get(1)!.name, "Al Ice"); assert.equal(cache.get(2), undefined); - assert.equal(cache.get(3).name, "Charly"); - assert.equal(cache._entries.length, 2); + assert.equal(cache.get(3)!.name, "Charly"); + assert.equal(cache.size, 2); }, "evict callback is called": assert => { let evictions = 0; - class CustomCache extends LRUCache { + class CustomCache extends LRUCache { _onEvictEntry(entry) { assert.equal(entry.name, "Alice"); evictions += 1; @@ -143,7 +154,7 @@ export function tests() { }, "evict callback is called when replacing entry with same identity": assert => { let evictions = 0; - class CustomCache extends LRUCache { + class CustomCache extends LRUCache { _onEvictEntry(entry) { assert.equal(entry.name, "Alice"); evictions += 1;