将 WechatGame 单体模块拆分为独立的 User、Level、GameConfig 模块, 新增体力值系统、关卡闯关流程,并修复多项代码质量问题: - 体力不足错误码从 401 修正为 400 - enterLevel 改用 findById 替代全表扫描 - consumeStamina 增加原子更新防止并发竞态 - 并行化独立数据库查询 (Promise.all) - 移除 WechatGameService/Controller 死代码
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { User } from '../entities/user.entity';
|
|
import { IUserRepository } from './user.repository.interface';
|
|
|
|
@Injectable()
|
|
export class UserRepository implements IUserRepository {
|
|
constructor(
|
|
@InjectRepository(User)
|
|
private readonly repository: Repository<User>,
|
|
) {}
|
|
|
|
async findById(id: string): Promise<User | null> {
|
|
return this.repository.findOne({ where: { id } });
|
|
}
|
|
|
|
async findByOpenid(openid: string): Promise<User | null> {
|
|
return this.repository.findOne({ where: { openid } });
|
|
}
|
|
|
|
create(data: Partial<User>): User {
|
|
return this.repository.create(data);
|
|
}
|
|
|
|
async save(user: User): Promise<User> {
|
|
return this.repository.save(user);
|
|
}
|
|
|
|
/**
|
|
* 原子更新体力值,使用 WHERE 条件防止并发竞态。
|
|
* 只有当 stamina 仍等于 expectedOldStamina 时才更新。
|
|
*/
|
|
async updateStaminaAtomic(
|
|
userId: string,
|
|
expectedOldStamina: number,
|
|
newStamina: number,
|
|
staminaUpdatedAt: Date,
|
|
): Promise<{ affected: number }> {
|
|
const result = await this.repository.update(
|
|
{ id: userId, stamina: expectedOldStamina },
|
|
{ stamina: newStamina, staminaUpdatedAt },
|
|
);
|
|
return { affected: result.affected ?? 0 };
|
|
}
|
|
}
|