refactor(plugins): change to new lock manager to use locks

This commit is contained in:
mytharcher 2024-08-15 14:14:52 +00:00
parent 0935b898fb
commit c49c1704fd
7 changed files with 43 additions and 29 deletions

View File

@ -14,7 +14,6 @@
], ],
"devDependencies": { "devDependencies": {
"@types/jsonwebtoken": "^8.5.8", "@types/jsonwebtoken": "^8.5.8",
"async-mutex": "^0.5.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"

View File

@ -11,7 +11,6 @@ import { Context, utils as actionUtils } from '@nocobase/actions';
import { Cache } from '@nocobase/cache'; import { Cache } from '@nocobase/cache';
import { Collection, RelationField, Transaction } from '@nocobase/database'; import { Collection, RelationField, Transaction } from '@nocobase/database';
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import { Mutex } from 'async-mutex';
import lodash from 'lodash'; import lodash from 'lodash';
import { resolve } from 'path'; import { resolve } from 'path';
import { availableActionResource } from './actions/available-actions'; 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) => { 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 collectionName = model.get('collectionName');
const fieldName = model.get('name'); const fieldName = model.get('name');

View File

@ -14,7 +14,6 @@
"@formily/react": "2.x", "@formily/react": "2.x",
"@formily/shared": "2.x", "@formily/shared": "2.x",
"@types/node-xlsx": "^0.15.1", "@types/node-xlsx": "^0.15.1",
"async-mutex": "^0.5.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"node-xlsx": "^0.16.1", "node-xlsx": "^0.16.1",
"react": "^18.2.0", "react": "^18.2.0",

View File

@ -12,10 +12,9 @@ import { Repository } from '@nocobase/database';
import XlsxExporter from '../xlsx-exporter'; import XlsxExporter from '../xlsx-exporter';
import XLSX from 'xlsx'; import XLSX from 'xlsx';
import { Mutex } from 'async-mutex';
import { DataSource } from '@nocobase/data-source-manager'; import { DataSource } from '@nocobase/data-source-manager';
import PluginActionExportServer from '..';
const mutex = new Mutex(); import { LockAcquireError } from '@nocobase/lock-manager';
async function exportXlsxAction(ctx: Context, next: Next) { async function exportXlsxAction(ctx: Context, next: Next) {
const { title, filter, sort, fields, except } = ctx.action.params; 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) { export async function exportXlsx(ctx: Context, next: Next) {
if (mutex.isLocked()) { const plugin = ctx.app.pm.get(PluginActionExportServer) as PluginActionExportServer;
throw new Error( const { collection } = ctx.getCurrentRepository();
ctx.t(`another export action is running, please try again later.`, { const dataSource = ctx.dataSource as DataSource;
ns: 'action-export', 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 { try {
await exportXlsxAction(ctx, next); await exportXlsxAction(ctx, next);

View File

@ -11,10 +11,9 @@ import { Context, Next } from '@nocobase/actions';
import { Repository } from '@nocobase/database'; import { Repository } from '@nocobase/database';
import XLSX from 'xlsx'; import XLSX from 'xlsx';
import { XlsxImporter } from '../services/xlsx-importer'; import { XlsxImporter } from '../services/xlsx-importer';
import { Mutex } from 'async-mutex';
import { DataSource } from '@nocobase/data-source-manager'; import { DataSource } from '@nocobase/data-source-manager';
import PluginActionImportServer from '..';
const mutex = new Mutex(); import { LockAcquireError } from '@nocobase/lock-manager';
const IMPORT_LIMIT_COUNT = 2000; const IMPORT_LIMIT_COUNT = 2000;
@ -60,15 +59,24 @@ async function importXlsxAction(ctx: Context, next: Next) {
} }
export async function importXlsx(ctx: Context, next: Next) { export async function importXlsx(ctx: Context, next: Next) {
if (mutex.isLocked()) { const plugin = ctx.app.pm.get(PluginActionImportServer) as PluginActionImportServer;
throw new Error( const { collection } = ctx.getCurrentRepository();
ctx.t(`another import action is running, please try again later.`, { const dataSource = ctx.dataSource as DataSource;
ns: 'action-import', 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 { try {
await importXlsxAction(ctx, next); await importXlsxAction(ctx, next);

View File

@ -11,7 +11,6 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"devDependencies": { "devDependencies": {
"@hapi/topo": "^6.0.0", "@hapi/topo": "^6.0.0",
"async-mutex": "^0.5.0",
"toposort": "^2.0.2" "toposort": "^2.0.2"
}, },
"peerDependencies": { "peerDependencies": {

View File

@ -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', beforeDestoryField(this.app.db));
this.app.db.on('fields.beforeDestroy', beforeDestroyForeignKey(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) => { 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); await model.remove(options);
this.sendSyncMessage( this.sendSyncMessage(