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