-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmergebox-cache.js
109 lines (93 loc) · 3.69 KB
/
mergebox-cache.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
let isMeteor1_8 = (Meteor.release=='none' ? "1.8" : Meteor.release).match(/(\d+)\.(\d+)/);
isMeteor1_8 = (isMeteor1_8[1]*100 + isMeteor1_8[2]*1) >= 108;
function getCache(collection, _id) {
var instance = DDP._CurrentMethodInvocation.get() || DDP._CurrentPublicationInvocation.get();
if (!instance || !instance.userId || !instance.connection) {
return;
}
const result = {_id}; // ensure the _id field is included https://github.com/msavin/userCache/issues/9
try {
var connectionId = instance.connection.id;
var doc = isMeteor1_8
? Meteor.default_server.sessions.get(connectionId).collectionViews.get(collection).documents.get(_id)
: Meteor.default_server.sessions[connectionId].collectionViews[collection].documents[_id];
var data = doc && doc.dataByKey || [];
var source = isMeteor1_8 ? Array.from(data.entries()) : Object.keys(data);
source.forEach(isMeteor1_8
? (item) => result[item[0]] = item[1][0].value
: (item) => result[item] = data[item][0].value
);
} catch(e) {
// console.log('getCache error');
// console.log(e);
return;
}
return result;
}
function hasField(doc, field) {
field = field.split('.');
for (var i = 0; i < field.length; i++) {
if (Array.isArray(doc)) {
// https://github.com/msavin/userCache/issues/8
if (!doc.length) {
return;
}
if (field[i] === "[]") {
// Skip to next field, only required if requested field is eg "emails.[].address"
continue;
}
doc = doc[0];
}
doc = doc[field[i]];
// return true even if the field is falsy
if (!doc) {
return typeof doc != 'undefined';
}
}
return typeof doc != 'undefined';
}
Mongo.Collection.prototype.findOneOriginal = Mongo.Collection.prototype.findOne;
Mongo.Collection.prototype.updateOriginal = Mongo.Collection.prototype.update;
const updatedCollections = new Meteor.EnvironmentVariable();
Mongo.Collection.prototype.update = function(...args) {
const uc = updatedCollections.get() || [];
uc.push(this._name);
updatedCollections.set(uc);
return this.updateOriginal.apply(this, args);
}
Mongo.Collection.prototype.findOne = function(query, options) {
// check if we are in an autorun so instead of looking at the cache we need to use the original reactive version...
if (Tracker && Tracker.active) {
return this.findOneOriginal.apply(this, arguments);
}
if ((updatedCollections.get()||[]).indexOf(this._name)!=-1) {
// console.log('findOne', 'collection updated', this._name, query, options);
return this.findOneOriginal.apply(this, arguments);
}
// check we have a valid _id and only an _id query
const _id =
(typeof query == 'string') ? query
: (typeof query == 'object' && typeof query._id == 'string' && Object.keys(query).length==1) ? query._id
: null;
if (!_id) {
// console.log('findOne', 'no _id', this._name, query, options);
return this.findOneOriginal.apply(this, arguments);
}
// check there is at least one positive field selector and they are all +ve
if (!options || !options.fields || !Object.keys(options.fields).every(f => options.fields[f]===1 || options.fields[f]===true)) {
// console.log('findOne', 'not all fields selectors are +ve', this._name, query, options);
return this.findOneOriginal.apply(this, arguments);
}
const cache = getCache(this._name, _id);
if (!cache) {
// console.log('findOne', 'no cache', this._name, query, options);
return this.findOneOriginal.apply(this, arguments);
}
// check the cache contains all the required fields...
if (Object.keys(options.fields).every(field => hasField(cache, field))) {
// console.log('findOne', 'CACHE HIT! ', this._name, query, options);
return cache;
}
// console.log('findOne', 'cache miss', this._name, query, options);
return this.findOneOriginal.apply(this, arguments);
};