Skip to content

Commit 6f3f756

Browse files
committed
Add caching support to HTTP server
1 parent f66e712 commit 6f3f756

3 files changed

Lines changed: 75 additions & 21 deletions

File tree

lib/express-http-server.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ class ExpressHTTPServer {
77
constructor(options) {
88
options = options || {};
99

10+
this.ui = options.ui;
1011
this.username = options.username;
1112
this.password = options.password;
13+
this.cache = options.cache;
14+
1215
this.app = express();
13-
this.ui = options.ui;
1416
}
1517

1618
serve(middleware) {
@@ -23,6 +25,10 @@ class ExpressHTTPServer {
2325
app.use(basicAuth(username, password));
2426
}
2527

28+
if (this.cache) {
29+
app.get('/*', this.buildCacheMiddleware());
30+
}
31+
2632
app.get('/*', middleware);
2733

2834
return new Promise(resolve => {
@@ -36,6 +42,46 @@ class ExpressHTTPServer {
3642
});
3743
});
3844
}
45+
46+
buildCacheMiddleware() {
47+
return (req, res, next) => {
48+
let path = req.path;
49+
50+
Promise.resolve(this.cache.fetch(path, req))
51+
.then(response => {
52+
if (response) {
53+
this.ui.writeLine(`cache hit; path=${path}`);
54+
res.send(response);
55+
} else {
56+
this.ui.writeLine(`cache miss; path=${path}`);
57+
this.interceptResponseCompletion(path, res);
58+
next();
59+
}
60+
})
61+
.catch(() => next());
62+
};
63+
}
64+
65+
interceptResponseCompletion(path, res) {
66+
let send = res.send.bind(res);
67+
68+
res.send = (body) => {
69+
let ret = send(body);
70+
71+
this.cache.put(path, body)
72+
.then(() => {
73+
this.ui.writeLine(`stored in cache; path=${path}`);
74+
})
75+
.catch(() => {
76+
let truncatedBody = body.replace(/\n/g).substr(0, 200);
77+
this.ui.writeLine(`error storing cache; path=${path}; body=${truncatedBody}...`);
78+
});
79+
80+
res.send = send;
81+
82+
return ret;
83+
};
84+
}
3985
}
4086

4187
module.exports = ExpressHTTPServer;

lib/fastboot-app-server.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,45 @@
33
const assert = require('assert');
44
const cluster = require('cluster');
55
const os = require('os');
6-
const path = require('path');
76

8-
const WORKER_PATH = path.join(__dirname, './worker.js');
7+
const Worker = require('./worker');
98

109
class FastBootAppServer {
1110
constructor(options) {
1211
options = options || {};
1312

14-
this.downloader = options.downloader;
1513
this.distPath = options.distPath;
14+
this.downloader = options.downloader;
1615
this.notifier = options.notifier;
17-
this.workerCount = options.workerCount || os.cpus().length;
16+
this.cache = options.cache;
1817
this.ui = options.ui;
1918

2019
if (!this.ui) {
2120
let UI = require('./ui');
2221
this.ui = new UI();
23-
this.propagateUI();
2422
}
2523

26-
assert(this.distPath || this.downloader, "FastBootAppServer must be provided with either a distPath or a downloader option.");
27-
assert(!(this.distPath && this.downloader), "FastBootAppServer must be provided with either a distPath or a downloader option, but not both.");
24+
this.propagateUI();
25+
26+
if (cluster.isWorker) {
27+
this.worker = new Worker({
28+
ui: this.ui,
29+
distPath: this.distPath || process.env.FASTBOOT_DIST_PATH,
30+
cache: this.cache
31+
});
32+
33+
this.worker.start();
34+
} else {
35+
this.workerCount = options.workerCount || os.cpus().length;
36+
37+
assert(this.distPath || this.downloader, "FastBootAppServer must be provided with either a distPath or a downloader option.");
38+
assert(!(this.distPath && this.downloader), "FastBootAppServer must be provided with either a distPath or a downloader option, but not both.");
39+
}
2840
}
2941

3042
start() {
43+
if (cluster.isWorker) { return; }
44+
3145
return this.initializeApp()
3246
.then(() => this.subscribeToNotifier())
3347
.then(() => this.forkWorkers())
@@ -44,6 +58,7 @@ class FastBootAppServer {
4458
propagateUI() {
4559
if (this.downloader) { this.downloader.ui = this.ui; }
4660
if (this.notifier) { this.notifier.ui = this.ui; }
61+
if (this.cache) { this.cache.ui = this.ui; }
4762
}
4863

4964
initializeApp() {
@@ -118,10 +133,6 @@ class FastBootAppServer {
118133
}
119134

120135
forkWorker() {
121-
cluster.setupMaster({
122-
exec: WORKER_PATH
123-
});
124-
125136
let env = this.buildWorkerEnv();
126137
let worker = cluster.fork(env);
127138

lib/worker.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
const FastBoot = require('fastboot');
44
const fastbootMiddleware = require('fastboot-express-middleware');
55
const ExpressHTTPServer = require('./express-http-server');
6-
const UI = require('./ui');
76

87
class Worker {
98
constructor(options) {
109
this.distPath = options.distPath;
1110
this.httpServer = options.httpServer;
1211
this.ui = options.ui;
12+
this.cache = options.cache;
1313

1414
if (!this.httpServer) {
15-
this.httpServer = new ExpressHTTPServer();
16-
this.httpServer.ui = this.ui;
15+
this.httpServer = new ExpressHTTPServer({
16+
ui: this.ui,
17+
cache: this.cache
18+
});
1719
}
1820
}
1921

@@ -75,9 +77,4 @@ class Worker {
7577
}
7678
}
7779

78-
let worker = new Worker({
79-
distPath: process.env.FASTBOOT_DIST_PATH || false,
80-
ui: new UI()
81-
});
82-
83-
worker.start();
80+
module.exports = Worker;

0 commit comments

Comments
 (0)