@x5e/gink
Version:
an eventually consistent database
65 lines (57 loc) • 1.86 kB
text/typescript
import { flock } from "fs-ext";
import { FileHandle, open } from "fs/promises";
import { Stats } from "fs";
export class LockableFile {
protected fileHandle: FileHandle;
protected fileLocked: boolean = false;
private lockableFileReady: Promise<void>;
constructor(
readonly filename: string,
readonly exclusive: boolean = false,
) {
this.lockableFileReady = this.initializeLockableFile();
}
get ready() {
return this.lockableFileReady;
}
private async initializeLockableFile(): Promise<void> {
this.fileHandle = await open(this.filename, "a+");
if (this.exclusive) {
await this.lockFile(false);
}
}
protected async lockFile(block: boolean): Promise<boolean> {
const thisLockableFile = this;
return new Promise((resolve, reject) => {
flock(this.fileHandle.fd, block ? "ex" : "exnb", (err) => {
if (err) {
return reject(err);
}
thisLockableFile.fileLocked = true;
resolve(true);
});
});
}
protected async unlockFile(): Promise<void> {
const thisLogBackedStore = this;
return new Promise((resolve, reject) => {
flock(this.fileHandle.fd, "un", async (err) => {
if (err) {
return reject(err);
}
thisLogBackedStore.fileLocked = false;
resolve();
});
});
}
protected async getFileLength(): Promise<number> {
let stats: Stats;
try {
stats = await this.fileHandle.stat();
} catch (problem) {
console.error(`problem with fileHandle.stat ${problem}`);
throw problem;
}
return stats.size;
}
}