import type { IDataStore } from "../repo"; import * as Fs from "fs"; import * as Path from "path"; export default class FSDataStore implements IDataStore { #path: string; #l = false; constructor(path: string) { this.#path = path; } async get(name: string) { return Fs.promises.readFile(Path.join(this.#path, name)); } async has(name: string) { return Fs.promises .access(Path.join(this.#path, name)) .then(() => true) .catch(() => false); } async set(name: string, data: Uint8Array) { const path = Path.join(this.#path, name); await Fs.promises.mkdir(Path.dirname(path), { recursive: true }); await Fs.promises.writeFile(path, data); } async _delete(name: string) { await Fs.promises.rm(Path.join(this.#path, name)); } async getLock() { //TODO: This is not atomic yet! FIX while ((await this.has("lock")) || this.#l) { try { let con = (await this.get("lock")).toString("utf-8"); if (Number(con) < Date.now() - 10000) break; await new Promise((y) => setTimeout(y, 10)); } catch (err) {} } this.#l = true; await this.set("lock", Buffer.from(`${Date.now()}`)); this.#l = false; return async () => { await this._delete("lock"); }; } }