1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | const fs = require('fs');
|
11 | const path = require('path');
|
12 | const zlib = require('zlib');
|
13 | const {promisify} = require('util');
|
14 |
|
15 | const makeDir = require('make-dir');
|
16 |
|
17 | const readFile = promisify(fs.readFile);
|
18 | const writeFile = promisify(fs.writeFile);
|
19 | const gunzip = promisify(zlib.gunzip);
|
20 | const gzip = promisify(zlib.gzip);
|
21 |
|
22 | module.exports = class PersistentDiskCache /*::<T>*/ {
|
23 | |
24 |
|
25 |
|
26 | constructor(cacheDirectory /*:string*/) {
|
27 | this.cacheDirectory = cacheDirectory;
|
28 | }
|
29 | async get(cacheKey /*: string*/, thunk /*: () => T */) {
|
30 | const filepath = getFilePath(this.cacheDirectory, cacheKey);
|
31 |
|
32 | try {
|
33 | return await read(filepath);
|
34 | } catch (err) {
|
35 |
|
36 | }
|
37 |
|
38 | const result = thunk();
|
39 |
|
40 | try {
|
41 | await makeDir(this.cacheDirectory);
|
42 | await write(filepath, result);
|
43 | } catch (err) {
|
44 |
|
45 | }
|
46 |
|
47 | return result;
|
48 | }
|
49 |
|
50 | async read(cacheKey ) {
|
51 | const path = getFilePath(this.cacheDirectory, cacheKey);
|
52 | return await read(path);
|
53 | }
|
54 |
|
55 | exists(cacheKey ) {
|
56 | const filepath = getFilePath(this.cacheDirectory, cacheKey);
|
57 | return fs.existsSync(filepath);
|
58 | }
|
59 | };
|
60 | async function read(path /*: string*/) {
|
61 | const data = await readFile(path);
|
62 | const content = await gunzip(data);
|
63 | return JSON.parse(content);
|
64 | }
|
65 | async function write(path /*: string*/, result) {
|
66 | const content = JSON.stringify(result);
|
67 | const data = await gzip(content);
|
68 | return await writeFile(path, data);
|
69 | }
|
70 |
|
71 | function getFilePath(dirname, cacheKey) {
|
72 | return path.join(dirname, `${cacheKey}.json.gz`);
|
73 | }
|