feat(dict) 分布式锁

This commit is contained in:
expressgy 2025-07-07 22:34:45 +08:00
parent cd49a78678
commit e8e352b6b6

View File

@ -13,6 +13,7 @@ import { sysDict } from '@/eneities';
import { eq, and, or, ne, desc, asc, sql, inArray, isNull, not, max } from 'drizzle-orm';
import { successResponse, BusinessError } from '@/utils/responseFormate';
import { nextId } from '@/utils/snowflake';
import { DistributedLockService } from '@/utils/distributedLock';
import type {
CreateDictRequest,
GetDictTreeByCodeRequest,
@ -43,6 +44,11 @@ export class DictService {
* @throws BusinessError
*/
public async createDict(body: CreateDictRequest): Promise<CreateDictSuccessType> {
const pid = body.pid || '0';
const lockKey = `dict:create:code:${body.code}:name:${body.name}:pid:${pid}`;
const lock = await DistributedLockService.acquire({ key: lockKey, ttl: 10 });
try {
// 1. code唯一性校验
const existCode = await db()
.select({ id: sysDict.id })
@ -54,7 +60,6 @@ export class DictService {
}
// 2. name同级唯一性校验
const pid = body.pid || '0';
const existName = await db()
.select({ id: sysDict.id })
.from(sysDict)
@ -143,6 +148,9 @@ export class DictService {
},
'创建字典项成功',
);
} finally {
await lock.release();
}
}
/**
@ -328,6 +336,8 @@ export class DictService {
* @returns Promise<UpdateDictSuccessType>
*/
public async updateDict(id: string, body: UpdateDictBodyRequest): Promise<UpdateDictSuccessType> {
const lock = await DistributedLockService.acquire({ key: `dict:update:${id}`, ttl: 10 });
try {
Logger.info(`更新字典项: ${id}, body: ${JSON.stringify(body)}`);
// 1. 检查字典项是否存在
@ -400,6 +410,9 @@ export class DictService {
},
'更新字典项成功',
);
} finally {
await lock.release();
}
}
/**
@ -410,6 +423,8 @@ export class DictService {
* @description 使SQL保证性能和类型安全
*/
public async sortDict(body: SortDictRequest): Promise<SortDictSuccessType> {
const lock = await DistributedLockService.acquire({ key: `dict:sort`, ttl: 30 });
try {
const { items } = body;
if (!items || items.length === 0) {
throw new BusinessError('排序项列表不能为空', 400);
@ -485,12 +500,14 @@ export class DictService {
if (error instanceof BusinessError) {
throw error;
}
Logger.error('字典项排序失败', { error });
throw new BusinessError('字典项排序失败,请稍后重试', 500);
}
Logger.info('字典项排序成功');
return successResponse(null, '字典项排序成功');
} finally {
await lock.release();
}
}
/**
@ -504,6 +521,8 @@ export class DictService {
id,
cascade,
}: DeleteDictRequest): Promise<DeleteDictSuccessType> {
const lock = await DistributedLockService.acquire({ key: `dict:delete:${id}`, ttl: 10 });
try {
const dictId = BigInt(id);
Logger.info(`请求删除字典项: ${dictId}, 是否级联: ${!!cascade}`);
@ -566,12 +585,14 @@ export class DictService {
if (error instanceof BusinessError) {
throw error;
}
Logger.error('字典项删除失败', { error });
throw new BusinessError('字典项删除失败,请稍后重试', 500);
}
Logger.info(`字典项 ${dictId} 及关联子项(如有)已成功软删除`);
return successResponse(null, '字典项删除成功');
} finally {
await lock.release();
}
}
/**