catbox-memory
Advanced tools
Comparing version 3.1.2 to 4.0.0
146
lib/index.js
@@ -5,3 +5,2 @@ 'use strict'; | ||
const BigTime = require('big-time'); | ||
const Boom = require('boom'); | ||
@@ -13,3 +12,6 @@ const Hoek = require('hoek'); | ||
const internals = {}; | ||
const internals = { | ||
maxTimer: 2147483647, // 2 ^ 31 - 1 | ||
entrySize: 144 // Approximate cache entry size without value: 144 bytes | ||
}; | ||
@@ -19,42 +21,23 @@ | ||
maxByteSize: 100 * 1024 * 1024, // 100MB | ||
allowMixedContent: false | ||
allowMixedContent: false, | ||
minCleanupIntervalMsec: 1000, | ||
cloneBuffersOnGet: false | ||
}; | ||
internals.MemoryCacheEntry = function MemoryCacheEntry(key, value, ttl, allowMixedContent) { | ||
let valueByteSize = 0; | ||
if (allowMixedContent && Buffer.isBuffer(value)) { | ||
this.item = Buffer.alloc(value.length); | ||
// copy buffer to prevent value from changing while in the cache | ||
value.copy(this.item); | ||
valueByteSize = this.item.length; | ||
} | ||
else { | ||
// stringify() to prevent value from changing while in the cache | ||
this.item = JSON.stringify(value); | ||
valueByteSize = Buffer.byteLength(this.item); | ||
} | ||
this.stored = Date.now(); | ||
this.ttl = ttl; | ||
// Approximate cache entry size without value: 144 bytes | ||
this.byteSize = 144 + valueByteSize + Buffer.byteLength(key.segment) + Buffer.byteLength(key.id); | ||
this.timeoutId = null; | ||
}; | ||
exports = module.exports = internals.Connection = class { | ||
constructor(options) { | ||
constructor(options = {}) { | ||
Hoek.assert(this.constructor === internals.Connection, 'Memory cache client must be instantiated using new'); | ||
Hoek.assert(!options || options.maxByteSize === undefined || options.maxByteSize >= 0, 'Invalid cache maxByteSize value'); | ||
Hoek.assert(!options || options.allowMixedContent === undefined || typeof options.allowMixedContent === 'boolean', 'Invalid allowMixedContent value'); | ||
Hoek.assert(options.maxByteSize === undefined || options.maxByteSize >= 0, 'Invalid cache maxByteSize value'); | ||
Hoek.assert(options.allowMixedContent === undefined || typeof options.allowMixedContent === 'boolean', 'Invalid allowMixedContent value'); | ||
Hoek.assert(options.minCleanupIntervalMsec === undefined || options.minCleanupIntervalMsec < internals.maxTimer, 'Invalid cache minCleanupIntervalMsec value'); | ||
Hoek.assert(options.cloneBuffersOnGet === undefined || typeof options.cloneBuffersOnGet === 'boolean', 'Invalid cloneBuffersOnGet value'); | ||
this.settings = Hoek.applyToDefaults(internals.defaults, options || {}); | ||
this.settings = Hoek.applyToDefaults(internals.defaults, options); | ||
this.cache = null; | ||
this._timer = null; | ||
this._timeDue = null; | ||
} | ||
@@ -70,13 +53,49 @@ | ||
stop() { | ||
_scheduleCleanup(msec) { | ||
// Clean up pending eviction timers | ||
const cleanup = () => { | ||
if (this.cache) { | ||
this.cache.forEach((segment) => { | ||
this._timer = null; | ||
this._timerDue = null; | ||
segment.forEach((item) => BigTime.clearTimeout(item.timeoutId)); | ||
}); | ||
const now = Date.now(); | ||
let next = Infinity; | ||
for (const [, segment] of this.cache) { | ||
for (const [id, envelope] of segment) { | ||
const ttl = envelope.stored + envelope.ttl - now; | ||
if (ttl <= 0) { | ||
segment.delete(id); | ||
this.byteSize -= envelope.byteSize; | ||
} | ||
else { | ||
next = Math.min(next, ttl); | ||
} | ||
} | ||
} | ||
if (next !== Infinity) { | ||
this._scheduleCleanup(next); | ||
} | ||
}; | ||
const now = Date.now(); | ||
const timeout = Math.min(Math.max(this.settings.minCleanupIntervalMsec, msec), internals.maxTimer); | ||
if (this._timer) { | ||
if (this._timeDue - now < msec) { | ||
return; | ||
} | ||
clearTimeout(this._timer); | ||
} | ||
this._timeDue = now + timeout; | ||
this._timer = setTimeout(cleanup, timeout); | ||
} | ||
stop() { | ||
clearTimeout(this._timer); | ||
this._timer = null; | ||
this._timerDue = null; | ||
this.cache = null; | ||
@@ -116,3 +135,2 @@ this.byteSize = 0; | ||
const envelope = segment.get(key.id); | ||
if (!envelope) { | ||
@@ -122,5 +140,15 @@ return null; | ||
if (envelope.stored + envelope.ttl < Date.now()) { | ||
this.drop(key); | ||
return null; | ||
} | ||
let item = null; | ||
if (Buffer.isBuffer(envelope.item)) { | ||
item = envelope.item; | ||
if (this.settings.cloneBuffersOnGet) { | ||
const copy = Buffer.alloc(item.length); | ||
item.copy(copy); | ||
item = copy; | ||
} | ||
} | ||
@@ -160,7 +188,4 @@ else { | ||
const cachedItem = segment.get(key.id); | ||
if (cachedItem && | ||
cachedItem.timeoutId) { | ||
BigTime.clearTimeout(cachedItem.timeoutId); | ||
this.byteSize -= cachedItem.byteSize; // If the item existed, decrement the byteSize as the value could be different | ||
if (cachedItem) { | ||
this.byteSize -= cachedItem.byteSize; // If the item existed, decrement the byteSize as the value could be different | ||
} | ||
@@ -174,4 +199,3 @@ | ||
envelope.timeoutId = BigTime.setTimeout(() => this.drop(key), ttl); | ||
this._scheduleCleanup(ttl); | ||
segment.set(key.id, envelope); | ||
@@ -191,9 +215,33 @@ this.byteSize += envelope.byteSize; | ||
if (item) { | ||
BigTime.clearTimeout(item.timeoutId); | ||
this.byteSize -= item.byteSize; | ||
segment.delete(key.id); | ||
} | ||
} | ||
} | ||
}; | ||
segment.delete(key.id); | ||
internals.MemoryCacheEntry = class { | ||
constructor(key, value, ttl, allowMixedContent) { | ||
let valueByteSize = 0; | ||
if (allowMixedContent && | ||
Buffer.isBuffer(value)) { | ||
this.item = Buffer.alloc(value.length); | ||
value.copy(this.item); // Copy buffer to prevent value from changing while in the cache | ||
valueByteSize = this.item.length; | ||
} | ||
else { | ||
this.item = JSON.stringify(value); // stringify() to prevent value from changing while in the cache | ||
valueByteSize = Buffer.byteLength(this.item); | ||
} | ||
this.stored = Date.now(); | ||
this.ttl = ttl; | ||
this.byteSize = internals.entrySize + valueByteSize + Buffer.byteLength(key.segment) + Buffer.byteLength(key.id); | ||
this.timeoutId = null; | ||
} | ||
}; |
{ | ||
"name": "catbox-memory", | ||
"description": "Memory adapter for catbox", | ||
"version": "3.1.2", | ||
"version": "4.0.0", | ||
"repository": "git://github.com/hapijs/catbox-memory", | ||
@@ -13,8 +13,7 @@ "main": "lib/index.js", | ||
"engines": { | ||
"node": ">=8.9.0" | ||
"node": ">=8.12.0" | ||
}, | ||
"dependencies": { | ||
"big-time": "2.x.x", | ||
"boom": "7.x.x", | ||
"hoek": "5.x.x" | ||
"hoek": "6.x.x" | ||
}, | ||
@@ -24,3 +23,3 @@ "devDependencies": { | ||
"code": "5.x.x", | ||
"lab": "15.x.x" | ||
"lab": "17.x.x" | ||
}, | ||
@@ -27,0 +26,0 @@ "scripts": { |
@@ -5,3 +5,4 @@ catbox-memory | ||
Memory adapter for [catbox](https://github.com/hapijs/catbox). | ||
This adapter is not designed to share a common cache between multiple processes (e.g. in a cluster mode). | ||
This adapter is not designed to share a common cache between multiple processes (e.g. in a cluster | ||
mode). It uses a single interval timeout to look for expired records and clean them from memory. | ||
@@ -18,2 +19,4 @@ Lead Maintainer - [Wyatt Preul](https://github.com/geek) | ||
not be relied on. Defaults to `104857600` (100MB). | ||
- `minCleanupIntervalMsec` - the minimum number of milliseconds in between each cache cleanup. | ||
Defaults to 1 second (`1000`). | ||
- `allowMixedContent` - by default, all data is cached as JSON strings, and converted | ||
@@ -24,1 +27,6 @@ to an object using `JSON.parse()` on retrieval. By setting this option to `true`, | ||
in the cache. Defaults to `false`. | ||
- `cloneBuffersOnGet` - by default, buffers stored in the cache with `allowMixedContent` | ||
set to `true` are copied when they are set but not when they are retrieved. This means | ||
a change to the buffer returned by a `get()` will change the value in the cache. To prevent | ||
this, set `cloneBuffersOnGet` to `true` to always return a copy of the cached buffer. Defaults | ||
to `false`. |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
10424
2
180
30
- Removedbig-time@2.x.x
- Removedbig-time@2.0.1(transitive)
- Removedhoek@5.0.4(transitive)
Updatedhoek@6.x.x