Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ const myCache = new NodeCache();
_Here's a [simple code example](https://runkit.com/mpneuried/useclones-example-83) showing the different behavior_
- `deleteOnExpire`: *(default: `true`)* whether variables will be deleted automatically when they expire.
If `true` the variable will be deleted. If `false` the variable will remain. You are encouraged to handle the variable upon the event `expired` by yourself.
- `enableLegacyCallbacks`: *(default: `false`)* re-enables the usage of callbacks instead of sync functions. adds an additional `cb` argument to each function which resolves to `(err, result)`. will be removed in node-cache v6.x.
- `enableLegacyCallbacks`: *(default: `false`)* re-enables the usage of callbacks instead of sync functions. Adds an additional `cb` argument to each function which resolves to `(err, result)`. will be removed in node-cache v6.x.
- `maxKeys`: *(default: `-1`)* specifies a maximum amount of keys that can be stored in the cache. If a new item is set and the cache is full, an error is thrown and the key will not be saved in the cache. -1 disables the key limit.

```js
const NodeCache = require( "node-cache" );
Expand Down
9 changes: 8 additions & 1 deletion _src/lib/node_cache.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ module.exports = class NodeCache extends EventEmitter
deleteOnExpire: true
# enable legacy callbacks
enableLegacyCallbacks: false
# max amount of keys that are being stored
maxKeys: -1
, @options )

# generate functions with callbacks (legacy)
if (@options.enableLegacyCallbacks)
console.warn("WARNING! node-cache legacy callback support will drop in v6.x")

[
"get",
"mget",
Expand Down Expand Up @@ -166,6 +167,11 @@ module.exports = class NodeCache extends EventEmitter
# console.log( err, success )
#
set: ( key, value, ttl )=>
# check if cache is overflowing
if (@stats.keys >= @options.maxKeys && @options.maxKeys > -1)
_err = @_error( "ECACHEFULL" )
throw _err

# force the data to string
if @options.forceString and not typeof value is "string"
value = JSON.stringify( value )
Expand Down Expand Up @@ -600,5 +606,6 @@ module.exports = class NodeCache extends EventEmitter

_ERRORS:
"ENOTFOUND": "Key `__key` not found"
"ECACHEFULL": "Cache max key size exceeded"
"EKEYTYPE": "The key argument has to be of type `string` or `number`. Found: `__key`"
"EKEYSTYPE": "The keys argument has to be an array."
143 changes: 76 additions & 67 deletions _src/test/mocha_test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ localCacheNoClone = new nodeCache({
checkperiod: 0
})

localCacheMaxKeys = new nodeCache({
maxKeys: 2
})

localCacheTTL = new nodeCache({
stdTTL: 0.3,
Expand Down Expand Up @@ -280,6 +283,40 @@ describe "`#{pkg.name}@#{pkg.version}` on `node@#{process.version}`", () ->

return

describe "max key amount", () ->
before () ->
state =
key1: randomString(10)
key2: randomString(10)
key3: randomString(10)
value1: randomString(10)
value2: randomString(10)
value3: randomString(10)
return

it "exceed max key size", () ->
setKey = localCacheMaxKeys.set(state.key1, state.value1, 0)
true.should.eql setKey

setKey2 = localCacheMaxKeys.set(state.key2, state.value2, 0)
true.should.eql setKey2

(() -> localCacheMaxKeys.set(state.key3, state.value3, 0)).should.throw({
name: "ECACHEFULL"
message: "Cache max key size exceeded"
})
return

it "remove a key and set another one", () ->
del = localCacheMaxKeys.del(state.key1)
1.should.eql del

setKey3 = localCacheMaxKeys.set(state.key3, state.value3, 0)
true.should.eql setKey3
return

return

describe "correct and incorrect key types", () ->
describe "number", () ->
before () ->
Expand All @@ -293,42 +330,32 @@ describe "`#{pkg.name}@#{pkg.version}` on `node@#{process.version}`", () ->

it "set", () ->
for key in state.keys
localCache.set key, state.val, (err, res) ->
should.not.exist err
true.should.eql res
return
res = localCache.set key, state.val
true.should.eql res
return

