修复 SQLite 钱包调账锁异常

This commit is contained in:
2026-07-22 15:03:06 +08:00
parent cd1996f281
commit 7ffc573d2e
2 changed files with 58 additions and 4 deletions

View File

@@ -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');
});
});

View File

@@ -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) {