1 | 'use strict';
|
2 |
|
3 | var async = require('async');
|
4 | var fs = require('fs');
|
5 | var path = require('path');
|
6 | var utils = require('./utils');
|
7 |
|
8 | class CacheChain {
|
9 |
|
10 | constructor(caches, root, serveDir) {
|
11 | this.caches = caches;
|
12 | this.root = root;
|
13 | this.serveDir = serveDir;
|
14 | }
|
15 |
|
16 | get(localFilename) {
|
17 | return new Promise((resolved, rejected) => {
|
18 | this.caches[0].get(utils.localToRemoteFilename(localFilename, this.root, this.serveDir)).then((result) => {
|
19 | if (!result) return resolved();
|
20 | async.reduce(result.files, new Date(0), (date, filename, next) => {
|
21 | var testForFilename = path.resolve(path.dirname(localFilename), filename);
|
22 | fs.access(testForFilename, (err) => {
|
23 | if (err) return this.invalidate(localFilename).then(resolved, rejected);
|
24 | fs.stat(path.resolve(path.dirname(localFilename), filename), (err, stats) => {
|
25 | if (err) return next(err);
|
26 | var modificationDate = stats.mtime > stats.ctime ? stats.mtime : stats.ctime;
|
27 | next(null, modificationDate > date ? modificationDate : date);
|
28 | });
|
29 | });
|
30 | }, (err, date) => {
|
31 | if (err) return rejected(err);
|
32 | if (date > result.modificationDate) {
|
33 | return this.invalidate(localFilename).then(resolved, rejected);
|
34 | }
|
35 | resolved(result);
|
36 | });
|
37 | }, rejected);
|
38 | });
|
39 | }
|
40 |
|
41 | set(filename, data) {
|
42 | return this.caches[0].set(utils.localToRemoteFilename(filename, this.root, this.serveDir), data);
|
43 | }
|
44 |
|
45 | invalidate(filename, data) {
|
46 | return this.caches[0].invalidate(utils.localToRemoteFilename(filename, this.root, this.serveDir));
|
47 | }
|
48 |
|
49 | }
|
50 |
|
51 | module.exports = exports = CacheChain;
|