diff --git a/packages/plugins/@nocobase/plugin-acl/package.json b/packages/plugins/@nocobase/plugin-acl/package.json index ed02957a8e..11c82472d1 100644 --- a/packages/plugins/@nocobase/plugin-acl/package.json +++ b/packages/plugins/@nocobase/plugin-acl/package.json @@ -14,7 +14,6 @@ ], "devDependencies": { "@types/jsonwebtoken": "^8.5.8", - "async-mutex": "^0.5.0", "jsonwebtoken": "^8.5.1", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/packages/plugins/@nocobase/plugin-acl/src/server/server.ts b/packages/plugins/@nocobase/plugin-acl/src/server/server.ts index 37936e0a9e..97d486e37e 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/server/server.ts @@ -11,7 +11,6 @@ import { Context, utils as actionUtils } from '@nocobase/actions'; import { Cache } from '@nocobase/cache'; import { Collection, RelationField, Transaction } from '@nocobase/database'; import { Plugin } from '@nocobase/server'; -import { Mutex } from 'async-mutex'; import lodash from 'lodash'; import { resolve } from 'path'; import { availableActionResource } from './actions/available-actions'; @@ -275,10 +274,9 @@ export class PluginACLServer extends Plugin { } }); - const mutex = new Mutex(); - this.app.db.on('fields.afterDestroy', async (model, options) => { - await mutex.runExclusive(async () => { + const lockKey = `${this.name}:fields.afterDestroy:${model.get('collectionName')}:${model.get('name')}`; + await this.app.lockManager.runExclusive(lockKey, async () => { const collectionName = model.get('collectionName'); const fieldName = model.get('name'); diff --git a/packages/plugins/@nocobase/plugin-action-export/package.json b/packages/plugins/@nocobase/plugin-action-export/package.json index 85e9d7e1fc..db10d0cfd8 100644 --- a/packages/plugins/@nocobase/plugin-action-export/package.json +++ b/packages/plugins/@nocobase/plugin-action-export/package.json @@ -14,7 +14,6 @@ "@formily/react": "2.x", "@formily/shared": "2.x", "@types/node-xlsx": "^0.15.1", - "async-mutex": "^0.5.0", "file-saver": "^2.0.5", "node-xlsx": "^0.16.1", "react": "^18.2.0", diff --git a/packages/plugins/@nocobase/plugin-action-export/src/server/actions/export-xlsx.ts b/packages/plugins/@nocobase/plugin-action-export/src/server/actions/export-xlsx.ts index f37f94ea8a..81430e65aa 100644 --- a/packages/plugins/@nocobase/plugin-action-export/src/server/actions/export-xlsx.ts +++ b/packages/plugins/@nocobase/plugin-action-export/src/server/actions/export-xlsx.ts @@ -12,10 +12,9 @@ import { Repository } from '@nocobase/database'; import XlsxExporter from '../xlsx-exporter'; import XLSX from 'xlsx'; -import { Mutex } from 'async-mutex'; import { DataSource } from '@nocobase/data-source-manager'; - -const mutex = new Mutex(); +import PluginActionExportServer from '..'; +import { LockAcquireError } from '@nocobase/lock-manager'; async function exportXlsxAction(ctx: Context, next: Next) { const { title, filter, sort, fields, except } = ctx.action.params; @@ -53,15 +52,27 @@ async function exportXlsxAction(ctx: Context, next: Next) { } export async function exportXlsx(ctx: Context, next: Next) { - if (mutex.isLocked()) { - throw new Error( - ctx.t(`another export action is running, please try again later.`, { - ns: 'action-export', - }), - ); + const plugin = ctx.app.pm.get(PluginActionExportServer) as PluginActionExportServer; + const { collection } = ctx.getCurrentRepository(); + const dataSource = ctx.dataSource as DataSource; + const lockKey = `${plugin.name}:${dataSource.name}:${collection.name}`; + let lock; + try { + lock = ctx.app.lockManager.tryAcquire(lockKey); + } catch (error) { + if (error instanceof LockAcquireError) { + throw new Error( + ctx.t(`another export action is running, please try again later.`, { + ns: 'action-export', + }), + { + cause: error, + }, + ); + } } - const release = await mutex.acquire(); + const release = await lock.acquire(5000); try { await exportXlsxAction(ctx, next); diff --git a/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts b/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts index 80ecd19407..28f40122fa 100644 --- a/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts +++ b/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts @@ -11,10 +11,9 @@ import { Context, Next } from '@nocobase/actions'; import { Repository } from '@nocobase/database'; import XLSX from 'xlsx'; import { XlsxImporter } from '../services/xlsx-importer'; -import { Mutex } from 'async-mutex'; import { DataSource } from '@nocobase/data-source-manager'; - -const mutex = new Mutex(); +import PluginActionImportServer from '..'; +import { LockAcquireError } from '@nocobase/lock-manager'; const IMPORT_LIMIT_COUNT = 2000; @@ -60,15 +59,24 @@ async function importXlsxAction(ctx: Context, next: Next) { } export async function importXlsx(ctx: Context, next: Next) { - if (mutex.isLocked()) { - throw new Error( - ctx.t(`another import action is running, please try again later.`, { - ns: 'action-import', - }), - ); + const plugin = ctx.app.pm.get(PluginActionImportServer) as PluginActionImportServer; + const { collection } = ctx.getCurrentRepository(); + const dataSource = ctx.dataSource as DataSource; + const lockKey = `${plugin.name}:${dataSource.name}:${collection.name}`; + let lock; + try { + lock = ctx.app.lockManager.tryAcquire(lockKey); + } catch (error) { + if (error instanceof LockAcquireError) { + throw new Error( + ctx.t(`another import action is running, please try again later.`, { + ns: 'action-import', + }), + ); + } } - const release = await mutex.acquire(); + const release = await lock.acquire(5000); try { await importXlsxAction(ctx, next); diff --git a/packages/plugins/@nocobase/plugin-data-source-main/package.json b/packages/plugins/@nocobase/plugin-data-source-main/package.json index d02d57b39e..b781645d59 100644 --- a/packages/plugins/@nocobase/plugin-data-source-main/package.json +++ b/packages/plugins/@nocobase/plugin-data-source-main/package.json @@ -11,7 +11,6 @@ "license": "AGPL-3.0", "devDependencies": { "@hapi/topo": "^6.0.0", - "async-mutex": "^0.5.0", "toposort": "^2.0.2" }, "peerDependencies": { diff --git a/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts b/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts index acf95af08e..e2948e6c1c 100644 --- a/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts @@ -315,9 +315,9 @@ export class PluginDataSourceMainServer extends Plugin { this.app.db.on('fields.beforeDestroy', beforeDestoryField(this.app.db)); this.app.db.on('fields.beforeDestroy', beforeDestroyForeignKey(this.app.db)); - const mutex = new Mutex(); this.app.db.on('fields.beforeDestroy', async (model: FieldModel, options) => { - await mutex.runExclusive(async () => { + const lockKey = `${this.name}:fields.beforeDestroy:${model.get('collectionName')}:${model.get('name')}`; + await this.app.lockManager.runExclusive(lockKey, async () => { await model.remove(options); this.sendSyncMessage(