New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

sequelize-simple-cache

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sequelize-simple-cache - npm Package Compare versions

Comparing version 1.0.0-beta.11 to 1.0.0-beta.12

2

package.json
{
"name": "sequelize-simple-cache",
"version": "1.0.0-beta.11",
"version": "1.0.0-beta.12",
"description": "A simple, transparent, client-side, in-memory cache for Sequelize",

@@ -5,0 +5,0 @@ "main": "src/SequelizeSimpleCache.js",

@@ -105,2 +105,13 @@ # sequelize-simple-cache

### Limit
This cache meant as a simple in-memory read cache for a very limited amount of data.
So, you should be able to control the size of the cache.
```javascript
const cache = new SequelizeSimpleCache({
User: { }, // default limit is 50
Page: { limit: 30 },
});
```
### Logging

@@ -110,3 +121,3 @@

Logging goes to `console.debug()` unless you set `delegate` to log somewhere else.
`event` is one of: `init`, `hit`, `miss`, `load` or `ops`.
`event` is one of: `init`, `hit`, `miss`, `load`, `purge` or `ops`.
```javascript

@@ -113,0 +124,0 @@ const cache = new SequelizeSimpleCache({

@@ -10,7 +10,12 @@ const md5 = require('md5');

methods: ['findById', 'findOne', 'findAll', 'findAndCountAll', 'count', 'min', 'max', 'sum'],
limit: 50,
};
this.config = Object.entries(config)
.reduce((acc, [type, { ttl = defaults.ttl, methods = defaults.methods }]) => ({
.reduce((acc, [type, {
ttl = defaults.ttl,
methods = defaults.methods,
limit = defaults.limit,
}]) => ({
...acc,
[type]: { ttl, methods },
[type]: { ttl, methods, limit },
}), {});

@@ -25,4 +30,6 @@ const {

this.delegate = delegate;
this.cache = new Map();
this.stats = { hit: 0, miss: 0, load: 0 };
this.cache = {};
this.stats = {
hit: 0, miss: 0, load: 0, purge: 0,
};
if (this.ops > 0) {

@@ -53,4 +60,9 @@ this.heart = setInterval(() => {

if (!config) return model; // no caching for this model
const { ttl, methods } = config;
this.log('init', { type, ttl, methods });
const { ttl, methods, limit } = config;
// create map for model
const cache = new Map();
this.cache[type] = cache;
this.log('init', {
type, ttl, methods, limit,
});
// proxy for intercepting Sequelize methods

@@ -65,3 +77,3 @@ return new Proxy(model, {

const hash = md5(key);
const item = this.cache.get(hash);
const item = cache.get(hash);
if (item) { // hit

@@ -80,4 +92,12 @@ const { data, expires } = item;

const expires = Date.now() + ttl * 1000;
this.cache.set(hash, { data, expires, type });
cache.set(hash, { data, expires });
this.log('load', { key, hash, expires });
if (cache.size > limit) { // check cache limit
let oldest = {};
cache.forEach(({ expires: e }, h) => {
if (!oldest.h || e < oldest.e) oldest = { h, e };
});
cache.delete(oldest.h);
this.log('purge', { hash: oldest.h, expires: oldest.e });
}
}

@@ -100,20 +120,24 @@ return data; // resolve from database

clear(...modelnames) {
if (!modelnames.length) {
this.cache.clear();
return;
}
this.cache.forEach(({ type }, key) => {
if (modelnames.includes(type)) {
this.cache.delete(key);
}
const types = modelnames.length ? modelnames : Object.keys(this.cache);
types.forEach((type) => {
const cache = this.cache[type];
if (!cache) return;
cache.clear();
});
}
size(...modelnames) {
const types = modelnames.length ? modelnames : Object.keys(this.cache);
return types
.filter(type => this.cache[type])
.reduce((acc, type) => acc + this.cache[type].size, 0);
}
log(event, details = {}) {
// stats
if (['hit', 'miss', 'load'].includes(event)) {
if (['hit', 'miss', 'load', 'purge'].includes(event)) {
this.stats[event] += 1;
}
// logging
if (!this.debug && ['init', 'hit', 'miss', 'load'].includes(event)) return;
if (!this.debug && ['init', 'hit', 'miss', 'load', 'purge'].includes(event)) return;
this.delegate(event, {

@@ -123,3 +147,4 @@ ...details,

ratio: this.stats.hit / (this.stats.hit + this.stats.miss),
size: this.cache.size,
size: Object.entries(this.cache)
.reduce((acc, [type, map]) => ({ ...acc, [type]: map.size }), {}),
});

@@ -126,0 +151,0 @@ }

@@ -129,7 +129,7 @@ const chai = require('chai');

const result2 = await Page.findOne({ where: { foo: true } });
expect(cache.cache.size).to.be.equal(2);
expect(cache.size()).to.be.equal(2);
cache.clear('User');
expect(result1).to.be.deep.equal({ username: 'fred' });
expect(result2).to.be.deep.equal({ foo: true });
expect(cache.cache.size).to.be.equal(1);
expect(cache.size()).to.be.equal(1);
});

@@ -386,2 +386,20 @@

});
it('should ensure limit is not exceeded', async () => {
const model = {
name: 'User',
findOne: async () => ({ username: 'fred' }),
};
const cache = new SequelizeSimpleCache({ User: { limit: 3 } }, { ops: false });
const User = cache.init(model);
await User.findOne({ where: { username: 'john' } });
await new Promise(resolve => setTimeout(() => resolve(), 16));
await User.findOne({ where: { username: 'jim' } });
await new Promise(resolve => setTimeout(() => resolve(), 16));
await User.findOne({ where: { username: 'bob' } });
await new Promise(resolve => setTimeout(() => resolve(), 16));
expect(cache.size()).to.be.equal(3);
await User.findOne({ where: { username: 'ron' } });
expect(cache.size()).to.be.equal(3);
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc