UNPKG

2.52 kBJavaScriptView Raw
1var Eidetic = require('eidetic');
2var cacheStore = new Eidetic({
3 maxSize: 50,
4 canPutWhenFull: true
5});
6
7var queues = {};
8var redirects = {};
9
10module.exports.cacheSeconds = function(ttl) {
11
12 return function(req, res, next) {
13 var key = req.originalUrl;
14 if (redirects[key]) return res.redirect(redirects[key]);
15
16 var value = cacheStore.get(key);
17
18 if (value) {
19 // returns the value immediately
20 if (value.isJson) {
21 res.json(value.body);
22 } else {
23 res.send(value.body);
24 }
25 return;
26 }
27
28 res.original_send = res.send;
29 res.original_json = res.json;
30 res.original_redirect = res.redirect;
31
32 if (!queues[key]) {
33 queues[key] = [];
34 }
35
36 // first request will get rendered output
37 if (queues[key].length === 0
38 && queues[key].push(function noop(){})) {
39
40 var didHandle = false;
41
42 function rawSend(data, isJson) {
43 didHandle = true;
44
45 var body = data instanceof Buffer ? data.toString() : data;
46 if (res.statusCode < 400) cacheStore.put(key, { body: body, isJson: isJson }, ttl);
47
48 // drain the queue so anyone else waiting for
49 // this value will get their responses.
50 var subscriber = null;
51 while (subscriber = queues[key].shift()) {
52 if (subscriber) {
53 process.nextTick(subscriber);
54 }
55 }
56
57 if (isJson) {
58 res.original_json(body);
59 } else {
60 res.original_send(body);
61 }
62 }
63
64 res.send = function (data) {
65 if (didHandle) {
66 res.original_send(data);
67 } else {
68 rawSend(data, false);
69 }
70 };
71
72 res.json = function (data) {
73 rawSend(data, true);
74 };
75
76 // If response happens to be a redirect -- store it to redirect all
77 // subsequent requests.
78 res.redirect = function(string) {
79 var body = string instanceof Buffer ? string.toString() : string;
80 redirects[key] = body;
81 res.original_redirect(body);
82 };
83
84 next();
85 // subsequent requests will batch while the first computes
86 } else {
87 queues[key].push(function() {
88 var value = cacheStore.get(key) || {};
89 if (value.isJson) {
90 res.json(value.body);
91 } else {
92 res.send(value.body);
93 }
94 });
95 }
96
97 }
98
99};
100
101
102module.exports.removeCache = function(url) {
103 if (redirects[url])
104 delete redirects[url];
105 cacheStore.del(url);
106};
107
108
109module.exports.cacheStore = cacheStore;