lru-cache
A Javascript LRU-cache for node and/or browser, featuring:
- LRU cache logic
- Alternate keys
- Singleton caches per value type
- Event registry for cache change events
- No dependencies
Installation
npm install --save @swarmy/lru-cache
Motivation
There are for sure more than a handful of different LRU-cache implementations flying around on npm.
What makes this one unique is that it features the use of alternate keys and an event registry for cache change events.
Alternate keys are useful in situations where certain cache consumers have no access to the primary key, or would have to construct or fetch the primary key in advance.
Cache events are useful to have a central point to handle object changes in an application with multiple models. E.g. register all models as listeners and ensure that all entity updates and deletes go over the cache. Than you can ensure that each update or delete of a certain entity, be it due to a change coming from a certain controller or due to a server push, will keep all models in sync. I have applications where I have no need to cache for performance reasons, but still use this pattern to keep my Redux state up to date (by having a single cache listener that dispatches a corresponding action).
Basic Usage
Caching
import {getCache} from "@swarmy/lru-cache";
...
const userCache = getCache("User");
userCache.set(user.id, user);
...
let user = userCache.get(userId);
if (!user) {
await fetchUser(userId);
}
- For the same value type (here "User"), getCache will always return the same cache instance.
- For detailed description of all cache methods, have a look at
Cache Events
To register for all cache change events
import {registerCacheChangedHandler} from "@swarmy/lru-cache";
registerCacheChangedHandler(changeObject => {
console.log("changes:", changeObject);
});
- For detailed description of all cache methods, have a look at
Quality
Develop
git clone https:
cd lru-cache
npm install
npm run build
npm run test
npm run test-performance
npm run generate-doc
Detailed Usage
Caching
WIP
Cache Events
WIP
Questions
What are the tradeoffs?
- Compared to a native Javascript Map, the LRU logic implies performance impact on get, set and delete. It's just the price to pay for having a LRU cache.
- Compared to a LRU cache without cache events, the is additional performance impact on get, set and delete.
- Again see Performance tests
- However, if you are caching for performance, then because the fetching of values is significantly more time consuming. So whether you save 400ms or only 399ms hardly makes a difference here.
- If you are not caching for performance reasons, but to have the change events, well than again it's just the price to pay for the event handling.
Why can I not differentiate between insert and update in the change events?
Garbage collected languages without weak references make the use of some patterns impossible. Two of these patterns affect this library:
- One cannot implement an instance-cache, hence a cache that ensures to not discard an entry, as long as this entry is referenced from somewhere outside the cache. If upon calling the set method, the value is not already in the cache, there is no way to tell, if it was never there, or if it was there an has been LRU discarded.
- One cannot implement event registries that reference listeners only weakly. Thus, it is up to the consumker of this library to ensure that no memory leaks occur due to not unregistered event listeners.
Why can I not just have a sorted list with all changes in the cache event, instead of sorting myself by order attribute?
- I just did not want to further increase the size of change object by another array holding redundant data.
- However, maybe in a future version, I will make it configurable to optionally include such a list.