From 88e9cfa4e3589b8e89ee4d8a23a219949a709af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Lucas=20de=20Oliveira=20Lopes?= <55464917+jlucaso1@users.noreply.github.com> Date: Fri, 14 Mar 2025 19:45:30 -0300 Subject: [PATCH] refactor: replace async-lock with async-mutex (#1304) Co-authored-by: Rajeh Taher --- package.json | 4 -- src/Utils/use-multi-file-auth-state.ts | 67 ++++++++++++++++++-------- yarn.lock | 40 +-------------- 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 6c46c54..7410c6d 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "@cacheable/node-cache": "^1.4.0", "@hapi/boom": "^9.1.3", "@whiskeysockets/eslint-config": "github:whiskeysockets/eslint-config", - "async-lock": "^1.4.1", "async-mutex": "^0.5.0", "axios": "^1.6.0", "cache-manager": "^5.7.6", @@ -51,14 +50,11 @@ "music-metadata": "^7.12.3", "pino": "^9.6", "protobufjs": "^7.2.4", - "uuid": "^10.0.0", "ws": "^8.13.0" }, "devDependencies": { - "@types/got": "^9.6.11", "@types/jest": "^27.5.1", "@types/node": "^16.0.0", - "@types/sharp": "^0.29.4", "@types/ws": "^8.0.0", "conventional-changelog-cli": "^2.2.2", "eslint": "^8.0.0", diff --git a/src/Utils/use-multi-file-auth-state.ts b/src/Utils/use-multi-file-auth-state.ts index c3f6cee..94d1712 100644 --- a/src/Utils/use-multi-file-auth-state.ts +++ b/src/Utils/use-multi-file-auth-state.ts @@ -1,4 +1,4 @@ -import AsyncLock from 'async-lock' +import { Mutex } from 'async-mutex' import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises' import { join } from 'path' import { proto } from '../../WAProto' @@ -9,9 +9,19 @@ import { BufferJSON } from './generics' // We need to lock files due to the fact that we are using async functions to read and write files // https://github.com/WhiskeySockets/Baileys/issues/794 // https://github.com/nodejs/node/issues/26338 -// Default pending is 1000, set it to infinity -// https://github.com/rogierschouten/async-lock/issues/63 -const fileLock = new AsyncLock({ maxPending: Infinity }) +// Use a Map to store mutexes for each file path +const fileLocks = new Map() + +// Get or create a mutex for a specific file path +const getFileLock = (path: string): Mutex => { + let mutex = fileLocks.get(path) + if(!mutex) { + mutex = new Mutex() + fileLocks.set(path, mutex) + } + + return mutex +} /** * stores the full authentication state in a single folder. @@ -22,22 +32,32 @@ const fileLock = new AsyncLock({ maxPending: Infinity }) * */ export const useMultiFileAuthState = async(folder: string): Promise<{ state: AuthenticationState, saveCreds: () => Promise }> => { // eslint-disable-next-line @typescript-eslint/no-explicit-any - const writeData = (data: any, file: string) => { + const writeData = async(data: any, file: string) => { const filePath = join(folder, fixFileName(file)!) - return fileLock.acquire( - filePath, - () => writeFile(join(filePath), JSON.stringify(data, BufferJSON.replacer)) - ) + const mutex = getFileLock(filePath) + + return mutex.acquire().then(async(release) => { + try { + await writeFile(filePath, JSON.stringify(data, BufferJSON.replacer)) + } finally { + release() + } + }) } const readData = async(file: string) => { try { const filePath = join(folder, fixFileName(file)!) - const data = await fileLock.acquire( - filePath, - () => readFile(filePath, { encoding: 'utf-8' }) - ) - return JSON.parse(data, BufferJSON.reviver) + const mutex = getFileLock(filePath) + + return await mutex.acquire().then(async(release) => { + try { + const data = await readFile(filePath, { encoding: 'utf-8' }) + return JSON.parse(data, BufferJSON.reviver) + } finally { + release() + } + }) } catch(error) { return null } @@ -46,12 +66,17 @@ export const useMultiFileAuthState = async(folder: string): Promise<{ state: Aut const removeData = async(file: string) => { try { const filePath = join(folder, fixFileName(file)!) - await fileLock.acquire( - filePath, - () => unlink(filePath) - ) - } catch{ + const mutex = getFileLock(filePath) + return mutex.acquire().then(async(release) => { + try { + await unlink(filePath) + } catch{ + } finally { + release() + } + }) + } catch{ } } @@ -103,8 +128,8 @@ export const useMultiFileAuthState = async(folder: string): Promise<{ state: Aut } } }, - saveCreds: () => { + saveCreds: async() => { return writeData(creds, 'creds.json') } } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 47d7a09..a0c31df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1232,15 +1232,6 @@ dependencies: "@babel/types" "^7.20.7" -"@types/got@^9.6.11": - version "9.6.12" - resolved "https://registry.yarnpkg.com/@types/got/-/got-9.6.12.tgz#fd42a6e1f5f64cd6bb422279b08c30bb5a15a56f" - integrity sha512-X4pj/HGHbXVLqTpKjA2ahI4rV/nNBc9mGO2I/0CgAra+F2dKgMXnENv2SRpemScBzBAI4vMelIVYViQxlSE6xA== - dependencies: - "@types/node" "*" - "@types/tough-cookie" "*" - form-data "^2.5.0" - "@types/graceful-fs@^4.1.2": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -1329,13 +1320,6 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== -"@types/sharp@^0.29.4": - version "0.29.5" - resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.29.5.tgz#9c7032d30d138ad16dde6326beaff2af757b91b3" - integrity sha512-3TC+S3H5RwnJmLYMHrcdfNjz/CaApKmujjY9b6PU/pE6n0qfooi99YqXGWoW8frU9EWYj/XTI35Pzxa+ThAZ5Q== - dependencies: - "@types/node" "*" - "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" @@ -1682,11 +1666,6 @@ ast-types@^0.13.4: dependencies: tslib "^2.0.1" -async-lock@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" - integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== - async-mutex@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.5.0.tgz#353c69a0b9e75250971a64ac203b0ebfddd75482" @@ -2247,7 +2226,7 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" -combined-stream@^1.0.6, combined-stream@^1.0.8: +combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -3356,16 +3335,6 @@ form-data-encoder@^2.1.2: resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== -form-data@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.2.tgz#dc653743d1de2fcc340ceea38079daf6e9069fd2" - integrity sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - safe-buffer "^5.2.1" - form-data@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.2.tgz#83ad9ced7c03feaad97e293d6f6091011e1659c8" @@ -6410,7 +6379,7 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@^5.0.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -7373,11 +7342,6 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" - integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"