add initial version of library
This commit is contained in:
parent
6333eef901
commit
08f0db5b31
1 changed files with 57 additions and 0 deletions
57
src/index.ts
Normal file
57
src/index.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
import { createHash } from 'crypto';
|
||||
import { promises, writeFileSync } from 'fs';
|
||||
import { serialize, deserialize } from 'v8';
|
||||
|
||||
export const autocache = (path: string, mode: Mode) => {
|
||||
let cache = <Cache>new Map();
|
||||
let loading: Promise<void>;
|
||||
let removing = new Set<string>();
|
||||
let pending = new Map<string, any>();
|
||||
return {
|
||||
async cache(key: string, compute_value: () => Promise<any>) {
|
||||
const key_hashed = createHash('sha1').update(key).digest('hex');
|
||||
await (loading ||
|
||||
(loading = promises
|
||||
.readFile(path)
|
||||
.then(deserialize)
|
||||
.then((data: Cache) => {
|
||||
cache = data;
|
||||
for (const [key, [, modes]] of cache) {
|
||||
modes.delete(mode);
|
||||
if (modes.size === 0) {
|
||||
removing.add(key);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {})));
|
||||
let value: any, modes: Set<Mode>;
|
||||
if (cache.has(key_hashed)) {
|
||||
[value, modes] = cache.get(key_hashed);
|
||||
} else if (pending.has(key_hashed)) {
|
||||
return pending.get(key_hashed);
|
||||
} else {
|
||||
const promise = compute_value();
|
||||
pending.set(key_hashed, promise);
|
||||
value = await promise;
|
||||
modes = new Set();
|
||||
cache.set(key_hashed, [value, modes]);
|
||||
pending.delete(key_hashed);
|
||||
}
|
||||
removing.delete(key_hashed);
|
||||
modes.add(mode);
|
||||
return value;
|
||||
},
|
||||
close() {
|
||||
for (const key of removing) {
|
||||
cache.delete(key);
|
||||
}
|
||||
writeFileSync(path, serialize(cache));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
type Mode = string | number | boolean | null | undefined;
|
||||
|
||||
type CacheEntry = [any, Set<Mode>];
|
||||
|
||||
type Cache = Map<string, CacheEntry>;
|
Loading…
Add table
Reference in a new issue