node-haste/Cache: @flow

Reviewed By: davidaurelio

Differential Revision: D4043681

fbshipit-source-id: 8c82b394f4df9bb0d580f405ce472c69224485f5
This commit is contained in:
Jean Lauliac 2016-10-24 10:25:49 -07:00 committed by Facebook Github Bot
parent c253a8ba39
commit 3b0d4f4c33
1 changed files with 37 additions and 7 deletions

View File

@ -5,7 +5,10 @@
* This source code is licensed under the BSD-style license found in the * This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/ */
'use strict'; 'use strict';
const crypto = require('crypto'); const crypto = require('crypto');
@ -13,9 +16,10 @@ const denodeify = require('denodeify');
const fs = require('graceful-fs'); const fs = require('graceful-fs');
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const path = require('path'); const path = require('path');
/* $FlowFixMe: missing function definition. */
const tmpDir = require('os').tmpDir(); const tmpDir = require('os').tmpDir();
function getObjectValues(object) { function getObjectValues<T>(object: {[key: string]: T}): Array<T> {
return Object.keys(object).map(key => object[key]); return Object.keys(object).map(key => object[key]);
} }
@ -27,11 +31,26 @@ function debounce(fn, delay) {
}; };
} }
type Record = {
data: {[field: string]: Promise<mixed>},
metadata: {[field: string]: Promise<mixed>},
};
class Cache { class Cache {
_cacheFilePath: string;
_data: {[filename: string]: Record};
_persistEventually: () => void;
_persisting: ?Promise<boolean> | void;
constructor({ constructor({
resetCache, resetCache,
cacheKey, cacheKey,
cacheDirectory = tmpDir, cacheDirectory = tmpDir,
}: {
resetCache: boolean,
cacheKey: string,
cacheDirectory: string,
}) { }) {
this._cacheFilePath = Cache.getCacheFilePath(cacheDirectory, cacheKey); this._cacheFilePath = Cache.getCacheFilePath(cacheDirectory, cacheKey);
if (!resetCache) { if (!resetCache) {
@ -49,7 +68,11 @@ class Cache {
return path.join(tmpdir, hash.digest('hex')); return path.join(tmpdir, hash.digest('hex'));
} }
get(filepath, field, loaderCb) { get(
filepath: string,
field: string,
loaderCb: (filepath: string) => Promise<mixed>,
): Promise<mixed> {
if (!isAbsolutePath(filepath)) { if (!isAbsolutePath(filepath)) {
throw new Error('Use absolute paths'); throw new Error('Use absolute paths');
} }
@ -59,7 +82,7 @@ class Cache {
: this.set(filepath, field, loaderCb(filepath)); : this.set(filepath, field, loaderCb(filepath));
} }
invalidate(filepath, field) { invalidate(filepath: string, field: string) {
if (this.has(filepath, field)) { if (this.has(filepath, field)) {
if (field == null) { if (field == null) {
delete this._data[filepath]; delete this._data[filepath];
@ -73,15 +96,20 @@ class Cache {
return this._persistCache(); return this._persistCache();
} }
has(filepath, field) { has(filepath: string, field: string) {
return Object.prototype.hasOwnProperty.call(this._data, filepath) && return Object.prototype.hasOwnProperty.call(this._data, filepath) &&
(field == null || Object.prototype.hasOwnProperty.call(this._data[filepath].data, field)); (field == null || Object.prototype.hasOwnProperty.call(this._data[filepath].data, field));
} }
set(filepath, field, loaderPromise) { set(
filepath: string,
field: string,
loaderPromise: Promise<mixed>,
): Promise<mixed> {
let record = this._data[filepath]; let record = this._data[filepath];
if (!record) { if (!record) {
record = Object.create(null); // $FlowFixMe: temporarily invalid record.
record = (Object.create(null): Record);
this._data[filepath] = record; this._data[filepath] = record;
this._data[filepath].data = Object.create(null); this._data[filepath].data = Object.create(null);
this._data[filepath].metadata = Object.create(null); this._data[filepath].metadata = Object.create(null);
@ -127,7 +155,8 @@ class Cache {
return Promise return Promise
.all(fieldValues) .all(fieldValues)
.then(ref => { .then(ref => {
const ret = Object.create(null); // $FlowFixMe: temporarily invalid record.
const ret = (Object.create(null): Record);
ret.metadata = record.metadata; ret.metadata = record.metadata;
ret.data = Object.create(null); ret.data = Object.create(null);
fieldNames.forEach((field, index) => fieldNames.forEach((field, index) =>
@ -183,6 +212,7 @@ class Cache {
ret[key] = Object.create(null); ret[key] = Object.create(null);
ret[key].metadata = Object.create(null); ret[key].metadata = Object.create(null);
ret[key].data = Object.create(null); ret[key].data = Object.create(null);
// $FlowFixMe: we should maybe avoid Object.create().
ret[key].metadata.mtime = record.metadata.mtime; ret[key].metadata.mtime = record.metadata.mtime;
Object.keys(record.data).forEach(field => { Object.keys(record.data).forEach(field => {