forked from wangziqi/gongxue-base
修复 SQLite 钱包调账锁异常
This commit is contained in:
@@ -117,3 +117,54 @@ describe('WalletsService financial boundaries', () => {
|
||||
expect(dataSource.transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('WalletsService wallet locking', () => {
|
||||
const createQueryManager = () => {
|
||||
const wallet = { id: 1, studentId: 10, balance: 0 };
|
||||
const query = {
|
||||
where: jest.fn(),
|
||||
setLock: jest.fn(),
|
||||
getOne: jest.fn(async () => wallet),
|
||||
};
|
||||
query.where.mockReturnValue(query);
|
||||
query.setLock.mockReturnValue(query);
|
||||
return {
|
||||
wallet,
|
||||
query,
|
||||
manager: {
|
||||
createQueryBuilder: jest.fn(() => query),
|
||||
findOne: jest.fn(),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
it('skips pessimistic locking for SQLite', async () => {
|
||||
const ctx = createQueryManager();
|
||||
const service = new WalletsService(
|
||||
{} as any,
|
||||
{} as any,
|
||||
{} as any,
|
||||
{ options: { type: 'better-sqlite3' } } as any,
|
||||
);
|
||||
|
||||
const result = await (service as any).getOrCreateWallet(ctx.manager, 10, true);
|
||||
|
||||
expect(result).toBe(ctx.wallet);
|
||||
expect(ctx.query.setLock).not.toHaveBeenCalled();
|
||||
expect(ctx.query.getOne).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('keeps pessimistic write locking for MySQL', async () => {
|
||||
const ctx = createQueryManager();
|
||||
const service = new WalletsService(
|
||||
{} as any,
|
||||
{} as any,
|
||||
{} as any,
|
||||
{ options: { type: 'mysql' } } as any,
|
||||
);
|
||||
|
||||
await (service as any).getOrCreateWallet(ctx.manager, 10, true);
|
||||
|
||||
expect(ctx.query.setLock).toHaveBeenCalledWith('pessimistic_write');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -259,10 +259,13 @@ export class WalletsService {
|
||||
if (!lock || !manager.createQueryBuilder) {
|
||||
return manager.findOne(StudentWallet, { where: { studentId } });
|
||||
}
|
||||
return manager.createQueryBuilder(StudentWallet, 'wallet')
|
||||
.where('wallet.studentId = :studentId', { studentId })
|
||||
.setLock('pessimistic_write')
|
||||
.getOne();
|
||||
let query = manager
|
||||
.createQueryBuilder(StudentWallet, 'wallet')
|
||||
.where('wallet.studentId = :studentId', { studentId });
|
||||
if (['mysql', 'mariadb', 'postgres', 'cockroachdb'].includes(this.dataSource.options.type)) {
|
||||
query = query.setLock('pessimistic_write');
|
||||
}
|
||||
return query.getOne();
|
||||
};
|
||||
let wallet = await find();
|
||||
if (!wallet) {
|
||||
|
||||
Reference in New Issue
Block a user