Skip to content

Commit

Permalink
Merge pull request #8 from biothings/fix-896-bte
Browse files Browse the repository at this point in the history
Add file locking mechanism
  • Loading branch information
tokebe authored Nov 13, 2024
2 parents 0e5358b + 55c6640 commit 0e6cd42
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
"devDependencies": {
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^11.0.0",
"biolink-model": "workspace:../biolink-model",
"@types/debug": "^4.1.10",
"@types/jest": "^29.5.7",
"@types/lodash": "^4.14.200",
"@types/node": "^20.8.10",
"@typescript-eslint/eslint-plugin": "^6.8.0",
"@typescript-eslint/parser": "^6.8.0",
"biolink-model": "workspace:../biolink-model",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
Expand All @@ -59,6 +59,7 @@
"ioredis": "^5.3.2",
"ioredis-mock": "^8.9.0",
"lodash": "^4.17.21",
"proper-lockfile": "^4.1.2",
"redlock": "5.0.0-beta.2"
}
}
38 changes: 38 additions & 0 deletions src/misc.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import lockfile from "proper-lockfile";

export function toArray<Type>(input: Type | Type[]): Type[] {
if (Array.isArray(input)) {
return input;
Expand Down Expand Up @@ -76,3 +78,39 @@ export function timeoutPromise<T>(promise: Promise<T>, timeout: number): Promise
reject = newReject;
});
}

export const LOCKFILE_STALENESS = {stale: 5000}; // lock expiration in milliseconds to prevent deadlocks
export const LOCKFILE_RETRY_CONFIG = {
retries: {
retries: 10,
factor: 2,
minTimeout: 100,
maxTimeout: 1000,
},
stale: LOCKFILE_STALENESS["stale"],
};

export async function lockWithActionAsync<T>(filePaths: string[], action: () => Promise<T>, debug?: (message: string) => void, lockfileRetryConfig?: any): Promise<T> {
if (process.env.NODE_ENV !== "production") {
debug(`Development mode: Skipping lockfile ${process.env.NODE_ENV}`);
const result = await action();
return result;
}

const releases: (() => void)[] = [];
const retryConfig = lockfileRetryConfig || LOCKFILE_RETRY_CONFIG;
try {
for (const filePath of filePaths) {
let release = await lockfile.lock(filePath, retryConfig);
releases.push(release);
}
const result = await action();
return result;
} catch (error) {
debug(`Lockfile error: ${error}`);
// throw error;
} finally {
for (const release of releases)
if (release) release();
}
}

0 comments on commit 0e6cd42

Please sign in to comment.