Skip to content

Commit e916775

Browse files
Fixed #182 added named query cacher
1 parent 200d2fb commit e916775

File tree

8 files changed

+129
-63
lines changed

8 files changed

+129
-63
lines changed

lib/namedQuery/README.md

-57
This file was deleted.
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {Meteor} from 'meteor/meteor';
2+
import cloneDeep from 'lodash.cloneDeep';
3+
4+
const DEFAULT_TTL = 60000;
5+
6+
/**
7+
* This is a very basic in-memory result caching functionality
8+
*/
9+
export default class MemoryResultCacher {
10+
constructor(config = {}) {
11+
this.store = {};
12+
this.config = config;
13+
}
14+
15+
get(cacheId, {
16+
query,
17+
countCursor,
18+
}) {
19+
const cacheData = this.store[cacheId];
20+
if (cacheData !== undefined) {
21+
return cloneDeep(cacheData);
22+
}
23+
24+
let data;
25+
if (query) {
26+
data = query.fetch();
27+
} else {
28+
data = countCursor.count();
29+
}
30+
31+
this.set(cacheId, data);
32+
33+
return data;
34+
}
35+
36+
set(cacheId, data) {
37+
const ttl = this.config.ttl || DEFAULT_TTL;
38+
this.store[cacheId] = cloneDeep(data);
39+
40+
Meteor.setTimeout(() => {
41+
delete this.store[cacheId];
42+
}, ttl)
43+
}
44+
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import {EJSON} from 'meteor/ejson';
2+
3+
export default function(queryName, params) {
4+
return `${queryName}::${EJSON.stringify(params)}`;
5+
}

lib/namedQuery/namedQuery.base.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@ export default class NamedQueryBase {
2424
}
2525

2626
clone(newParams) {
27-
return new this.constructor(
27+
let clone = new this.constructor(
2828
this.queryName,
2929
this.collection,
3030
deepClone(this.body),
3131
_.extend({}, deepClone(this.params), newParams)
3232
);
33+
34+
clone.cacher = this.cacher;
35+
36+
return clone;
3337
}
3438
}

lib/namedQuery/namedQuery.server.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import prepareForProcess from '../query/lib/prepareForProcess.js';
22
import Base from './namedQuery.base';
33
import deepClone from 'lodash.cloneDeep';
4+
import MemoryResultCacher from './cache/MemoryResultCacher';
5+
import generateQueryId from './cache/generateQueryId';
46

57
export default class extends Base {
68
/**
@@ -13,6 +15,11 @@ export default class extends Base {
1315
deepClone(this.params)
1416
);
1517

18+
if (this.cacher) {
19+
const cacheId = generateQueryId(this.queryName, this.params);
20+
return this.cacher.get(cacheId, {query});
21+
}
22+
1623
return query.fetch();
1724
}
1825

@@ -30,7 +37,15 @@ export default class extends Base {
3037
* @returns {any}
3138
*/
3239
getCount() {
33-
return this.getCursorForCounting().count();
40+
const countCursor = this.getCursorForCounting();
41+
42+
if (this.cacher) {
43+
const cacheId = 'count::' + generateQueryId(this.queryName, this.params);
44+
45+
return this.cacher.get(cacheId, {countCursor});
46+
}
47+
48+
return countCursor.count();
3449
}
3550

3651
/**
@@ -42,4 +57,15 @@ export default class extends Base {
4257

4358
return this.collection.find(body.$filters || {}, {fields: {_id: 1}});
4459
}
60+
61+
/**
62+
* @param cacher
63+
*/
64+
cacheResults(cacher) {
65+
if (!cacher) {
66+
cacher = new MemoryResultCacher();
67+
}
68+
69+
this.cacher = cacher;
70+
}
4571
}

lib/namedQuery/testing/bootstrap/server.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createQuery } from 'meteor/cultofcoders:grapher';
1+
import { createQuery, MemoryResultCacher } from 'meteor/cultofcoders:grapher';
22
import postListExposure from './queries/postListExposure.js';
33

44
const postList = createQuery('postList', {
@@ -16,6 +16,7 @@ const postList = createQuery('postList', {
1616
}
1717
});
1818

19+
1920
export { postList };
2021
export { postListExposure };
2122

@@ -28,3 +29,15 @@ postListExposure.expose({
2829
}
2930
}
3031
});
32+
33+
const postListCached = createQuery('postListCached', {
34+
posts: {
35+
title: 1,
36+
}
37+
});
38+
39+
export {postListCached};
40+
41+
postListCached.cacheResults(new MemoryResultCacher({
42+
ttl: 400,
43+
}));

lib/namedQuery/testing/server.test.js

+30-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { postList } from './bootstrap/server.js';
1+
import { postList, postListCached } from './bootstrap/server.js';
22
import { createQuery } from 'meteor/cultofcoders:grapher';
33

4+
45
describe('Named Query', function () {
56
it('Should return the proper values', function () {
67
const createdQuery = createQuery({
@@ -42,5 +43,31 @@ describe('Named Query', function () {
4243
assert.isObject(post.author);
4344
assert.isObject(post.group);
4445
})
45-
})
46-
});
46+
});
47+
48+
it('Should properly cache the values', function (done) {
49+
const posts = postListCached.fetch();
50+
const postsCount = postListCached.getCount();
51+
52+
const Posts = Mongo.Collection.get('posts');
53+
const postId = Posts.insert({title: 'Hello Cacher!'});
54+
55+
assert.equal(posts.length, postListCached.fetch().length);
56+
assert.equal(postsCount, postListCached.getCount());
57+
58+
Meteor.setTimeout(function () {
59+
const newPosts = postListCached.fetch();
60+
const newCount = postListCached.getCount();
61+
62+
Posts.remove(postId);
63+
64+
assert.isArray(newPosts);
65+
assert.isNumber(newCount);
66+
67+
assert.equal(posts.length + 1, newPosts.length);
68+
assert.equal(postsCount + 1, newCount);
69+
70+
done();
71+
}, 500)
72+
});
73+
});

main.server.js

+4
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@ export {
2121
default as getDocumentationObject
2222
} from './lib/documentor/index.js';
2323

24+
export {
25+
default as MemoryResultCacher
26+
} from './lib/namedQuery/cache/MemoryResultCacher';
27+
2428
export { Types } from './lib/constants';

0 commit comments

Comments
 (0)