it "get", () ->
localCache.get state.keys[0], (err, res) ->
should.not.exist err
state.val.should.eql res
return
res = localCache.get state.keys[0]
state.val.should.eql res
return

it "mget", () ->
localCache.mget state.keys[0..1], (err, res) ->
should.not.exist err
# generate prediction
prediction = {}
prediction[state.keys[0]] = state.val
prediction[state.keys[1]] = state.val
prediction.should.eql res
return
res = localCache.mget state.keys[0..1]
# generate prediction
prediction = {}
prediction[state.keys[0]] = state.val
prediction[state.keys[1]] = state.val
prediction.should.eql res
return

it "del single", () ->
localCache.del state.keys[0], (err, count) ->
should.not.exist err
1.should.eql count
return
count = localCache.del state.keys[0]
1.should.eql count
return

it "del multi", () ->
localCache.del state.keys[1..2], (err, count) ->
should.not.exist err
2.should.eql count
return
count = localCache.del state.keys[1..2]
2.should.eql count
return

it "ttl", (done) ->
Expand Down Expand Up @@ -372,42 +399,32 @@ describe "`#{pkg.name}@#{pkg.version}` on `node@#{process.version}`", () ->

it "set", () ->
for key in state.keys
localCache.set key, state.val, (err, res) ->
should.not.exist err
true.should.eql res
return
res = localCache.set key, state.val
true.should.eql res
return

it "get", () ->
localCache.get state.keys[0], (err, res) ->
should.not.exist err
state.val.should.eql res
return
res = localCache.get state.keys[0]
state.val.should.eql res
return

it "mget", () ->
localCache.mget state.keys[0..1], (err, res) ->
should.not.exist err
# generate prediction
prediction = {}
prediction[state.keys[0]] = state.val
prediction[state.keys[1]] = state.val
prediction.should.eql res
return
res = localCache.mget state.keys[0..1]
# generate prediction
prediction = {}
prediction[state.keys[0]] = state.val
prediction[state.keys[1]] = state.val
prediction.should.eql res
return

it "del single", () ->
localCache.del state.keys[0], (err, count) ->
should.not.exist err
1.should.eql count
return
count = localCache.del state.keys[0]
1.should.eql count
return

it "del multi", () ->
localCache.del state.keys[1..2], (err, count) ->
should.not.exist err
2.should.eql count
return
count = localCache.del state.keys[1..2]
2.should.eql count
return

it "ttl", (done) ->
Expand Down Expand Up @@ -832,13 +849,11 @@ describe "`#{pkg.name}@#{pkg.version}` on `node@#{process.version}`", () ->
return

it "set a key with ttl", () ->
localCache.set state.key1, state.val, 0.7, (err, res) ->
should.not.exist err
true.should.eql res
ts = localCache.getTtl state.key1
if state.now < ts < state.now + 300
throw new Error "Invalid timestamp"
return
res = localCache.set state.key1, state.val, 0.7
true.should.eql res
ts = localCache.getTtl state.key1
if state.now < ts < state.now + 300
throw new Error "Invalid timestamp"
return

it "check this key immediately", () ->
Expand Down Expand Up @@ -870,17 +885,13 @@ describe "`#{pkg.name}@#{pkg.version}` on `node@#{process.version}`", () ->
return

it "set another key with ttl", () ->
localCache.set state.key2, state.val, 0.5, (err, res) ->
should.not.exist err
true.should.eql res
return
res = localCache.set state.key2, state.val, 0.5
true.should.eql res
return

it "check this key immediately", () ->
localCache.get state.key2, (err, res) ->
should.not.exist err
state.val.should.eql res
return
res = localCache.get state.key2
state.val.should.eql res
return

it "before it times out", () ->
Expand Down Expand Up @@ -969,10 +980,8 @@ describe "`#{pkg.name}@#{pkg.version}` on `node@#{process.version}`", () ->
return

it "check if the key still exists", () ->
localCache.get state.key3, (err, res) ->
should.not.exist err
state.val.should.eql res
return
res = localCache.get state.key3
state.val.should.eql res
return

it "wait until ttl has ended and check if the key was deleted", (done) ->
Expand Down