memory-cache-node
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -20,4 +20,5 @@ export declare type ItemValueWrapper<V> = { | ||
clear(): void; | ||
destroy(): void; | ||
private readonly deleteExpiredItems; | ||
private deleteExpiredItemsFromBatch; | ||
} |
@@ -20,6 +20,11 @@ "use strict"; | ||
storeExpiringItem(itemKey, itemValue, timeToLiveInSecs) { | ||
if (this.timer === null) { | ||
throw new Error('Cache is destroyed. Cannot store items anymore.'); | ||
} | ||
if (this.itemCount < this.maxItemCount) { | ||
this.itemKeyToItemValueWrapperMap.set(itemKey, { | ||
itemValue, | ||
expirationTimestampInMillisSinceEpoch: timeToLiveInSecs ? Date.now() + timeToLiveInSecs * 1000 : undefined | ||
expirationTimestampInMillisSinceEpoch: timeToLiveInSecs | ||
? Date.now() + timeToLiveInSecs * 1000 | ||
: undefined, | ||
}); | ||
@@ -48,3 +53,6 @@ this.itemCount++; | ||
this.itemCount = 0; | ||
} | ||
destroy() { | ||
if (this.timer) { | ||
this.clear(); | ||
clearInterval(this.timer); | ||
@@ -51,0 +59,0 @@ this.timer = null; |
@@ -10,3 +10,3 @@ "use strict"; | ||
afterEach(() => { | ||
memoryCache.clear(); | ||
memoryCache.destroy(); | ||
}); | ||
@@ -17,31 +17,26 @@ describe('MemoryCache', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
expect((memoryCache.getItemCount())).toBe(0); | ||
expect(memoryCache.getItemCount()).toBe(0); | ||
}); | ||
}); | ||
describe('storePermanentItem', () => { | ||
it('should store a permanent item in cache', (done) => { | ||
it('should call storeExpiringItem with timeToLiveInSecs set to zero', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.storeExpiringItem = jest.fn(); | ||
memoryCache.storePermanentItem('key', 1); | ||
setTimeout(() => { | ||
expect((memoryCache.getItemCount())).toBe(1); | ||
done(); | ||
}, 3000); | ||
expect(memoryCache.storeExpiringItem).toHaveBeenCalledWith('key', 1, 0); | ||
}); | ||
it('should replace an existing item in the cache', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.storePermanentItem('key', 1); | ||
memoryCache.storePermanentItem('key', 2); | ||
expect(memoryCache.retrieveItemValue('key')).toBe(2); | ||
}); | ||
}); | ||
describe('storeExpiringItem', () => { | ||
it('should store an expiring item in cache and cache should not contain item after it has expired', (done) => { | ||
it('should store an expiring item in cache', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.storeExpiringItem('key', 1, 1); | ||
setTimeout(() => { | ||
expect(memoryCache.hasItem('key')).toBe(false); | ||
expect((memoryCache.getItemCount())).toBe(0); | ||
done(); | ||
}, 3000); | ||
memoryCache.storeExpiringItem('key', 1, 10); | ||
expect(memoryCache.hasItem('key')).toBe(true); | ||
expect(memoryCache.getItemCount()).toBe(1); | ||
}); | ||
it('should not store item in the cache if cache is full', () => { | ||
memoryCache = new MemoryCache_1.default(1, 1); | ||
memoryCache.storeExpiringItem('key', 1, 10); | ||
memoryCache.storeExpiringItem('key', 2, 10); | ||
expect(memoryCache.getItemCount()).toBe(1); | ||
}); | ||
it('should replace an existing item in the cache', () => { | ||
@@ -53,2 +48,9 @@ memoryCache = new MemoryCache_1.default(1, 10); | ||
}); | ||
it('should throw an error if cache is destroyed', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.destroy(); | ||
expect(() => { | ||
memoryCache.storeExpiringItem('key', 1, 10); | ||
}).toThrow('Cache is destroyed. Cannot store items anymore.'); | ||
}); | ||
}); | ||
@@ -117,2 +119,16 @@ describe('getItemCount', () => { | ||
}); | ||
it('it is idempotent', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.clear(); | ||
memoryCache.clear(); | ||
}); | ||
}); | ||
describe('destroy', () => { | ||
it('it should clear the cache', () => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.storePermanentItem('key', 2); | ||
memoryCache.clear = jest.fn(); | ||
memoryCache.destroy(); | ||
expect(memoryCache.clear).toHaveBeenCalledTimes(1); | ||
}); | ||
it('it clears the items expiration check timer', () => { | ||
@@ -122,3 +138,3 @@ jest.useFakeTimers('legacy'); | ||
memoryCache.storeExpiringItem('key', 2, 1); | ||
memoryCache.clear(); | ||
memoryCache.destroy(); | ||
expect(clearInterval).toHaveBeenCalledTimes(1); | ||
@@ -128,8 +144,39 @@ jest.useRealTimers(); | ||
it('it is idempotent', () => { | ||
const memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.clear(); | ||
memoryCache.clear(); | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.destroy(); | ||
memoryCache.destroy(); | ||
}); | ||
}); | ||
describe('deleteExpiredItems', () => { | ||
it('should not delete permanent item from cache', (done) => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.storePermanentItem('key', 1); | ||
setTimeout(() => { | ||
expect(memoryCache.getItemCount()).toBe(1); | ||
done(); | ||
}, 3000); | ||
}); | ||
it('should not delete non-expired item from cache', (done) => { | ||
memoryCache = new MemoryCache_1.default(1, 10); | ||
memoryCache.storeExpiringItem('key', 1, 60); | ||
setTimeout(() => { | ||
expect(memoryCache.getItemCount()).toBe(1); | ||
done(); | ||
}, 3000); | ||
}); | ||
it('should delete expired items from cache', (done) => { | ||
const itemCount = 250000; | ||
memoryCache = new MemoryCache_1.default(1, itemCount); | ||
Array(itemCount) | ||
.fill(1) | ||
.forEach((_, index) => { | ||
memoryCache.storeExpiringItem('key' + index, 1, 1); | ||
}); | ||
setTimeout(() => { | ||
expect(memoryCache.getItemCount()).toBe(0); | ||
done(); | ||
}, 5000); | ||
}); | ||
}); | ||
}); | ||
//# sourceMappingURL=MemoryCache.spec.js.map |
{ | ||
"name": "memory-cache-node", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Fast, modern and event loop non-blocking memory cache for Node.js and browse", | ||
@@ -5,0 +5,0 @@ "author": { |
159
README.md
@@ -1,1 +0,158 @@ | ||
# memory-cache-node | ||
# memory-cache-node | ||
[![version][version-badge]][package] | ||
[![build][build]][circleci] | ||
[![coverage][coverage]][codecov] | ||
[](https://sonarcloud.io/dashboard?id=pksilen_memory-cache-node) | ||
[](https://sonarcloud.io/dashboard?id=pksilen_memory-cache-node) | ||
[](https://sonarcloud.io/dashboard?id=pksilen_memory-cache-node) | ||
[![Downloads][downloads]][package] | ||
[![MIT License][license-badge]][license] | ||
A fast and type safe memory cache for Node.js and browser. `memory-cache-node` use Javascript Map as cache implementation which | ||
is faster than using Javascript object that some other similar libraries use. `memory-cache-node` also uses implementation that does | ||
not block the event loop for a long time, if the cache is very large (hundreds of thousands or millions of entries). | ||
## Table of Contents | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [API Documentation](#api-documentation) | ||
- [License](#license) | ||
## <a name="installation"></a> Installation | ||
```bash | ||
npm install --save memory-cache-node | ||
``` | ||
## <a name="usage"></a> Usage | ||
### Creating a memory cache | ||
Below example creates a memory cache for items which has string keys and number values. | ||
Memory cache checks expiring items every 600 seconds (i.e. every 10 minutes) | ||
The maximum number of items in the cache is 1 million. | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const itemsExpirationCheckIntervalInSecs = 10 * 60; | ||
const maxItemCount = 1000000; | ||
const memoryCache = new MemoryCache<string, number>(itemsExpirationCheckIntervalInSecs, maxItemCount); | ||
``` | ||
### Storing items in the memory cache | ||
Below example stores a permanent item in the memory cache with key `key1` and stores an expiring item with key | ||
`key2`. The latter item expires earliest after 30 minutes. | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
memoryCache.storePermanentItem('key1', 1); | ||
const timeToLiveInSecs = 30 * 60; | ||
memoryCache.storeExpiringItem('key2', 2, timeToLiveInSecs); | ||
``` | ||
### Getting the number of items in the memory cache | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
memoryCache.storePermanentItem('key1', 1); | ||
const timeToLiveInSecs = 30 * 60; | ||
memoryCache.storeExpiringItem('key2', 2, timeToLiveInSecs); | ||
console.log(memoryCache.getItemCount()); // Logs to console: 2 | ||
``` | ||
### Checking if an item exists in the memory cache | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
memoryCache.storePermanentItem('key1', 1); | ||
console.log(memoryCache.hasItem('key1')); // Logs to console: true | ||
console.log(memoryCache.hasItem('notFound')); // Logs to console: false | ||
``` | ||
### Retrieving the value of an item in the memory cache | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
memoryCache.storePermanentItem('key1', 1); | ||
console.log(memoryCache.retrieveItemValue('key1')); // Logs to console: 1 | ||
console.log(memoryCache.retrieveItemValue('notFound')); // Logs to console: undefined | ||
``` | ||
### Removing an item from the memory cache | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
memoryCache.storePermanentItem('key1', 1); | ||
console.log(memoryCache.hasItem('key1')); // Logs to console: true | ||
memoryCache.removeItem('key1'); | ||
console.log(memoryCache.hasItem('key1')); // Logs to console: false | ||
``` | ||
### Clearing the memory cache | ||
Below examples removes all items from the memory cache | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
// Use cache here | ||
// ... | ||
memoryCache.clear() | ||
``` | ||
### Destroying the memory cache | ||
Below example destroys the memory cache and it **should not be used** after that. | ||
It clears the memory cache and also removes the timer for checking expired items. | ||
**NOTE! You should NEVER use a destroyed cache again!** | ||
You should destroy your memory cache if it is not used in your application anymore. | ||
```ts | ||
import { MemoryCache } from 'memory-cache-node'; | ||
const memoryCache = new MemoryCache<string, number>(600, 1000000); | ||
// Use cache here | ||
// ... | ||
memoryCache.destroy() | ||
``` | ||
## <a name="api-documentation"></a> API Documentation | ||
```ts | ||
class MemoryCache<K, V> { | ||
constructor(itemsExpirationCheckIntervalInSecs: number, maxItemCount: number); | ||
storePermanentItem(itemKey: K, itemValue: V): void; | ||
storeExpiringItem(itemKey: K, itemValue: V, timeToLiveInSecs: number): void; | ||
getItemCount(): number; | ||
hasItem(itemKey: K): boolean; | ||
retrieveItemValue(itemKey: K): V | undefined; | ||
removeItem(itemKey: K): void; | ||
clear(): void; | ||
destroy(): void; | ||
} | ||
``` | ||
`K` is the type of the item key. | ||
`V` is the type of the item value. | ||
## <a name="license"></a> License | ||
[MIT](https://github.com/pksilen/memory-cache-node/blob/main/LICENSE) | ||
[license-badge]: https://img.shields.io/badge/license-MIT-green | ||
[license]: https://github.com/pksilen/memory-cache-node/blob/main/LICENSE | ||
[version-badge]: https://img.shields.io/npm/v/memory-cache-node.svg?style=flat-square | ||
[package]: https://www.npmjs.com/package/memory-cache-node | ||
[downloads]: https://img.shields.io/npm/dm/memory-cache-node | ||
[build]: https://img.shields.io/circleci/project/github/pksilen/memory-cache-node/main.svg?style=flat-square | ||
[circleci]: https://circleci.com/gh/pksilen/memory-cache-node/tree/main | ||
[coverage]: https://img.shields.io/codecov/c/github/pksilen/memory-cache-node/main.svg?style=flat-square | ||
[codecov]: https://codecov.io/gh/pksilen/memory-cache-node |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
50177
13
285
159