도커 서버를 5개로 늘린 이후 대시보드에 채점 결과가 업데이트 되지 않는 문제가 발생했다.
원인을 찾아 본 결과, 채점 서버에서 들어오는 요청을 처리하는데 비동기?벙렬?적으로 처리하는 바람에 문제가 발생한 것이다.
// 가져오기
const submission = await this.submissionRepository.findOneBy({
id: scoreResultDto.submissionId,
});
if (!submission) throw new NotFoundException('제출 기록이 없습니다.');
const result = {
testcaseId: scoreResultDto.testcaseId,
result: scoreResultDto.result,
timeUsage: scoreResultDto.timeUsage,
memoryUsage: scoreResultDto.memoryUsage,
};
submission.detail.push(result);
// 저장
await this.submissionRepository.save(submission);
채점 서버가 채점이 완료되면 api 서버에 요청을 보낸다.
api 서버는 요청을 받아 처리하는데, 각 요청을 개별적으로 처리한다. (https://stackoverflow.com/questions/58102508/concurrency-in-express?rq=3)
typeorm에서 save를 사용하여 데이터 수정을 하면, select와 update, 두 쿼리가 실행된다.
save → update로 수정해 주었다.
문제를 해결해주기 위해 트랜잭션 코드를 추가해 주었다.
let submission: Submission;
const result = {
testcaseId: scoreResultDto.testcaseId,
result: scoreResultDto.result,
timeUsage: scoreResultDto.timeUsage,
memoryUsage: scoreResultDto.memoryUsage,
};
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
submission = await queryRunner.manager.findOneBy(Submission, {
id: scoreResultDto.submissionId,
});
if (!submission) throw new NotFoundException('제출 기록이 없습니다.');
submission.detail.push(result);
await queryRunner.manager.update(Submission, submission.id, { detail: submission.detail });
await queryRunner.commitTransaction();
await queryRunner.release();
} catch (error) {
await queryRunner.rollbackTransaction();
await queryRunner.release();
throw error;
}